Skip to content

Commit 3b47bee

Browse files
committed
Bug 907410 - Winrt async input - keyboard input. r=masayuki
1 parent de21a81 commit 3b47bee

File tree

8 files changed

+100
-5
lines changed

8 files changed

+100
-5
lines changed

widget/nsGUIEvent.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,8 @@ class nsKeyEvent : public nsInputEvent
11521152
keyCode(0), charCode(0),
11531153
location(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD), isChar(0),
11541154
mKeyNameIndex(mozilla::widget::KEY_NAME_INDEX_Unidentified),
1155-
mNativeKeyEvent(nullptr)
1155+
mNativeKeyEvent(nullptr),
1156+
mUniqueId(0)
11561157
{
11571158
}
11581159

@@ -1171,6 +1172,11 @@ class nsKeyEvent : public nsInputEvent
11711172
mozilla::widget::KeyNameIndex mKeyNameIndex;
11721173
// OS-specific native event can optionally be preserved
11731174
void* mNativeKeyEvent;
1175+
// Unique id associated with a keydown / keypress event. Used in identifing
1176+
// keypress events for removal from async event dispatch queue in metrofx
1177+
// after preventDefault is called on keydown events. It's ok if this wraps
1178+
// over long periods.
1179+
uint32_t mUniqueId;
11741180

11751181
void GetDOMKeyName(nsAString& aKeyName)
11761182
{
@@ -1205,6 +1211,7 @@ class nsKeyEvent : public nsInputEvent
12051211
// Don't copy mNativeKeyEvent because it may be referred after its instance
12061212
// is destroyed.
12071213
mNativeKeyEvent = nullptr;
1214+
mUniqueId = aEvent.mUniqueId;
12081215
}
12091216
};
12101217

widget/nsGUIEventIPC.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ struct ParamTraits<nsKeyEvent>
261261
WriteParam(aMsg, aParam.charCode);
262262
WriteParam(aMsg, aParam.isChar);
263263
WriteParam(aMsg, aParam.location);
264+
WriteParam(aMsg, aParam.mUniqueId);
264265
// An OS-specific native event might be attached in |mNativeKeyEvent|, but
265266
// that cannot be copied across process boundaries.
266267
}
@@ -273,7 +274,8 @@ struct ParamTraits<nsKeyEvent>
273274
ReadParam(aMsg, aIter, &aResult->keyCode) &&
274275
ReadParam(aMsg, aIter, &aResult->charCode) &&
275276
ReadParam(aMsg, aIter, &aResult->isChar) &&
276-
ReadParam(aMsg, aIter, &aResult->location))
277+
ReadParam(aMsg, aIter, &aResult->location) &&
278+
ReadParam(aMsg, aIter, &aResult->mUniqueId))
277279
{
278280
aResult->mKeyNameIndex = static_cast<mozilla::widget::KeyNameIndex>(keyNameIndex);
279281
aResult->mNativeKeyEvent = NULL;

widget/windows/KeyboardLayout.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
namespace mozilla {
4242
namespace widget {
4343

44+
// Unique id counter associated with a keydown / keypress events. Used in
45+
// identifing keypress events for removal from async event dispatch queue
46+
// in metrofx after preventDefault is called on keydown events.
47+
static uint32_t sUniqueKeyEventId = 0;
48+
4449
struct DeadKeyEntry
4550
{
4651
PRUnichar BaseChar;
@@ -756,6 +761,9 @@ NativeKey::InitKeyEvent(nsKeyEvent& aKeyEvent,
756761
switch (aKeyEvent.message) {
757762
case NS_KEY_DOWN:
758763
aKeyEvent.keyCode = mDOMKeyCode;
764+
// Unique id for this keydown event and its associated keypress.
765+
sUniqueKeyEventId++;
766+
aKeyEvent.mUniqueId = sUniqueKeyEventId;
759767
break;
760768
case NS_KEY_UP:
761769
aKeyEvent.keyCode = mDOMKeyCode;
@@ -768,6 +776,7 @@ NativeKey::InitKeyEvent(nsKeyEvent& aKeyEvent,
768776
(mOriginalVirtualKeyCode == VK_MENU && mMsg.message != WM_SYSKEYUP);
769777
break;
770778
case NS_KEY_PRESS:
779+
aKeyEvent.mUniqueId = sUniqueKeyEventId;
771780
break;
772781
default:
773782
MOZ_CRASH("Invalid event message");
@@ -797,7 +806,7 @@ NativeKey::DispatchKeyEvent(nsKeyEvent& aKeyEvent,
797806
aKeyEvent.pluginEvent = static_cast<void*>(&pluginEvent);
798807
}
799808

800-
return (mWidget->DispatchWindowEvent(&aKeyEvent) || mWidget->Destroyed());
809+
return (mWidget->DispatchKeyboardEvent(&aKeyEvent) || mWidget->Destroyed());
801810
}
802811

803812
bool

widget/windows/nsWindow.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3662,6 +3662,13 @@ bool nsWindow::DispatchStandardEvent(uint32_t aMsg)
36623662
return result;
36633663
}
36643664

3665+
bool nsWindow::DispatchKeyboardEvent(nsGUIEvent* event)
3666+
{
3667+
nsEventStatus status;
3668+
DispatchEvent(event, status);
3669+
return ConvertStatus(status);
3670+
}
3671+
36653672
bool nsWindow::DispatchWindowEvent(nsGUIEvent* event)
36663673
{
36673674
nsEventStatus status;

widget/windows/nsWindow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class nsWindow : public nsWindowBase
8787
// nsWindowBase
8888
virtual void InitEvent(nsGUIEvent& aEvent, nsIntPoint* aPoint = nullptr) MOZ_OVERRIDE;
8989
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
90+
virtual bool DispatchKeyboardEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
9091
virtual nsWindowBase* GetParentWindowBase(bool aIncludeOwner) MOZ_OVERRIDE;
9192
virtual bool IsTopLevelWidget() MOZ_OVERRIDE { return mIsTopWidgetWindow; }
9293

widget/windows/nsWindowBase.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,16 @@ class nsWindowBase : public nsBaseWidget
4949
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) = 0;
5050

5151
/*
52-
* Dispatch a plugin event with the message.
52+
* Dispatch a gecko keyboard event for this widget. This
53+
* is called by KeyboardLayout to dispatch gecko events.
54+
* Returns true if it's consumed. Otherwise, false.
55+
*/
56+
virtual bool DispatchKeyboardEvent(nsGUIEvent* aEvent) = 0;
57+
58+
/*
59+
* Default dispatch of a plugin event.
5360
*/
54-
virtual bool DispatchPluginEvent(const MSG &aMsg) MOZ_FINAL
61+
virtual bool DispatchPluginEvent(const MSG &aMsg)
5562
{
5663
if (!PluginHasFocus()) {
5764
return false;

widget/windows/winrt/MetroWidget.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,61 @@ MetroWidget::DeliverNextScrollEvent()
625625
delete msg;
626626
}
627627

628+
// defined in nsWiondowBase, called from shared module KeyboardLayout.
629+
bool
630+
MetroWidget::DispatchKeyboardEvent(nsGUIEvent* aEvent)
631+
{
632+
MOZ_ASSERT(aEvent);
633+
nsKeyEvent* oldKeyEvent = static_cast<nsKeyEvent*>(aEvent);
634+
nsKeyEvent* keyEvent =
635+
new nsKeyEvent(oldKeyEvent->mFlags.mIsTrusted, oldKeyEvent->message, oldKeyEvent->widget);
636+
// XXX note this leaves pluginEvent null, which is fine for now.
637+
keyEvent->AssignKeyEventData(*oldKeyEvent, true);
638+
mKeyEventQueue.Push(keyEvent);
639+
nsCOMPtr<nsIRunnable> runnable =
640+
NS_NewRunnableMethod(this, &MetroWidget::DeliverNextKeyboardEvent);
641+
NS_DispatchToCurrentThread(runnable);
642+
return false;
643+
}
644+
645+
// Used in conjunction with mKeyEventQueue to find a keypress event
646+
// that should not be delivered due to the return result of the
647+
// preceeding keydown.
648+
class KeyQueryIdAndCancel : public nsDequeFunctor {
649+
public:
650+
KeyQueryIdAndCancel(uint32_t aIdToCancel) :
651+
mId(aIdToCancel) {
652+
}
653+
virtual void* operator() (void* aObject) {
654+
nsKeyEvent* event = static_cast<nsKeyEvent*>(aObject);
655+
if (event->mUniqueId == mId) {
656+
event->mFlags.mPropagationStopped = true;
657+
}
658+
return nullptr;
659+
}
660+
protected:
661+
uint32_t mId;
662+
};
663+
664+
void
665+
MetroWidget::DeliverNextKeyboardEvent()
666+
{
667+
nsKeyEvent* event = static_cast<nsKeyEvent*>(mKeyEventQueue.PopFront());
668+
if (event->mFlags.mPropagationStopped) {
669+
// This can happen if a keypress was previously cancelled.
670+
delete event;
671+
return;
672+
}
673+
674+
if (DispatchWindowEvent(event) && event->message == NS_KEY_DOWN) {
675+
// keydown events may be followed by multiple keypress events which
676+
// shouldn't be sent if preventDefault is called on keydown.
677+
KeyQueryIdAndCancel query(event->mUniqueId);
678+
mKeyEventQueue.ForEach(query);
679+
}
680+
delete event;
681+
}
682+
628683
// static
629684
LRESULT CALLBACK
630685
MetroWidget::StaticWindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam)
@@ -691,6 +746,9 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
691746
break;
692747
}
693748

749+
// Keyboard handling is passed to KeyboardLayout, which delivers gecko events
750+
// via DispatchKeyboardEvent.
751+
694752
case WM_KEYDOWN:
695753
case WM_SYSKEYDOWN:
696754
{

widget/windows/winrt/MetroWidget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class MetroWidget : public nsWindowBase,
7575

7676
// nsWindowBase
7777
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
78+
virtual bool DispatchKeyboardEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
79+
virtual bool DispatchPluginEvent(const MSG &aMsg) MOZ_OVERRIDE { return false; }
7880
virtual bool IsTopLevelWidget() MOZ_OVERRIDE { return true; }
7981
virtual nsWindowBase* GetParentWindowBase(bool aIncludeOwner) MOZ_OVERRIDE { return nullptr; }
8082
// InitEvent assumes physical coordinates and is used by shared win32 code. Do
@@ -253,9 +255,11 @@ class MetroWidget : public nsWindowBase,
253255
// Async event dispatching
254256
void DispatchAsyncScrollEvent(DispatchMsg* aEvent);
255257
void DeliverNextScrollEvent();
258+
void DeliverNextKeyboardEvent();
256259
DispatchMsg* CreateDispatchMsg(UINT aMsg, WPARAM aWParam, LPARAM aLParam);
257260

258261
nsDeque mMsgEventQueue;
262+
nsDeque mKeyEventQueue;
259263

260264
public:
261265
static nsRefPtr<mozilla::layers::APZCTreeManager> sAPZC;

0 commit comments

Comments
 (0)