Bug 826657 part.3 nsTextStore should handle NOTIFY_IME_OF_MOUSE_BUTTON_EVENT r=emk

This commit is contained in:
Masayuki Nakano 2014-08-29 19:08:43 +09:00
parent 00abc24da1
commit 936e144f85
4 changed files with 232 additions and 0 deletions

View File

@ -173,6 +173,8 @@ IMEHandler::NotifyIME(nsWindow* aWindow,
case NOTIFY_IME_OF_BLUR:
return nsTextStore::OnFocusChange(false, aWindow,
aWindow->GetInputContext().mIMEState);
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
return nsTextStore::OnMouseButtonEvent(aIMENotification);
case REQUEST_TO_COMMIT_COMPOSITION:
if (nsTextStore::IsComposingOn(aWindow)) {
nsTextStore::CommitComposition(false);

View File

@ -612,6 +612,121 @@ GetDisplayAttrStr(const TF_DISPLAYATTRIBUTE &aDispAttr)
return str;
}
static const char*
GetEventMessageName(uint32_t aMessage)
{
switch (aMessage) {
case NS_MOUSE_BUTTON_DOWN:
return "NS_MOUSE_BUTTON_DOWN";
case NS_MOUSE_BUTTON_UP:
return "NS_MOUSE_BUTTON_UP";
default:
return "Unknown";
}
}
static const char*
GetMouseButtonName(int16_t aButton)
{
switch (aButton) {
case WidgetMouseEventBase::eLeftButton:
return "LeftButton";
case WidgetMouseEventBase::eMiddleButton:
return "MiddleButton";
case WidgetMouseEventBase::eRightButton:
return "RightButton";
default:
return "UnknownButton";
}
}
#define ADD_SEPARATOR_IF_NECESSARY(aStr) \
if (!aStr.IsEmpty()) { \
aStr.AppendLiteral(", "); \
}
static nsCString
GetMouseButtonsName(int16_t aButtons)
{
if (!aButtons) {
return NS_LITERAL_CSTRING("no buttons");
}
nsAutoCString names;
if (aButtons & WidgetMouseEventBase::eLeftButtonFlag) {
names = "LeftButton";
}
if (aButtons & WidgetMouseEventBase::eRightButtonFlag) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += "RightButton";
}
if (aButtons & WidgetMouseEventBase::eMiddleButtonFlag) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += "MiddleButton";
}
if (aButtons & WidgetMouseEventBase::e4thButtonFlag) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += "4thButton";
}
if (aButtons & WidgetMouseEventBase::e5thButtonFlag) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += "5thButton";
}
return names;
}
static nsCString
GetModifiersName(Modifiers aModifiers)
{
if (aModifiers == MODIFIER_NONE) {
return NS_LITERAL_CSTRING("no modifiers");
}
nsAutoCString names;
if (aModifiers & MODIFIER_ALT) {
names = NS_DOM_KEYNAME_ALT;
}
if (aModifiers & MODIFIER_ALTGRAPH) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_ALTGRAPH;
}
if (aModifiers & MODIFIER_CAPSLOCK) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_CAPSLOCK;
}
if (aModifiers & MODIFIER_CONTROL) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_CONTROL;
}
if (aModifiers & MODIFIER_FN) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_FN;
}
if (aModifiers & MODIFIER_META) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_META;
}
if (aModifiers & MODIFIER_NUMLOCK) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_NUMLOCK;
}
if (aModifiers & MODIFIER_SCROLLLOCK) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_SCROLLLOCK;
}
if (aModifiers & MODIFIER_SHIFT) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_SHIFT;
}
if (aModifiers & MODIFIER_SYMBOLLOCK) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_SYMBOLLOCK;
}
if (aModifiers & MODIFIER_OS) {
ADD_SEPARATOR_IF_NECESSARY(names);
names += NS_DOM_KEYNAME_OS;
}
return names;
}
#endif // #ifdef PR_LOGGING
nsTextStore::nsTextStore()
@ -3605,6 +3720,7 @@ nsTextStore::GetIMEUpdatePreference()
nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE |
nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE |
nsIMEUpdatePreference::NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR |
nsIMEUpdatePreference::NOTIFY_DURING_DEACTIVE);
// nsTextStore shouldn't notify TSF of selection change and text change
// which are caused by composition.
@ -3740,6 +3856,80 @@ nsTextStore::OnLayoutChangeInternal()
return NS_OK;
}
nsresult
nsTextStore::OnMouseButtonEventInternal(const IMENotification& aIMENotification)
{
if (mMouseTrackers.IsEmpty()) {
return NS_OK;
}
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: 0x%p nsTextStore::OnMouseButtonEventInternal("
"aIMENotification={ mEventMessage=%s, mOffset=%u, mCursorPos={ "
"mX=%d, mY=%d }, mCharRect={ mX=%d, mY=%d, mWidth=%d, mHeight=%d }, "
"mButton=%s, mButtons=%s, mModifiers=%s })",
this, GetEventMessageName(
aIMENotification.mMouseButtonEventData.mEventMessage),
aIMENotification.mMouseButtonEventData.mOffset,
aIMENotification.mMouseButtonEventData.mCursorPos.mX,
aIMENotification.mMouseButtonEventData.mCursorPos.mY,
aIMENotification.mMouseButtonEventData.mCharRect.mX,
aIMENotification.mMouseButtonEventData.mCharRect.mY,
aIMENotification.mMouseButtonEventData.mCharRect.mWidth,
aIMENotification.mMouseButtonEventData.mCharRect.mHeight,
GetMouseButtonName(aIMENotification.mMouseButtonEventData.mButton),
GetMouseButtonsName(
aIMENotification.mMouseButtonEventData.mButtons).get(),
GetModifiersName(
aIMENotification.mMouseButtonEventData.mModifiers).get()));
uint32_t offset = aIMENotification.mMouseButtonEventData.mOffset;
nsIntRect charRect =
aIMENotification.mMouseButtonEventData.mCharRect.AsIntRect();
nsIntPoint cursorPos =
aIMENotification.mMouseButtonEventData.mCursorPos.AsIntPoint();
ULONG quadrant = 1;
if (charRect.width > 0) {
int32_t cursorXInChar = cursorPos.x - charRect.x;
quadrant = cursorXInChar * 4 / charRect.width;
quadrant = (quadrant + 2) % 4;
}
ULONG edge = quadrant < 2 ? offset + 1 : offset;
DWORD buttonStatus = 0;
bool isMouseUp =
aIMENotification.mMouseButtonEventData.mEventMessage == NS_MOUSE_BUTTON_UP;
if (!isMouseUp) {
switch (aIMENotification.mMouseButtonEventData.mButton) {
case WidgetMouseEventBase::eLeftButton:
buttonStatus = MK_LBUTTON;
break;
case WidgetMouseEventBase::eMiddleButton:
buttonStatus = MK_MBUTTON;
break;
case WidgetMouseEventBase::eRightButton:
buttonStatus = MK_RBUTTON;
break;
}
}
if (aIMENotification.mMouseButtonEventData.mModifiers & MODIFIER_CONTROL) {
buttonStatus |= MK_CONTROL;
}
if (aIMENotification.mMouseButtonEventData.mModifiers & MODIFIER_SHIFT) {
buttonStatus |= MK_SHIFT;
}
for (size_t i = 0; i < mMouseTrackers.Length(); i++) {
MouseTracker& tracker = mMouseTrackers[i];
if (!tracker.IsUsing() || !tracker.InRange(offset)) {
continue;
}
if (tracker.OnMouseButtonEvent(edge - tracker.RangeStart(),
quadrant, buttonStatus)) {
return NS_SUCCESS_EVENT_CONSUMED;
}
}
return NS_OK;
}
void
nsTextStore::CreateNativeCaret()
{
@ -4641,6 +4831,24 @@ nsTextStore::MouseTracker::UnadviseSink()
mStart = mLength = -1;
}
bool
nsTextStore::MouseTracker::OnMouseButtonEvent(ULONG aEdge,
ULONG aQuadrant,
DWORD aButtonStatus)
{
MOZ_ASSERT(IsUsing(), "The caller must check before calling OnMouseEvent()");
BOOL eaten = FALSE;
HRESULT hr = mSink->OnMouseEvent(aEdge, aQuadrant, aButtonStatus, &eaten);
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: 0x%p nsTextStore::MouseTracker::OnMouseEvent(aEdge=%d, "
"aQuadrant=%d, aButtonStatus=0x%08X), hr=0x%08X, eaten=%s",
this, aEdge, aQuadrant, aButtonStatus, hr, GetBoolName(!!eaten)));
return SUCCEEDED(hr) && eaten;
}
#ifdef DEBUG
// static
bool

View File

@ -162,6 +162,14 @@ public:
return sTsfTextStore->OnLayoutChangeInternal();
}
static nsresult OnMouseButtonEvent(const IMENotification& aIMENotification)
{
if (NS_WARN_IF(!sTsfTextStore)) {
return NS_ERROR_NOT_AVAILABLE;
}
return sTsfTextStore->OnMouseButtonEventInternal(aIMENotification);
}
static nsIMEUpdatePreference GetIMEUpdatePreference();
// Returns the address of the pointer so that the TSF automatic test can
@ -274,6 +282,7 @@ protected:
void CommitCompositionInternal(bool);
nsresult OnTextChangeInternal(const IMENotification& aIMENotification);
nsresult OnSelectionChangeInternal(void);
nsresult OnMouseButtonEventInternal(const IMENotification& aIMENotification);
HRESULT GetDisplayAttribute(ITfProperty* aProperty,
ITfRange* aRange,
TF_DISPLAYATTRIBUTE* aResult);
@ -689,7 +698,18 @@ protected:
void UnadviseSink();
bool IsUsing() const { return mSink != nullptr; }
bool InRange(uint32_t aOffset) const
{
if (NS_WARN_IF(mStart < 0) ||
NS_WARN_IF(mLength <= 0)) {
return false;
}
return aOffset >= static_cast<uint32_t>(mStart) &&
aOffset < static_cast<uint32_t>(mStart + mLength);
}
DWORD Cookie() const { return mCookie; }
bool OnMouseButtonEvent(ULONG aEdge, ULONG aQuadrant, DWORD aButtonStatus);
LONG RangeStart() const { return mStart; }
private:
nsRefPtr<ITfMouseSink> mSink;

View File

@ -1579,6 +1579,8 @@ MetroWidget::NotifyIME(const IMENotification& aIMENotification)
return nsTextStore::OnTextChange(aIMENotification);
case NOTIFY_IME_OF_POSITION_CHANGE:
return nsTextStore::OnLayoutChange();
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
return nsTextStore::OnMouseButtonEvent(aIMENotification);
default:
return NS_ERROR_NOT_IMPLEMENTED;
}