Skip to content
Permalink
Browse files

Merge PR #3208: GlobalShortcutWin, MumbleApplication: add suppression…

… support for injected Windows keyboard/mouse message events.
  • Loading branch information...
mkrautz committed Aug 7, 2017
2 parents 5db1fa4 + b22f9c3 commit 807869b3f3b4f77565dd3837466d0ccf0362897f
Showing with 63 additions and 29 deletions.
  1. +39 −19 src/mumble/GlobalShortcut_win.cpp
  2. +8 −2 src/mumble/GlobalShortcut_win.h
  3. +16 −8 src/mumble/MumbleApplication.cpp
@@ -11,6 +11,8 @@
#include "OverlayClient.h"
#include "Global.h"

#include <future>

// 3rdparty/xinputcheck-src.
#include <xinputcheck.h>

@@ -34,26 +36,31 @@ class InjectKeyboardMessageEvent : public QEvent {
Q_DISABLE_COPY(InjectKeyboardMessageEvent);

public:
std::promise<bool> m_suppressionPromise;
DWORD m_scancode;
DWORD m_vkcode;
bool m_extended;
bool m_down;

/// Construct a new InjectKeyboardMessageEvent.
///
/// @param scancode The Windows scancode of the button.
/// @param vkcode The Windows virtual keycode of the button.
/// @param extended Indicates whether the button is an extended key in
/// Windows nomenclature. ("[...] such as the right-hand ALT
/// and CTRL keys that appear on an enhanced 101- or 102-key
/// keyboard")
/// @param down The down/pressed status of the keyboard button.
/// @param scancode The Windows scancode of the button.
/// @param vkcode The Windows virtual keycode of the button.
/// @param extended Indicates whether the button is an extended key in
/// Windows nomenclature. ("[...] such as the right-hand ALT
/// and CTRL keys that appear on an enhanced 101- or 102-key
/// keyboard")
/// @param down The down/pressed status of the keyboard button.
InjectKeyboardMessageEvent(DWORD scancode, DWORD vkcode, bool extended, bool down)
: QEvent(static_cast<QEvent::Type>(INJECTKEYBOARDMESSAGE_QEVENT))
, m_scancode(scancode)
, m_vkcode(vkcode)
, m_extended(extended)
, m_down(down) {}

inline std::future<bool> shouldSuppress() {
return m_suppressionPromise.get_future();
}
};

/// InjectMouseMessageEvent is an event that can be sent to
@@ -63,17 +70,22 @@ class InjectMouseMessageEvent : public QEvent {
Q_DISABLE_COPY(InjectMouseMessageEvent);

public:
std::promise<bool> m_suppressionPromise;
unsigned int m_btn;
bool m_down;

/// Construct a new InjectMouseMessageEvent.
///
/// @param btn The DirectInput button index of the mouse event.
/// @param down The down/pressed status of the mouse button.
/// @param btn The DirectInput button index of the mouse event.
/// @param down The down/pressed status of the mouse button.
InjectMouseMessageEvent(unsigned int btn, bool down)
: QEvent(static_cast<QEvent::Type>(INJECTMOUSEMESSAGE_QEVENT))
, m_btn(btn)
, m_down(down) {}

inline std::future<bool> shouldSuppress() {
return m_suppressionPromise.get_future();
}
};

uint qHash(const GUID &a) {
@@ -206,19 +218,21 @@ bool GlobalShortcutWin::event(QEvent *event) {
QEvent::Type type = event->type();
if (type == INJECTKEYBOARDMESSAGE_QEVENT) {
InjectKeyboardMessageEvent *ikme = static_cast<InjectKeyboardMessageEvent *>(event);
handleKeyboardMessage(ikme->m_scancode, ikme->m_vkcode, ikme->m_extended, ikme->m_down);
bool suppress = handleKeyboardMessage(ikme->m_scancode, ikme->m_vkcode, ikme->m_extended, ikme->m_down);
ikme->m_suppressionPromise.set_value(suppress);
return true;
} else if (type == INJECTMOUSEMESSAGE_QEVENT) {
InjectMouseMessageEvent *imme = static_cast<InjectMouseMessageEvent *>(event);
handleMouseMessage(imme->m_btn, imme->m_down);
bool suppress = handleMouseMessage(imme->m_btn, imme->m_down);
imme->m_suppressionPromise.set_value(suppress);
return true;
}
return GlobalShortcutEngine::event(event);
}

void GlobalShortcutWin::injectKeyboardMessage(MSG *msg) {
bool GlobalShortcutWin::injectKeyboardMessage(MSG *msg) {
if (!bHook) {
return;
return false;
}

// Only allow keyboard messages.
@@ -229,20 +243,23 @@ void GlobalShortcutWin::injectKeyboardMessage(MSG *msg) {
case WM_SYSKEYUP:
break;
default:
return;
return false;
}

DWORD scancode = (msg->lParam >> 16) & 0xff;
DWORD vkcode = msg->wParam;
bool extended = !!(msg->lParam & 0x01000000);
bool up = !!(msg->lParam & 0x80000000);

qApp->postEvent(this, new InjectKeyboardMessageEvent(scancode, vkcode, extended, !up));
InjectKeyboardMessageEvent *ikme = new InjectKeyboardMessageEvent(scancode, vkcode, extended, !up);
std::future<bool> suppress = ikme->shouldSuppress();
qApp->postEvent(this, ikme);
return suppress.get();
}

void GlobalShortcutWin::injectMouseMessage(MSG *msg) {
bool GlobalShortcutWin::injectMouseMessage(MSG *msg) {
if (!bHook) {
return;
return false;
}

bool down = false;
@@ -274,10 +291,13 @@ void GlobalShortcutWin::injectMouseMessage(MSG *msg) {
}
default:
// Non-mouse event. Return early.
return;
return false;
}

qApp->postEvent(this, new InjectMouseMessageEvent(btn, down));
InjectMouseMessageEvent *imme = new InjectMouseMessageEvent(btn, down);
std::future<bool> suppress = imme->shouldSuppress();
qApp->postEvent(this, imme);
return suppress.get();
}

bool GlobalShortcutWin::handleKeyboardMessage(DWORD scancode, DWORD vkcode, bool extended, bool down) {
@@ -112,7 +112,10 @@ class GlobalShortcutWin : public GlobalShortcutEngine {
/// @param msg The keyboard message to inject into GlobalShortcutWin.
/// Must be WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN or WM_SYSKEYUP.
/// Otherwise the message will be ignored.
void injectKeyboardMessage(MSG *msg);
///
/// @return Returns true if the GlobalShortcut engine signalled that
/// the button should be suppressed. Returns false otherwise.
bool injectKeyboardMessage(MSG *msg);

/// Inject a native Windows mouse message into GlobalShortcutWin's
/// event stream. This method is meant to be called from the main thread
@@ -122,7 +125,10 @@ class GlobalShortcutWin : public GlobalShortcutEngine {
/// Must be WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDOWN,
/// WM_RBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_XBUTTONDOWN
/// or WM_XBUTTONUP. Otherwise the message will be ignored.
void injectMouseMessage(MSG *msg);
///
/// @return Returns true if the GlobalShortcut engine signalled that
/// the button should be suppressed. Returns false otherwise.
bool injectMouseMessage(MSG *msg);
};

uint qHash(const GUID &);
@@ -62,10 +62,13 @@ bool MumbleApplication::event(QEvent *e) {
#ifdef Q_OS_WIN
/// gswForward forwards a native Windows keyboard/mouse message
/// into GlobalShortcutWin's event stream.
static void gswForward(MSG *msg) {
///
/// @return Returns true if the forwarded event was suppressed
/// by GlobalShortcutWin. Otherwise, returns false.
static bool gswForward(MSG *msg) {
GlobalShortcutWin *gsw = static_cast<GlobalShortcutWin *>(GlobalShortcutEngine::engine);
if (gsw == NULL) {
return;
return false;
}
switch (msg->message) {
case WM_LBUTTONDOWN:
@@ -76,29 +79,34 @@ static void gswForward(MSG *msg) {
case WM_MBUTTONUP:
case WM_XBUTTONDOWN:
case WM_XBUTTONUP:
gsw->injectMouseMessage(msg);
break;
return gsw->injectMouseMessage(msg);
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
gsw->injectKeyboardMessage(msg);
break;
return gsw->injectKeyboardMessage(msg);
}
return false;
}

# if QT_VERSION >= 0x050000
bool MumbleApplication::nativeEventFilter(const QByteArray &, void *message, long *) {
MSG *msg = reinterpret_cast<MSG *>(message);
if (QThread::currentThread() == thread()) {
gswForward(msg);
bool suppress = gswForward(msg);
if (suppress) {
return true;
}
}
return false;
}
# else
bool MumbleApplication::winEventFilter(MSG *msg, long *result) {
if (QThread::currentThread() == thread()) {
gswForward(msg);
bool suppress = gswForward(msg);
if (suppress) {
return true;
}
}
return QApplication::winEventFilter(msg, result);
}

0 comments on commit 807869b

Please sign in to comment.
You can’t perform that action at this time.