Bug 865561 Dispatch key events when WM_APPCOMMAND is fired for a keypress r=jimm+smaug

This commit is contained in:
Masayuki Nakano 2014-12-30 10:47:56 +09:00
parent f840763cec
commit 7fd8ddebc2
7 changed files with 440 additions and 186 deletions

View File

@ -20,6 +20,7 @@
#define KEY_MAP_WIN_JPN(aCPPKeyName, aNativeKey)
#define KEY_MAP_WIN_KOR(aCPPKeyName, aNativeKey)
#define KEY_MAP_WIN_OTH(aCPPKeyName, aNativeKey)
#define KEY_MAP_WIN_CMD(aCPPKeyName, aAppCommand)
// Mac OS X
#define KEY_MAP_COCOA(aCPPKeyName, aNativeKey)
// GTK
@ -30,28 +31,41 @@
#define KEY_MAP_ANDROID(aCPPKeyName, aNativeKey)
#if defined(XP_WIN)
#if defined(NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX)
// KEY_MAP_WIN() defines the mapping not depending on keyboard layout.
#undef KEY_MAP_WIN
#define KEY_MAP_WIN(aCPPKeyName, aNativeKey) \
NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, KEY_NAME_INDEX_##aCPPKeyName)
#elif defined(NS_JAPANESE_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX)
// KEY_MAP_WIN_JPN() defines the mapping which is valid only with Japanese
// keyboard layout.
#undef KEY_MAP_WIN_JPN
#define KEY_MAP_WIN_JPN(aCPPKeyName, aNativeKey) \
NS_JAPANESE_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, \
KEY_NAME_INDEX_##aCPPKeyName)
#elif defined(NS_KOREAN_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX)
// KEY_MAP_WIN_KOR() defines the mapping which is valid only with Korean
// keyboard layout.
#undef KEY_MAP_WIN_KOR
#define KEY_MAP_WIN_KOR(aCPPKeyName, aNativeKey) \
NS_KOREAN_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, \
KEY_NAME_INDEX_##aCPPKeyName)
#elif defined(NS_OTHER_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX)
// KEY_MAP_WIN_OTH() defines the mapping which is valid with neither
// Japanese keyboard layout nor Korean keyboard layout.
#undef KEY_MAP_WIN_OTH
#define KEY_MAP_WIN_OTH(aCPPKeyName, aNativeKey) \
NS_OTHER_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, \
KEY_NAME_INDEX_##aCPPKeyName)
#elif defined(NS_APPCOMMAND_TO_DOM_KEY_NAME_INDEX)
// KEY_MAP_WIN_CMD() defines the mapping from APPCOMMAND_* of WM_APPCOMMAND.
#undef KEY_MAP_WIN_CMD
#define KEY_MAP_WIN_CMD(aCPPKeyName, aAppCommand) \
NS_APPCOMMAND_TO_DOM_KEY_NAME_INDEX(aAppCommand, \
KEY_NAME_INDEX_##aCPPKeyName)
#else
#error Any NS_*_TO_DOM_KEY_NAME_INDEX() is not defined.
#endif // #if defined(NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX) ...
#elif defined(XP_MACOSX)
#undef KEY_MAP_COCOA
#define KEY_MAP_COCOA(aCPPKeyName, aNativeKey) \
@ -319,13 +333,16 @@ KEY_MAP_QT (Insert, Qt::Key_Insert)
KEY_MAP_ANDROID (Insert, AKEYCODE_INSERT)
// Paste
KEY_MAP_WIN_CMD (Paste, APPCOMMAND_PASTE)
KEY_MAP_GTK (Paste, GDK_Paste)
KEY_MAP_QT (Paste, Qt::Key_Paste)
// Redo
KEY_MAP_WIN_CMD (Redo, APPCOMMAND_REDO)
KEY_MAP_GTK (Redo, GDK_Redo)
// Undo
KEY_MAP_WIN_CMD (Undo, APPCOMMAND_UNDO)
KEY_MAP_GTK (Undo, GDK_Undo)
/******************************************************************************
@ -364,10 +381,12 @@ KEY_MAP_GTK (Execute, GDK_Execute)
KEY_MAP_QT (Execute, Qt::Key_Execute)
// Find
KEY_MAP_WIN_CMD (Find, APPCOMMAND_FIND)
KEY_MAP_GTK (Find, GDK_Find)
// Help
KEY_MAP_WIN (Help, VK_HELP)
KEY_MAP_WIN_CMD (Help, APPCOMMAND_HELP)
KEY_MAP_COCOA (Help, kVK_Help)
KEY_MAP_GTK (Help, GDK_Help)
KEY_MAP_QT (Help, Qt::Key_Help)
@ -867,67 +886,82 @@ KEY_MAP_QT (F35, Qt::Key_F35)
// Close
// NOTE: This is not a key to close disk tray, this is a key to close document
// or window.
KEY_MAP_WIN_CMD (Close, APPCOMMAND_CLOSE)
KEY_MAP_GTK (Close, GDK_Close)
KEY_MAP_QT (Close, Qt::Key_Close)
// MailForward
KEY_MAP_WIN_CMD (MailForward, APPCOMMAND_FORWARD_MAIL)
KEY_MAP_GTK (MailForward, GDK_MailForward)
KEY_MAP_QT (MailForward, Qt::Key_MailForward)
// MailReply
KEY_MAP_WIN_CMD (MailReply, APPCOMMAND_REPLY_TO_MAIL)
KEY_MAP_GTK (MailReply, GDK_Reply)
KEY_MAP_QT (MailReply, Qt::Key_Reply)
// MailSend
KEY_MAP_WIN_CMD (MailSend, APPCOMMAND_SEND_MAIL)
KEY_MAP_GTK (MailSend, GDK_Send)
KEY_MAP_QT (MailSend, Qt::Key_Send)
// MediaPlayPause
KEY_MAP_WIN (MediaPlayPause, VK_MEDIA_PLAY_PAUSE)
KEY_MAP_WIN_CMD (MediaPlayPause, APPCOMMAND_MEDIA_PLAY_PAUSE)
KEY_MAP_QT (MediaPlayPause, Qt::Key_MediaTogglePlayPause)
KEY_MAP_ANDROID (MediaPlayPause, AKEYCODE_MEDIA_PLAY_PAUSE)
// MediaSelect
KEY_MAP_WIN (MediaSelect, VK_LAUNCH_MEDIA_SELECT)
KEY_MAP_WIN_CMD (MediaSelect, APPCOMMAND_LAUNCH_MEDIA_SELECT)
KEY_MAP_GTK (MediaSelect, GDK_AudioMedia)
// MediaStop
KEY_MAP_WIN (MediaStop, VK_MEDIA_STOP)
KEY_MAP_WIN_CMD (MediaStop, APPCOMMAND_MEDIA_STOP)
KEY_MAP_GTK (MediaStop, GDK_AudioStop)
KEY_MAP_QT (MediaStop, Qt::Key_MediaStop)
KEY_MAP_ANDROID (MediaStop, AKEYCODE_MEDIA_STOP)
// MediaTrackNext
KEY_MAP_WIN (MediaTrackNext, VK_MEDIA_NEXT_TRACK)
KEY_MAP_WIN_CMD (MediaTrackNext, APPCOMMAND_MEDIA_NEXTTRACK)
KEY_MAP_GTK (MediaTrackNext, GDK_AudioNext)
KEY_MAP_QT (MediaTrackNext, Qt::Key_MediaNext)
KEY_MAP_ANDROID (MediaTrackNext, AKEYCODE_MEDIA_NEXT)
// MediaTrackPrevious
KEY_MAP_WIN (MediaTrackPrevious, VK_MEDIA_PREV_TRACK)
KEY_MAP_WIN_CMD (MediaTrackPrevious, APPCOMMAND_MEDIA_PREVIOUSTRACK)
KEY_MAP_GTK (MediaTrackPrevious, GDK_AudioPrev)
KEY_MAP_QT (MediaTrackPrevious, Qt::Key_MediaPrevious)
KEY_MAP_ANDROID (MediaTrackPrevious, AKEYCODE_MEDIA_PREVIOUS)
// New
KEY_MAP_WIN_CMD (New, APPCOMMAND_NEW)
KEY_MAP_GTK (New, GDK_New)
// Open
KEY_MAP_WIN_CMD (Open, APPCOMMAND_OPEN)
KEY_MAP_GTK (Open, GDK_Open)
// Print
KEY_MAP_WIN_CMD (Print, APPCOMMAND_PRINT)
KEY_MAP_QT (Print, Qt::Key_Printer)
// Save
KEY_MAP_WIN_CMD (Save, APPCOMMAND_SAVE)
KEY_MAP_GTK (Save, GDK_Save)
KEY_MAP_QT (Save, Qt::Key_Save)
// SpellCheck
KEY_MAP_WIN_CMD (SpellCheck, APPCOMMAND_SPELL_CHECK)
KEY_MAP_GTK (SpellCheck, GDK_Spell)
KEY_MAP_QT (SpellCheck, Qt::Key_Spell)
// VolumeDown
KEY_MAP_WIN (VolumeDown, VK_VOLUME_DOWN)
KEY_MAP_WIN_CMD (VolumeDown, APPCOMMAND_VOLUME_DOWN)
KEY_MAP_COCOA (VolumeDown, kVK_VolumeDown)
KEY_MAP_GTK (VolumeDown, GDK_AudioLowerVolume)
KEY_MAP_QT (VolumeDown, Qt::Key_VolumeDown)
@ -935,6 +969,7 @@ KEY_MAP_ANDROID (VolumeDown, AKEYCODE_VOLUME_DOWN)
// VolumeUp
KEY_MAP_WIN (VolumeUp, VK_VOLUME_UP)
KEY_MAP_WIN_CMD (VolumeUp, APPCOMMAND_VOLUME_UP)
KEY_MAP_COCOA (VolumeUp, kVK_VolumeUp)
KEY_MAP_GTK (VolumeUp, GDK_AudioRaiseVolume)
KEY_MAP_QT (VolumeUp, Qt::Key_VolumeUp)
@ -942,6 +977,7 @@ KEY_MAP_ANDROID (VolumeUp, AKEYCODE_VOLUME_UP)
// VolumeMute
KEY_MAP_WIN (VolumeMute, VK_VOLUME_MUTE)
KEY_MAP_WIN_CMD (VolumeMute, APPCOMMAND_VOLUME_MUTE)
KEY_MAP_COCOA (VolumeMute, kVK_Mute)
KEY_MAP_GTK (VolumeMute, GDK_AudioMute)
KEY_MAP_QT (VolumeMute, Qt::Key_VolumeMute)
@ -962,6 +998,7 @@ KEY_MAP_ANDROID (LaunchCalendar, AKEYCODE_CALENDAR)
// LaunchMail
KEY_MAP_WIN (LaunchMail, VK_LAUNCH_MAIL)
KEY_MAP_WIN_CMD (LaunchMail, APPCOMMAND_LAUNCH_MAIL)
KEY_MAP_GTK (LaunchMail, GDK_Mail)
KEY_MAP_QT (LaunchMail, Qt::Key_LaunchMail)
KEY_MAP_ANDROID (LaunchMail, AKEYCODE_ENVELOPE)
@ -1008,11 +1045,13 @@ KEY_MAP_QT (LaunchWordProcessor, Qt::Key_Word)
// LaunchApplication1
KEY_MAP_WIN (LaunchApplication1, VK_LAUNCH_APP1)
KEY_MAP_WIN_CMD (LaunchApplication1, APPCOMMAND_LAUNCH_APP1)
KEY_MAP_GTK (LaunchApplication1, GDK_Launch0)
KEY_MAP_QT (LaunchApplication1, Qt::Key_Launch0)
// LaunchApplication2
KEY_MAP_WIN (LaunchApplication2, VK_LAUNCH_APP2)
KEY_MAP_WIN_CMD (LaunchApplication2, APPCOMMAND_LAUNCH_APP2)
KEY_MAP_GTK (LaunchApplication2, GDK_Launch1)
KEY_MAP_QT (LaunchApplication2, Qt::Key_Launch1)
@ -1083,28 +1122,33 @@ KEY_MAP_QT (LaunchApplication18, Qt::Key_LaunchH)
******************************************************************************/
// BrowserBack
KEY_MAP_WIN (BrowserBack, VK_BROWSER_BACK)
KEY_MAP_WIN_CMD (BrowserBack, APPCOMMAND_BROWSER_BACKWARD)
KEY_MAP_GTK (BrowserBack, GDK_Back)
KEY_MAP_QT (BrowserBack, Qt::Key_Back)
KEY_MAP_ANDROID (BrowserBack, AKEYCODE_BACK)
// BrowserFavorites
KEY_MAP_WIN (BrowserFavorites, VK_BROWSER_FAVORITES)
KEY_MAP_WIN_CMD (BrowserFavorites, APPCOMMAND_BROWSER_FAVORITES)
KEY_MAP_QT (BrowserFavorites, Qt::Key_Favorites)
KEY_MAP_ANDROID (BrowserFavorites, AKEYCODE_BOOKMARK)
// BrowserForward
KEY_MAP_WIN (BrowserForward, VK_BROWSER_FORWARD)
KEY_MAP_WIN_CMD (BrowserForward, APPCOMMAND_BROWSER_FORWARD)
KEY_MAP_GTK (BrowserForward, GDK_Forward)
KEY_MAP_QT (BrowserForward, Qt::Key_Forward)
KEY_MAP_ANDROID (BrowserForward, AKEYCODE_FORWARD)
// BrowserHome
KEY_MAP_WIN (BrowserHome, VK_BROWSER_HOME)
KEY_MAP_WIN_CMD (BrowserHome, APPCOMMAND_BROWSER_HOME)
KEY_MAP_GTK (BrowserHome, GDK_HomePage)
KEY_MAP_QT (BrowserHome, Qt::Key_HomePage)
// BrowserRefresh
KEY_MAP_WIN (BrowserRefresh, VK_BROWSER_REFRESH)
KEY_MAP_WIN_CMD (BrowserRefresh, APPCOMMAND_BROWSER_REFRESH)
KEY_MAP_GTK (BrowserRefresh, GDK_Refresh)
KEY_MAP_GTK (BrowserRefresh, GDK_Reload)
KEY_MAP_QT (BrowserRefresh, Qt::Key_Refresh)
@ -1112,12 +1156,14 @@ KEY_MAP_QT (BrowserRefresh, Qt::Key_Reload)
// BrowserSearch
KEY_MAP_WIN (BrowserSearch, VK_BROWSER_SEARCH)
KEY_MAP_WIN_CMD (BrowserSearch, APPCOMMAND_BROWSER_SEARCH)
KEY_MAP_GTK (BrowserSearch, GDK_Search)
KEY_MAP_QT (BrowserSearch, Qt::Key_Search)
KEY_MAP_ANDROID (BrowserSearch, AKEYCODE_SEARCH)
// BrowserStop
KEY_MAP_WIN (BrowserStop, VK_BROWSER_STOP)
KEY_MAP_WIN_CMD (BrowserStop, APPCOMMAND_BROWSER_STOP)
KEY_MAP_GTK (BrowserStop, GDK_Stop)
KEY_MAP_QT (BrowserStop, Qt::Key_Stop)
@ -1125,9 +1171,11 @@ KEY_MAP_QT (BrowserStop, Qt::Key_Stop)
* Media Controller Keys
******************************************************************************/
// AudioBassBoostDown
KEY_MAP_WIN_CMD (AudioBassBoostDown, APPCOMMAND_BASS_DOWN)
KEY_MAP_QT (AudioBassBoostDown, Qt::Key_BassDown)
// AudioBassBoostUp
KEY_MAP_WIN_CMD (AudioBassBoostUp, APPCOMMAND_BASS_UP)
KEY_MAP_QT (AudioBassBoostUp, Qt::Key_BassUp)
// AVRInput
@ -1180,21 +1228,25 @@ KEY_MAP_ANDROID (MediaFastForward, AKEYCODE_MEDIA_FAST_FORWARD)
KEY_MAP_QT (MediaLast, Qt::Key_MediaLast)
// MediaPause
KEY_MAP_WIN_CMD (MediaPause, APPCOMMAND_MEDIA_PAUSE)
KEY_MAP_GTK (MediaPause, GDK_AudioPause)
KEY_MAP_QT (MediaPause, Qt::Key_MediaPause)
KEY_MAP_ANDROID (MediaPause, AKEYCODE_MEDIA_PAUSE)
// MediaPlay
KEY_MAP_WIN_CMD (MediaPlay, APPCOMMAND_MEDIA_PLAY)
KEY_MAP_GTK (MediaPlay, GDK_AudioPlay)
KEY_MAP_QT (MediaPlay, Qt::Key_MediaPlay)
KEY_MAP_ANDROID (MediaPlay, AKEYCODE_MEDIA_PLAY)
// MediaRecord
KEY_MAP_WIN_CMD (MediaRecord, APPCOMMAND_MEDIA_RECORD)
KEY_MAP_GTK (MediaRecord, GDK_AudioRecord)
KEY_MAP_QT (MediaRecord, Qt::Key_MediaRecord)
KEY_MAP_ANDROID (MediaRecord, AKEYCODE_MEDIA_RECORD)
// MediaRewind
KEY_MAP_WIN_CMD (MediaRewind, APPCOMMAND_MEDIA_REWIND)
KEY_MAP_GTK (MediaRewind, GDK_AudioRewind)
KEY_MAP_QT (MediaRewind, Qt::Key_AudioRewind)
KEY_MAP_ANDROID (MediaRewind, AKEYCODE_MEDIA_REWIND)
@ -1240,6 +1292,7 @@ KEY_MAP_QT (ZoomToggle, Qt::Key_Zoom)
#undef KEY_MAP_WIN_JPN
#undef KEY_MAP_WIN_KOR
#undef KEY_MAP_WIN_OTH
#undef KEY_MAP_WIN_CMD
#undef KEY_MAP_COCOA
#undef KEY_MAP_GTK
#undef KEY_MAP_QT

View File

@ -8,29 +8,29 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/MiscEvents.h"
#include "mozilla/TextEvents.h"
#include "mozilla/WindowsVersion.h"
#include "KeyboardLayout.h"
#include "nsIMM32Handler.h"
#include "nsMemory.h"
#include "nsToolkit.h"
#include "nsQuickSort.h"
#include "nsAlgorithm.h"
#include "nsUnicharUtils.h"
#include "WidgetUtils.h"
#include "WinUtils.h"
#include "nsWindowDbg.h"
#include "nsServiceManagerUtils.h"
#include "nsPrintfCString.h"
#include "nsIDOMKeyEvent.h"
#include "nsIIdleServiceInternal.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#include "nsGkAtoms.h"
#include "nsIDOMKeyEvent.h"
#include "nsIIdleServiceInternal.h"
#include "nsIMM32Handler.h"
#include "nsMemory.h"
#include "nsPrintfCString.h"
#include "nsQuickSort.h"
#include "nsServiceManagerUtils.h"
#include "nsToolkit.h"
#include "nsUnicharUtils.h"
#include "nsWindowDbg.h"
#include "KeyboardLayout.h"
#include "WidgetUtils.h"
#include "WinUtils.h"
#include "npapi.h"
@ -669,18 +669,35 @@ VirtualKey::FillKbdState(PBYTE aKbdState,
* mozilla::widget::NativeKey
*****************************************************************************/
uint8_t NativeKey::sDispatchedKeyOfAppCommand = 0;
NativeKey::NativeKey(nsWindowBase* aWidget,
const MSG& aKeyOrCharMessage,
const MSG& aMessage,
const ModifierKeyState& aModKeyState,
nsTArray<FakeCharMsg>* aFakeCharMsgs) :
mWidget(aWidget), mMsg(aKeyOrCharMessage), mDOMKeyCode(0),
mModKeyState(aModKeyState), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0),
mFakeCharMsgs(aFakeCharMsgs && aFakeCharMsgs->Length() ?
aFakeCharMsgs : nullptr)
nsTArray<FakeCharMsg>* aFakeCharMsgs)
: mWidget(aWidget)
, mMsg(aMessage)
, mDOMKeyCode(0)
, mKeyNameIndex(KEY_NAME_INDEX_Unidentified)
, mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
, mModKeyState(aModKeyState)
, mVirtualKeyCode(0)
, mOriginalVirtualKeyCode(0)
, mScanCode(0)
, mIsExtended(false)
, mIsDeadKey(false)
, mFakeCharMsgs(aFakeCharMsgs && aFakeCharMsgs->Length() ?
aFakeCharMsgs : nullptr)
{
MOZ_ASSERT(aWidget);
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
mKeyboardLayout = keyboardLayout->GetLayout();
if (mMsg.message == WM_APPCOMMAND) {
InitWithAppCommand();
return;
}
mScanCode = WinUtils::GetScanCode(mMsg.lParam);
mIsExtended = WinUtils::IsExtendedScanCode(mMsg.lParam);
switch (mMsg.message) {
@ -855,6 +872,102 @@ NativeKey::NativeKey(nsWindowBase* aWidget,
mIsPrintableKey = KeyboardLayout::IsPrintableCharKey(mOriginalVirtualKeyCode);
}
void
NativeKey::InitWithAppCommand()
{
if (GET_DEVICE_LPARAM(mMsg.lParam) != FAPPCOMMAND_KEY) {
return;
}
uint32_t appCommand = GET_APPCOMMAND_LPARAM(mMsg.lParam);
switch (GET_APPCOMMAND_LPARAM(mMsg.lParam)) {
#undef NS_APPCOMMAND_TO_DOM_KEY_NAME_INDEX
#define NS_APPCOMMAND_TO_DOM_KEY_NAME_INDEX(aAppCommand, aKeyNameIndex) \
case aAppCommand: \
mKeyNameIndex = aKeyNameIndex; \
break;
#include "NativeKeyToDOMKeyName.h"
#undef NS_APPCOMMAND_TO_DOM_KEY_NAME_INDEX
default:
mKeyNameIndex = KEY_NAME_INDEX_Unidentified;
}
// Guess the virtual keycode which caused this message.
switch (appCommand) {
case APPCOMMAND_BROWSER_BACKWARD:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_BROWSER_BACK;
break;
case APPCOMMAND_BROWSER_FORWARD:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_BROWSER_FORWARD;
break;
case APPCOMMAND_BROWSER_REFRESH:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_BROWSER_REFRESH;
break;
case APPCOMMAND_BROWSER_STOP:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_BROWSER_STOP;
break;
case APPCOMMAND_BROWSER_SEARCH:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_BROWSER_SEARCH;
break;
case APPCOMMAND_BROWSER_FAVORITES:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_BROWSER_FAVORITES;
break;
case APPCOMMAND_BROWSER_HOME:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_BROWSER_HOME;
break;
case APPCOMMAND_VOLUME_MUTE:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_VOLUME_MUTE;
break;
case APPCOMMAND_VOLUME_DOWN:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_VOLUME_DOWN;
break;
case APPCOMMAND_VOLUME_UP:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_VOLUME_UP;
break;
case APPCOMMAND_MEDIA_NEXTTRACK:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_MEDIA_NEXT_TRACK;
break;
case APPCOMMAND_MEDIA_PREVIOUSTRACK:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_MEDIA_PREV_TRACK;
break;
case APPCOMMAND_MEDIA_STOP:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_MEDIA_STOP;
break;
case APPCOMMAND_MEDIA_PLAY_PAUSE:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_MEDIA_PLAY_PAUSE;
break;
case APPCOMMAND_LAUNCH_MAIL:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_LAUNCH_MAIL;
break;
case APPCOMMAND_LAUNCH_MEDIA_SELECT:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_LAUNCH_MEDIA_SELECT;
break;
case APPCOMMAND_LAUNCH_APP1:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_LAUNCH_APP1;
break;
case APPCOMMAND_LAUNCH_APP2:
mVirtualKeyCode = mOriginalVirtualKeyCode = VK_LAUNCH_APP2;
break;
default:
return;
}
uint16_t scanCodeEx = ComputeScanCodeExFromVirtualKeyCode(mVirtualKeyCode);
mScanCode = static_cast<uint8_t>(scanCodeEx & 0xFF);
uint8_t extended = static_cast<uint8_t>((scanCodeEx & 0xFF00) >> 8);
mIsExtended = (extended == 0xE0) || (extended == 0xE1);
mDOMKeyCode =
KeyboardLayout::GetInstance()->
ConvertNativeKeyCodeToDOMKeyCode(mOriginalVirtualKeyCode);
mCodeNameIndex =
KeyboardLayout::ConvertScanCodeToCodeNameIndex(
GetScanCodeWithExtendedFlag());
}
bool
NativeKey::IsFollowedByDeadCharMessage() const
{
@ -1102,6 +1215,196 @@ NativeKey::DispatchKeyEvent(WidgetKeyboardEvent& aKeyEvent,
return (mWidget->DispatchKeyboardEvent(&aKeyEvent) || mWidget->Destroyed());
}
bool
NativeKey::DispatchCommandEvent(uint32_t aEventCommand) const
{
nsCOMPtr<nsIAtom> command;
switch (aEventCommand) {
case APPCOMMAND_BROWSER_BACKWARD:
command = nsGkAtoms::Back;
break;
case APPCOMMAND_BROWSER_FORWARD:
command = nsGkAtoms::Forward;
break;
case APPCOMMAND_BROWSER_REFRESH:
command = nsGkAtoms::Reload;
break;
case APPCOMMAND_BROWSER_STOP:
command = nsGkAtoms::Stop;
break;
case APPCOMMAND_BROWSER_SEARCH:
command = nsGkAtoms::Search;
break;
case APPCOMMAND_BROWSER_FAVORITES:
command = nsGkAtoms::Bookmarks;
break;
case APPCOMMAND_BROWSER_HOME:
command = nsGkAtoms::Home;
break;
case APPCOMMAND_CLOSE:
command = nsGkAtoms::Close;
break;
case APPCOMMAND_FIND:
command = nsGkAtoms::Find;
break;
case APPCOMMAND_HELP:
command = nsGkAtoms::Help;
break;
case APPCOMMAND_NEW:
command = nsGkAtoms::New;
break;
case APPCOMMAND_OPEN:
command = nsGkAtoms::Open;
break;
case APPCOMMAND_PRINT:
command = nsGkAtoms::Print;
break;
case APPCOMMAND_SAVE:
command = nsGkAtoms::Save;
break;
case APPCOMMAND_FORWARD_MAIL:
command = nsGkAtoms::ForwardMail;
break;
case APPCOMMAND_REPLY_TO_MAIL:
command = nsGkAtoms::ReplyToMail;
break;
case APPCOMMAND_SEND_MAIL:
command = nsGkAtoms::SendMail;
break;
case APPCOMMAND_MEDIA_NEXTTRACK:
command = nsGkAtoms::NextTrack;
break;
case APPCOMMAND_MEDIA_PREVIOUSTRACK:
command = nsGkAtoms::PreviousTrack;
break;
case APPCOMMAND_MEDIA_STOP:
command = nsGkAtoms::MediaStop;
break;
case APPCOMMAND_MEDIA_PLAY_PAUSE:
command = nsGkAtoms::PlayPause;
break;
default:
return false;
}
WidgetCommandEvent commandEvent(true, nsGkAtoms::onAppCommand,
command, mWidget);
mWidget->InitEvent(commandEvent);
return (mWidget->DispatchWindowEvent(&commandEvent) || mWidget->Destroyed());
}
bool
NativeKey::HandleAppCommandMessage() const
{
// NOTE: Typical behavior of WM_APPCOMMAND caused by key is, WM_APPCOMMAND
// message is _sent_ first. Then, the DefaultWndProc will _post_
// WM_KEYDOWN message and WM_KEYUP message if the keycode for the
// command is available (i.e., mVirtualKeyCode is not 0).
// NOTE: IntelliType (Microsoft's keyboard utility software) always consumes
// WM_KEYDOWN and WM_KEYUP.
// Let's dispatch keydown message before our chrome handles the command
// when the message is caused by a keypress. This behavior makes handling
// WM_APPCOMMAND be a default action of the keydown event. This means that
// web applications can handle multimedia keys and prevent our default action.
// This allow web applications to provide better UX for multimedia keyboard
// users.
bool dispatchKeyEvent = (GET_DEVICE_LPARAM(mMsg.lParam) == FAPPCOMMAND_KEY);
bool consumed = false;
if (dispatchKeyEvent) {
WidgetKeyboardEvent keydownEvent(true, NS_KEY_DOWN, mWidget);
InitKeyEvent(keydownEvent, mModKeyState);
// NOTE: If the keydown event is consumed by web contents, we shouldn't
// continue to handle the command.
consumed = DispatchKeyEvent(keydownEvent, &mMsg);
sDispatchedKeyOfAppCommand = mVirtualKeyCode;
if (mWidget->Destroyed()) {
return true;
}
}
// Dispatch a command event or a content command event if the command is
// supported.
if (!consumed) {
uint32_t appCommand = GET_APPCOMMAND_LPARAM(mMsg.lParam);
uint32_t contentCommandMessage = NS_EVENT_NULL;
switch (appCommand) {
case APPCOMMAND_BROWSER_BACKWARD:
case APPCOMMAND_BROWSER_FORWARD:
case APPCOMMAND_BROWSER_REFRESH:
case APPCOMMAND_BROWSER_STOP:
case APPCOMMAND_BROWSER_SEARCH:
case APPCOMMAND_BROWSER_FAVORITES:
case APPCOMMAND_BROWSER_HOME:
case APPCOMMAND_CLOSE:
case APPCOMMAND_FIND:
case APPCOMMAND_HELP:
case APPCOMMAND_NEW:
case APPCOMMAND_OPEN:
case APPCOMMAND_PRINT:
case APPCOMMAND_SAVE:
case APPCOMMAND_FORWARD_MAIL:
case APPCOMMAND_REPLY_TO_MAIL:
case APPCOMMAND_SEND_MAIL:
case APPCOMMAND_MEDIA_NEXTTRACK:
case APPCOMMAND_MEDIA_PREVIOUSTRACK:
case APPCOMMAND_MEDIA_STOP:
case APPCOMMAND_MEDIA_PLAY_PAUSE:
// We shouldn't consume the message always because if we don't handle
// the message, the sender (typically, utility of keyboard or mouse)
// may send other key messages which indicate well known shortcut key.
consumed = DispatchCommandEvent(appCommand);
break;
// Use content command for following commands:
case APPCOMMAND_COPY:
contentCommandMessage = NS_CONTENT_COMMAND_COPY;
break;
case APPCOMMAND_CUT:
contentCommandMessage = NS_CONTENT_COMMAND_CUT;
break;
case APPCOMMAND_PASTE:
contentCommandMessage = NS_CONTENT_COMMAND_PASTE;
break;
case APPCOMMAND_REDO:
contentCommandMessage = NS_CONTENT_COMMAND_REDO;
break;
case APPCOMMAND_UNDO:
contentCommandMessage = NS_CONTENT_COMMAND_UNDO;
break;
}
if (contentCommandMessage) {
WidgetContentCommandEvent contentCommandEvent(true, contentCommandMessage,
mWidget);
mWidget->DispatchWindowEvent(&contentCommandEvent);
consumed = true;
}
if (mWidget->Destroyed()) {
return true;
}
}
// Dispatch a keyup event if the command is caused by pressing a key and
// the key isn't mapped to a virtual keycode.
if (dispatchKeyEvent && !mVirtualKeyCode) {
WidgetKeyboardEvent keyupEvent(true, NS_KEY_UP, mWidget);
InitKeyEvent(keyupEvent, mModKeyState);
// NOTE: Ignore if the keyup event is consumed because keyup event
// represents just a physical key event state change.
DispatchKeyEvent(keyupEvent, &mMsg);
if (mWidget->Destroyed()) {
return true;
}
}
return consumed;
}
bool
NativeKey::HandleKeyDownMessage(bool* aEventDispatched) const
{
@ -1111,6 +1414,14 @@ NativeKey::HandleKeyDownMessage(bool* aEventDispatched) const
*aEventDispatched = false;
}
if (sDispatchedKeyOfAppCommand &&
sDispatchedKeyOfAppCommand == mOriginalVirtualKeyCode) {
// The multimedia key event has already been dispatch from
// HandleAppCommandMessage().
sDispatchedKeyOfAppCommand = 0;
return true;
}
bool defaultPrevented = false;
if (mFakeCharMsgs ||
!RedirectedKeyDownMessageManager::IsRedirectedMessage(mMsg)) {
@ -2597,6 +2908,7 @@ KeyboardLayout::ConvertNativeKeyCodeToDOMKeyCode(UINT aNativeKeyCode) const
case VK_BROWSER_FAVORITES:
case VK_BROWSER_HOME:
case VK_MEDIA_NEXT_TRACK:
case VK_MEDIA_PREV_TRACK:
case VK_MEDIA_STOP:
case VK_MEDIA_PLAY_PAUSE:
case VK_LAUNCH_MAIL:
@ -2717,11 +3029,6 @@ KeyboardLayout::ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const
return KEY_NAME_INDEX_USE_STRING;
}
#define NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex)
#define NS_JAPANESE_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex)
#define NS_KOREAN_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex)
#define NS_OTHER_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex)
switch (aVirtualKey) {
#undef NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
@ -2731,7 +3038,6 @@ KeyboardLayout::ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const
#include "NativeKeyToDOMKeyName.h"
#undef NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
#define NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex)
default:
break;
@ -2751,7 +3057,6 @@ KeyboardLayout::ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const
#include "NativeKeyToDOMKeyName.h"
#undef NS_JAPANESE_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
#define NS_JAPANESE_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex)
default:
break;
@ -2766,7 +3071,6 @@ KeyboardLayout::ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const
#include "NativeKeyToDOMKeyName.h"
#undef NS_KOREAN_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
#define NS_KOREAN_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex)
default:
return KEY_NAME_INDEX_Unidentified;
@ -2781,9 +3085,6 @@ KeyboardLayout::ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const
#include "NativeKeyToDOMKeyName.h"
#undef NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
#undef NS_JAPANESE_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
#undef NS_KOREAN_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
#undef NS_OTHER_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
default:

View File

@ -234,7 +234,7 @@ public:
};
NativeKey(nsWindowBase* aWidget,
const MSG& aKeyOrCharMessage,
const MSG& aMessage,
const ModifierKeyState& aModKeyState,
nsTArray<FakeCharMsg>* aFakeCharMsgs = nullptr);
@ -260,6 +260,12 @@ public:
*/
bool HandleKeyUpMessage(bool* aEventDispatched = nullptr) const;
/**
* Handles WM_APPCOMMAND message. Returns true if the event is consumed.
* Otherwise, false.
*/
bool HandleAppCommandMessage() const;
private:
nsRefPtr<nsWindowBase> mWidget;
HKL mKeyboardLayout;
@ -294,11 +300,19 @@ private:
nsTArray<FakeCharMsg>* mFakeCharMsgs;
// When a keydown event is dispatched at handling WM_APPCOMMAND, the computed
// virtual keycode is set to this. Even if we consume WM_APPCOMMAND message,
// Windows may send WM_KEYDOWN and WM_KEYUP message for them.
// At that time, we should not dispatch key events for them.
static uint8_t sDispatchedKeyOfAppCommand;
NativeKey()
{
MOZ_CRASH("The default constructor of NativeKey isn't available");
}
void InitWithAppCommand();
/**
* Returns true if the key event is caused by auto repeat.
*/
@ -312,6 +326,21 @@ private:
case WM_DEADCHAR:
case WM_SYSDEADCHAR:
return ((mMsg.lParam & (1 << 30)) != 0);
case WM_APPCOMMAND:
if (mVirtualKeyCode) {
// If we can map the WM_APPCOMMAND to a virtual keycode, we can trust
// the result of GetKeyboardState().
BYTE kbdState[256];
memset(kbdState, 0, sizeof(kbdState));
::GetKeyboardState(kbdState);
return !!kbdState[mVirtualKeyCode];
}
// If there is no virtual keycode for the command, we dispatch both
// keydown and keyup events from WM_APPCOMMAND handler. Therefore,
// even if WM_APPCOMMAND is caused by auto key repeat, web apps receive
// a pair of DOM keydown and keyup events. I.e., KeyboardEvent.repeat
// should be never true of such keys.
return false;
default:
return false;
}
@ -414,6 +443,12 @@ private:
const ModifierKeyState& aModKeyState) const;
void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent) const;
/**
* Dispatches a command event for aEventCommand.
* Returns true if the event is consumed. Otherwise, false.
*/
bool DispatchCommandEvent(uint32_t aEventCommand) const;
/**
* Dispatches the key event. Returns true if the event is consumed.
* Otherwise, false.

View File

@ -5122,8 +5122,11 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
break;
case WM_APPCOMMAND:
result = HandleAppCommandMsg(wParam, lParam, aRetValue);
{
MSG nativeMsg = WinUtils::InitMSG(msg, wParam, lParam, mWnd);
result = HandleAppCommandMsg(nativeMsg, aRetValue);
break;
}
// The WM_ACTIVATE event is fired when a window is raised or lowered,
// and the loword of wParam specifies which. But we don't want to tell

View File

@ -6,7 +6,6 @@
#include "nsWindowBase.h"
#include "mozilla/MiscEvents.h"
#include "nsGkAtoms.h"
#include "WinUtils.h"
#include "npapi.h"
@ -195,151 +194,12 @@ nsWindowBase::ClearNativeTouchSequence()
}
bool
nsWindowBase::DispatchCommandEvent(uint32_t aEventCommand)
{
nsCOMPtr<nsIAtom> command;
switch (aEventCommand) {
case APPCOMMAND_BROWSER_BACKWARD:
command = nsGkAtoms::Back;
break;
case APPCOMMAND_BROWSER_FORWARD:
command = nsGkAtoms::Forward;
break;
case APPCOMMAND_BROWSER_REFRESH:
command = nsGkAtoms::Reload;
break;
case APPCOMMAND_BROWSER_STOP:
command = nsGkAtoms::Stop;
break;
case APPCOMMAND_BROWSER_SEARCH:
command = nsGkAtoms::Search;
break;
case APPCOMMAND_BROWSER_FAVORITES:
command = nsGkAtoms::Bookmarks;
break;
case APPCOMMAND_BROWSER_HOME:
command = nsGkAtoms::Home;
break;
case APPCOMMAND_CLOSE:
command = nsGkAtoms::Close;
break;
case APPCOMMAND_FIND:
command = nsGkAtoms::Find;
break;
case APPCOMMAND_HELP:
command = nsGkAtoms::Help;
break;
case APPCOMMAND_NEW:
command = nsGkAtoms::New;
break;
case APPCOMMAND_OPEN:
command = nsGkAtoms::Open;
break;
case APPCOMMAND_PRINT:
command = nsGkAtoms::Print;
break;
case APPCOMMAND_SAVE:
command = nsGkAtoms::Save;
break;
case APPCOMMAND_FORWARD_MAIL:
command = nsGkAtoms::ForwardMail;
break;
case APPCOMMAND_REPLY_TO_MAIL:
command = nsGkAtoms::ReplyToMail;
break;
case APPCOMMAND_SEND_MAIL:
command = nsGkAtoms::SendMail;
break;
case APPCOMMAND_MEDIA_NEXTTRACK:
command = nsGkAtoms::NextTrack;
break;
case APPCOMMAND_MEDIA_PREVIOUSTRACK:
command = nsGkAtoms::PreviousTrack;
break;
case APPCOMMAND_MEDIA_STOP:
command = nsGkAtoms::MediaStop;
break;
case APPCOMMAND_MEDIA_PLAY_PAUSE:
command = nsGkAtoms::PlayPause;
break;
default:
return false;
}
WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, command, this);
InitEvent(event);
return DispatchWindowEvent(&event);
}
bool
nsWindowBase::HandleAppCommandMsg(WPARAM aWParam,
LPARAM aLParam,
nsWindowBase::HandleAppCommandMsg(const MSG& aAppCommandMsg,
LRESULT *aRetValue)
{
uint32_t appCommand = GET_APPCOMMAND_LPARAM(aLParam);
uint32_t contentCommandMessage = NS_EVENT_NULL;
// XXX After we implement KeyboardEvent.key, we should dispatch the
// key event if (GET_DEVICE_LPARAM(lParam) == FAPPCOMMAND_KEY) is.
switch (appCommand)
{
case APPCOMMAND_BROWSER_BACKWARD:
case APPCOMMAND_BROWSER_FORWARD:
case APPCOMMAND_BROWSER_REFRESH:
case APPCOMMAND_BROWSER_STOP:
case APPCOMMAND_BROWSER_SEARCH:
case APPCOMMAND_BROWSER_FAVORITES:
case APPCOMMAND_BROWSER_HOME:
case APPCOMMAND_CLOSE:
case APPCOMMAND_FIND:
case APPCOMMAND_HELP:
case APPCOMMAND_NEW:
case APPCOMMAND_OPEN:
case APPCOMMAND_PRINT:
case APPCOMMAND_SAVE:
case APPCOMMAND_FORWARD_MAIL:
case APPCOMMAND_REPLY_TO_MAIL:
case APPCOMMAND_SEND_MAIL:
case APPCOMMAND_MEDIA_NEXTTRACK:
case APPCOMMAND_MEDIA_PREVIOUSTRACK:
case APPCOMMAND_MEDIA_STOP:
case APPCOMMAND_MEDIA_PLAY_PAUSE:
// We shouldn't consume the message always because if we don't handle
// the message, the sender (typically, utility of keyboard or mouse)
// may send other key messages which indicate well known shortcut key.
if (DispatchCommandEvent(appCommand)) {
// tell the driver that we handled the event
*aRetValue = 1;
return true;
}
break;
// Use content command for following commands:
case APPCOMMAND_COPY:
contentCommandMessage = NS_CONTENT_COMMAND_COPY;
break;
case APPCOMMAND_CUT:
contentCommandMessage = NS_CONTENT_COMMAND_CUT;
break;
case APPCOMMAND_PASTE:
contentCommandMessage = NS_CONTENT_COMMAND_PASTE;
break;
case APPCOMMAND_REDO:
contentCommandMessage = NS_CONTENT_COMMAND_REDO;
break;
case APPCOMMAND_UNDO:
contentCommandMessage = NS_CONTENT_COMMAND_UNDO;
break;
}
if (contentCommandMessage) {
WidgetContentCommandEvent contentCommand(true, contentCommandMessage,
this);
DispatchWindowEvent(&contentCommand);
// tell the driver that we handled the event
*aRetValue = 1;
return true;
}
// default = false - tell the driver that the event was not handled
return false;
ModifierKeyState modKeyState;
NativeKey nativeKey(this, aAppCommandMsg, modKeyState);
bool consumed = nativeKey.HandleAppCommandMessage();
*aRetValue = consumed ? 1 : 0;
return consumed;
}

View File

@ -89,14 +89,13 @@ public:
virtual nsresult ClearNativeTouchSequence();
/*
* WM_APPCOMMAND common handler. Sends events via DispatchWindowEvent.
* WM_APPCOMMAND common handler.
* Sends events via NativeKey::HandleAppCommandMessage().
*/
virtual bool HandleAppCommandMsg(WPARAM aWParam,
LPARAM aLParam,
virtual bool HandleAppCommandMsg(const MSG& aAppCommandMsg,
LRESULT *aRetValue);
protected:
bool DispatchCommandEvent(uint32_t aEventCommand);
static bool InitTouchInjection();
bool InjectTouchPoint(uint32_t aId, nsIntPoint& aPointerScreenPoint,
POINTER_FLAGS aFlags, uint32_t aPressure = 1024,

View File

@ -880,8 +880,11 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
}
case WM_APPCOMMAND:
processDefault = HandleAppCommandMsg(aWParam, aLParam, &processResult);
{
MSG msg = WinUtils::InitMSG(aMsg, aWParam, aLParam, aWnd);
processDefault = HandleAppCommandMsg(msg, &processResult);
break;
}
case WM_GETOBJECT:
{