Support multimedia keys on Windows

We currently do not receive events from most multimedia keys on Windows
because they are sent using appcommand events instead of the normal key
events.

This patchs adds support for parsing appcommand events.

Change-Id: I19f568b6fa0d3d136e3a22318df1499a1fab6edb
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
bb10
Allan Sandfeld Jensen 2014-07-02 15:44:49 +02:00
parent c0c80f14af
commit 985ebe32f2
8 changed files with 136 additions and 4 deletions

View File

@ -1014,6 +1014,15 @@ public:
Key_Info = 0x0100011b,
Key_Settings = 0x0100011c,
Key_MicVolumeUp = 0x0100011d,
Key_MicVolumeDown = 0x0100011e,
Key_New = 0x01000120,
Key_Open = 0x01000121,
Key_Find = 0x01000122,
Key_Undo = 0x01000123,
Key_Redo = 0x01000124,
Key_MediaLast = 0x0100ffff,
// Keypad navigation keys

View File

@ -490,7 +490,7 @@ static const struct {
{ Qt::Key_BrightnessAdjust, QT_TRANSLATE_NOOP("QShortcut", "Adjust Brightness") },
{ Qt::Key_Finance, QT_TRANSLATE_NOOP("QShortcut", "Finance") },
{ Qt::Key_Community, QT_TRANSLATE_NOOP("QShortcut", "Community") },
{ Qt::Key_AudioRewind, QT_TRANSLATE_NOOP("QShortcut", "Audio Rewind") },
{ Qt::Key_AudioRewind, QT_TRANSLATE_NOOP("QShortcut", "Media Rewind") },
{ Qt::Key_BackForward, QT_TRANSLATE_NOOP("QShortcut", "Back Forward") },
{ Qt::Key_ApplicationLeft, QT_TRANSLATE_NOOP("QShortcut", "Application Left") },
{ Qt::Key_ApplicationRight, QT_TRANSLATE_NOOP("QShortcut", "Application Right") },
@ -550,17 +550,40 @@ static const struct {
{ Qt::Key_Bluetooth, QT_TRANSLATE_NOOP("QShortcut", "Bluetooth") },
{ Qt::Key_WLAN, QT_TRANSLATE_NOOP("QShortcut", "Wireless") },
{ Qt::Key_UWB, QT_TRANSLATE_NOOP("QShortcut", "Ultra Wide Band") },
{ Qt::Key_AudioForward, QT_TRANSLATE_NOOP("QShortcut", "Audio Forward") },
{ Qt::Key_AudioForward, QT_TRANSLATE_NOOP("QShortcut", "Media Fast Forward") },
{ Qt::Key_AudioRepeat, QT_TRANSLATE_NOOP("QShortcut", "Audio Repeat") },
{ Qt::Key_AudioRandomPlay, QT_TRANSLATE_NOOP("QShortcut", "Audio Random Play") },
{ Qt::Key_Subtitle, QT_TRANSLATE_NOOP("QShortcut", "Subtitle") },
{ Qt::Key_AudioCycleTrack, QT_TRANSLATE_NOOP("QShortcut", "Audio Cycle Track") },
{ Qt::Key_Time, QT_TRANSLATE_NOOP("QShortcut", "Time") },
{ Qt::Key_Select, QT_TRANSLATE_NOOP("QShortcut", "Select") },
{ Qt::Key_Hibernate, QT_TRANSLATE_NOOP("QShortcut", "Hibernate") },
{ Qt::Key_View, QT_TRANSLATE_NOOP("QShortcut", "View") },
{ Qt::Key_TopMenu, QT_TRANSLATE_NOOP("QShortcut", "Top Menu") },
{ Qt::Key_PowerDown, QT_TRANSLATE_NOOP("QShortcut", "Power Down") },
{ Qt::Key_Suspend, QT_TRANSLATE_NOOP("QShortcut", "Suspend") },
{ Qt::Key_Hibernate, QT_TRANSLATE_NOOP("QShortcut", "Hibernate") },
{ Qt::Key_MicMute, QT_TRANSLATE_NOOP("QShortcut", "Microphone Mute") },
{ Qt::Key_Red, QT_TRANSLATE_NOOP("QShortcut", "Red") },
{ Qt::Key_Green, QT_TRANSLATE_NOOP("QShortcut", "Green") },
{ Qt::Key_Yellow, QT_TRANSLATE_NOOP("QShortcut", "Yellow") },
{ Qt::Key_Blue, QT_TRANSLATE_NOOP("QShortcut", "Blue") },
{ Qt::Key_ChannelUp, QT_TRANSLATE_NOOP("QShortcut", "Channel Up") },
{ Qt::Key_ChannelDown, QT_TRANSLATE_NOOP("QShortcut", "Channel Down") },
{ Qt::Key_Guide, QT_TRANSLATE_NOOP("QShortcut", "Guide") },
{ Qt::Key_Info, QT_TRANSLATE_NOOP("QShortcut", "Info") },
{ Qt::Key_Settings, QT_TRANSLATE_NOOP("QShortcut", "Settings") },
{ Qt::Key_MicVolumeUp, QT_TRANSLATE_NOOP("QShortcut", "Microphone Volume Up") },
{ Qt::Key_MicVolumeDown, QT_TRANSLATE_NOOP("QShortcut", "Microphone Volume Down") },
{ Qt::Key_New, QT_TRANSLATE_NOOP("QShortcut", "New") },
{ Qt::Key_Open, QT_TRANSLATE_NOOP("QShortcut", "Open") },
{ Qt::Key_Find, QT_TRANSLATE_NOOP("QShortcut", "Find") },
{ Qt::Key_Undo, QT_TRANSLATE_NOOP("QShortcut", "Undo") },
{ Qt::Key_Redo, QT_TRANSLATE_NOOP("QShortcut", "Redo") },
// --------------------------------------------------------------
// More consistent namings
@ -647,6 +670,7 @@ static const struct {
{ Qt::Key_Execute, QT_TRANSLATE_NOOP("QShortcut", "Execute") },
{ Qt::Key_Play, QT_TRANSLATE_NOOP("QShortcut", "Play") },
{ Qt::Key_Zoom, QT_TRANSLATE_NOOP("QShortcut", "Zoom") },
{ Qt::Key_Exit, QT_TRANSLATE_NOOP("QShortcut", "Exit") },
{ 0, 0 }
};

View File

@ -103,6 +103,7 @@ enum WindowsEventType // Simplify event types
AccessibleObjectFromWindowRequest = ApplicationEventFlag + 3,
QueryEndSessionApplicationEvent = ApplicationEventFlag + 4,
EndSessionApplicationEvent = ApplicationEventFlag + 5,
AppCommandEvent = ApplicationEventFlag + 6,
InputMethodStartCompositionEvent = InputMethodEventFlag + 1,
InputMethodCompositionEvent = InputMethodEventFlag + 2,
InputMethodEndCompositionEvent = InputMethodEventFlag + 3,
@ -241,6 +242,10 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::QueryEndSessionApplicationEvent;
case WM_ENDSESSION:
return QtWindows::EndSessionApplicationEvent;
#endif
#if defined(WM_APPCOMMAND)
case WM_APPCOMMAND:
return QtWindows::AppCommandEvent;
#endif
default:
break;

View File

@ -962,6 +962,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::InputMethodKeyEvent:
case QtWindows::InputMethodKeyDownEvent:
case QtWindows::KeyboardLayoutChangeEvent:
case QtWindows::AppCommandEvent:
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
return platformSessionManager()->isInteractionBlocked() ? true : d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
#else

View File

@ -115,6 +115,9 @@ messageDebugEntries[] = {
{WM_SYSCOMMAND, "WM_SYSCOMMAND", true},
{WM_KEYUP, "WM_KEYUP", true},
{WM_SYSKEYUP, "WM_SYSKEYUP", true},
#if defined(WM_APPCOMMAND)
{WM_APPCOMMAND, "WM_APPCOMMAND", true},
#endif
{WM_IME_CHAR, "WM_IMECHAR", true},
{WM_IME_KEYDOWN, "WM_IMECHAR", true},
{WM_CANCELMODE, "WM_CANCELMODE", true},

View File

@ -428,6 +428,63 @@ static const uint KeyTbl[] = { // Keyboard mapping table
0
};
static const uint CmdTbl[] = { // Multimedia keys mapping table
// Dec | Hex | AppCommand
Qt::Key_unknown, // 0 0x00
Qt::Key_Back, // 1 0x01 APPCOMMAND_BROWSER_BACKWARD
Qt::Key_Forward, // 2 0x02 APPCOMMAND_BROWSER_FORWARD
Qt::Key_Refresh, // 3 0x03 APPCOMMAND_BROWSER_REFRESH
Qt::Key_Stop, // 4 0x04 APPCOMMAND_BROWSER_STOP
Qt::Key_Search, // 5 0x05 APPCOMMAND_BROWSER_SEARCH
Qt::Key_Favorites, // 6 0x06 APPCOMMAND_BROWSER_FAVORITES
Qt::Key_Home, // 7 0x07 APPCOMMAND_BROWSER_HOME
Qt::Key_VolumeMute, // 8 0x08 APPCOMMAND_VOLUME_MUTE
Qt::Key_VolumeDown, // 9 0x09 APPCOMMAND_VOLUME_DOWN
Qt::Key_VolumeUp, // 10 0x0a APPCOMMAND_VOLUME_UP
Qt::Key_MediaNext, // 11 0x0b APPCOMMAND_MEDIA_NEXTTRACK
Qt::Key_MediaPrevious, // 12 0x0c APPCOMMAND_MEDIA_PREVIOUSTRACK
Qt::Key_MediaStop, // 13 0x0d APPCOMMAND_MEDIA_STOP
Qt::Key_MediaTogglePlayPause, // 14 0x0e APPCOMMAND_MEDIA_PLAYPAUSE
Qt::Key_LaunchMail, // 15 0x0f APPCOMMAND_LAUNCH_MAIL
Qt::Key_LaunchMedia, // 16 0x10 APPCOMMAND_LAUNCH_MEDIA_SELECT
Qt::Key_Launch0, // 17 0x11 APPCOMMAND_LAUNCH_APP1
Qt::Key_Launch1, // 18 0x12 APPCOMMAND_LAUNCH_APP2
Qt::Key_BassDown, // 19 0x13 APPCOMMAND_BASS_DOWN
Qt::Key_BassBoost, // 20 0x14 APPCOMMAND_BASS_BOOST
Qt::Key_BassUp, // 21 0x15 APPCOMMAND_BASS_UP
Qt::Key_TrebleDown, // 22 0x16 APPCOMMAND_TREBLE_DOWN
Qt::Key_TrebleUp, // 23 0x17 APPCOMMAND_TREBLE_UP
Qt::Key_MicMute, // 24 0x18 APPCOMMAND_MICROPHONE_VOLUME_MUTE
Qt::Key_MicVolumeDown, // 25 0x19 APPCOMMAND_MICROPHONE_VOLUME_DOWN
Qt::Key_MicVolumeUp, // 26 0x1a APPCOMMAND_MICROPHONE_VOLUME_UP
Qt::Key_Help, // 27 0x1b APPCOMMAND_HELP
Qt::Key_Find, // 28 0x1c APPCOMMAND_FIND
Qt::Key_New, // 29 0x1d APPCOMMAND_NEW
Qt::Key_Open, // 30 0x1e APPCOMMAND_OPEN
Qt::Key_Close, // 31 0x1f APPCOMMAND_CLOSE
Qt::Key_Save, // 32 0x20 APPCOMMAND_SAVE
Qt::Key_Print, // 33 0x21 APPCOMMAND_PRINT
Qt::Key_Undo, // 34 0x22 APPCOMMAND_UNDO
Qt::Key_Redo, // 35 0x23 APPCOMMAND_REDO
Qt::Key_Copy, // 36 0x24 APPCOMMAND_COPY
Qt::Key_Cut, // 37 0x25 APPCOMMAND_CUT
Qt::Key_Paste, // 38 0x26 APPCOMMAND_PASTE
Qt::Key_Reply, // 39 0x27 APPCOMMAND_REPLY_TO_MAIL
Qt::Key_MailForward, // 40 0x28 APPCOMMAND_FORWARD_MAIL
Qt::Key_Send, // 41 0x29 APPCOMMAND_SEND_MAIL
Qt::Key_Spell, // 42 0x2a APPCOMMAND_SPELL_CHECK
Qt::Key_unknown, // 43 0x2b APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE
Qt::Key_unknown, // 44 0x2c APPCOMMAND_MIC_ON_OFF_TOGGLE
Qt::Key_unknown, // 45 0x2d APPCOMMAND_CORRECTION_LIST
Qt::Key_MediaPlay, // 46 0x2e APPCOMMAND_MEDIA_PLAY
Qt::Key_MediaPause, // 47 0x2f APPCOMMAND_MEDIA_PAUSE
Qt::Key_MediaRecord, // 48 0x30 APPCOMMAND_MEDIA_RECORD
Qt::Key_AudioForward, // 49 0x31 APPCOMMAND_MEDIA_FAST_FORWARD
Qt::Key_AudioRewind, // 50 0x32 APPCOMMAND_MEDIA_REWIND
Qt::Key_ChannelDown, // 51 0x33 APPCOMMAND_MEDIA_CHANNEL_DOWN
Qt::Key_ChannelUp // 52 0x34 APPCOMMAND_MEDIA_CHANNEL_UP
};
// Possible modifier states.
// NOTE: The order of these states match the order in QWindowsKeyMapper::updatePossibleKeyCodes()!
static const Qt::KeyboardModifiers ModsTbl[] = {
@ -747,6 +804,11 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd,
return true;
}
#if defined(WM_APPCOMMAND)
if (msg.message == WM_APPCOMMAND)
return translateMultimediaKeyEventInternal(widget, msg);
#endif
// WM_(IME_)CHAR messages already contain the character in question so there is
// no need to fiddle with our key map. In any other case add this key to the
// keymap if it is not present yet.
@ -761,6 +823,29 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd,
return translateKeyEventInternal(widget, msg, false);
}
bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, const MSG &msg)
{
#if defined(WM_APPCOMMAND)
const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
const int dwKeys = GET_KEYSTATE_LPARAM(msg.lParam);
int state = 0;
state |= (dwKeys & MK_SHIFT ? int(Qt::ShiftModifier) : 0);
state |= (dwKeys & MK_CONTROL ? int(Qt::ControlModifier) : 0);
QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
if (cmd < 0 || cmd > 52)
return false;
const int qtKey = CmdTbl[cmd];
sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
return true;
#else
Q_UNREACHABLE();
return false;
#endif
}
bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */)
{
const int msgType = msg.message;

View File

@ -93,6 +93,7 @@ public:
private:
bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab);
bool translateMultimediaKeyEventInternal(QWindow *receiver, const MSG &msg);
void updateKeyMap(const MSG &msg);
bool m_useRTLExtensions;

View File

@ -198,8 +198,10 @@
#define XF86XK_MenuKB 0x1008FF65
#define XF86XK_MenuPB 0x1008FF66
#define XF86XK_MySites 0x1008FF67
#define XF86XK_New 0x1008FF68
#define XF86XK_News 0x1008FF69
#define XF86XK_OfficeHome 0x1008FF6A
#define XF86XK_Open 0x1008FF6B
#define XF86XK_Option 0x1008FF6C
#define XF86XK_Paste 0x1008FF6D
#define XF86XK_Phone 0x1008FF6E
@ -497,8 +499,10 @@ static const unsigned int KeyTbl[] = {
XF86XK_MenuKB, Qt::Key_MenuKB,
XF86XK_MenuPB, Qt::Key_MenuPB,
XF86XK_MySites, Qt::Key_MySites,
XF86XK_New, Qt::Key_New,
XF86XK_News, Qt::Key_News,
XF86XK_OfficeHome, Qt::Key_OfficeHome,
XF86XK_Open, Qt::Key_Open,
XF86XK_Option, Qt::Key_Option,
XF86XK_Paste, Qt::Key_Paste,
XF86XK_Phone, Qt::Key_Phone,