mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
fix X11 auto-type
This commit is contained in:
parent
e53ac65518
commit
7ab6af00bc
@ -641,21 +641,13 @@ int AutoTypePlatformX11::AddKeysym(KeySym keysym)
|
|||||||
* If input focus is specified explicitly, select the window
|
* If input focus is specified explicitly, select the window
|
||||||
* before send event to the window.
|
* before send event to the window.
|
||||||
*/
|
*/
|
||||||
void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type)
|
void AutoTypePlatformX11::SendKeyEvent(unsigned keycode, bool press)
|
||||||
{
|
{
|
||||||
XSync(event->display, False);
|
XSync(m_dpy, False);
|
||||||
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
|
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
|
||||||
|
|
||||||
event->type = event_type;
|
XTestFakeKeyEvent(m_dpy, keycode, press, 0);
|
||||||
Bool press;
|
XFlush(m_dpy);
|
||||||
if (event->type == KeyPress) {
|
|
||||||
press = True;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
press = False;
|
|
||||||
}
|
|
||||||
XTestFakeKeyEvent(event->display, event->keycode, press, 0);
|
|
||||||
XFlush(event->display);
|
|
||||||
|
|
||||||
XSetErrorHandler(oldHandler);
|
XSetErrorHandler(oldHandler);
|
||||||
}
|
}
|
||||||
@ -664,17 +656,12 @@ void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type)
|
|||||||
* Send a modifier press/release event for all modifiers
|
* Send a modifier press/release event for all modifiers
|
||||||
* which are set in the mask variable.
|
* which are set in the mask variable.
|
||||||
*/
|
*/
|
||||||
void AutoTypePlatformX11::SendModifier(XKeyEvent *event, unsigned int mask, int event_type)
|
void AutoTypePlatformX11::SendModifiers(unsigned int mask, bool press)
|
||||||
{
|
{
|
||||||
int mod_index;
|
int mod_index;
|
||||||
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
|
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
|
||||||
if (mask & (1 << mod_index)) {
|
if (mask & (1 << mod_index)) {
|
||||||
event->keycode = m_modifier_keycode[mod_index];
|
SendKeyEvent(m_modifier_keycode[mod_index], press);
|
||||||
SendEvent(event, event_type);
|
|
||||||
if (event_type == KeyPress)
|
|
||||||
event->state |= (1 << mod_index);
|
|
||||||
else
|
|
||||||
event->state &= (1 << mod_index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -729,43 +716,15 @@ bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned i
|
|||||||
* window to simulate keyboard. If modifiers (shift, control, etc)
|
* window to simulate keyboard. If modifiers (shift, control, etc)
|
||||||
* are set ON, many events will be sent.
|
* are set ON, many events will be sent.
|
||||||
*/
|
*/
|
||||||
void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym)
|
void AutoTypePlatformX11::SendKey(KeySym keysym, unsigned int modifiers)
|
||||||
{
|
{
|
||||||
SendKey(keysym,true);
|
|
||||||
SendKey(keysym,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AutoTypePlatformX11::SendKey(KeySym keysym, bool isKeyDown)
|
|
||||||
{
|
|
||||||
Window cur_focus;
|
|
||||||
int revert_to;
|
|
||||||
XKeyEvent event;
|
|
||||||
int keycode;
|
|
||||||
|
|
||||||
if (keysym == NoSymbol) {
|
if (keysym == NoSymbol) {
|
||||||
qWarning("No such key: keysym=0x%lX", keysym);
|
qWarning("No such key: keysym=0x%lX", keysym);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
XGetInputFocus(m_dpy, &cur_focus, &revert_to);
|
int keycode;
|
||||||
|
unsigned int wanted_mask;
|
||||||
event.display = m_dpy;
|
|
||||||
event.window = cur_focus;
|
|
||||||
event.root = m_rootWindow;
|
|
||||||
event.subwindow = None;
|
|
||||||
event.time = CurrentTime;
|
|
||||||
event.x = 1;
|
|
||||||
event.y = 1;
|
|
||||||
event.x_root = 1;
|
|
||||||
event.y_root = 1;
|
|
||||||
event.same_screen = True;
|
|
||||||
|
|
||||||
Window root, child;
|
|
||||||
int root_x, root_y, x, y;
|
|
||||||
unsigned int wanted_mask = 0;
|
|
||||||
unsigned int original_mask;
|
|
||||||
|
|
||||||
XQueryPointer(m_dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &original_mask);
|
|
||||||
|
|
||||||
/* determine keycode and mask for the given keysym */
|
/* determine keycode and mask for the given keysym */
|
||||||
keycode = GetKeycode(keysym, &wanted_mask);
|
keycode = GetKeycode(keysym, &wanted_mask);
|
||||||
@ -773,8 +732,14 @@ void AutoTypePlatformX11::SendKey(KeySym keysym, bool isKeyDown)
|
|||||||
qWarning("Unable to get valid keycode for key: keysym=0x%lX", keysym);
|
qWarning("Unable to get valid keycode for key: keysym=0x%lX", keysym);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
wanted_mask |= modifiers;
|
||||||
|
|
||||||
event.state = original_mask;
|
Window root, child;
|
||||||
|
int root_x, root_y, x, y;
|
||||||
|
unsigned int original_mask;
|
||||||
|
|
||||||
|
XSync(m_dpy, False);
|
||||||
|
XQueryPointer(m_dpy, m_rootWindow, &root, &child, &root_x, &root_y, &x, &y, &original_mask);
|
||||||
|
|
||||||
// modifiers that need to be pressed but aren't
|
// modifiers that need to be pressed but aren't
|
||||||
unsigned int press_mask = wanted_mask & ~original_mask;
|
unsigned int press_mask = wanted_mask & ~original_mask;
|
||||||
@ -785,47 +750,52 @@ void AutoTypePlatformX11::SendKey(KeySym keysym, bool isKeyDown)
|
|||||||
// modifiers we need to release before sending the keycode
|
// modifiers we need to release before sending the keycode
|
||||||
unsigned int release_mask = 0;
|
unsigned int release_mask = 0;
|
||||||
|
|
||||||
// check every release_check_mask individually if it affects the keysym we would generate
|
if (!modifiers) {
|
||||||
// if it doesn't we probably don't need to release it
|
// check every release_check_mask individually if it affects the keysym we would generate
|
||||||
for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
|
// if it doesn't we probably don't need to release it
|
||||||
if (release_check_mask & (1 << mod_index)) {
|
for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
|
||||||
unsigned int mods_rtrn;
|
if (release_check_mask & (1 << mod_index)) {
|
||||||
KeySym keysym_rtrn;
|
unsigned int mods_rtrn;
|
||||||
XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (1 << mod_index), &mods_rtrn, &keysym_rtrn);
|
KeySym keysym_rtrn;
|
||||||
|
XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (1 << mod_index), &mods_rtrn, &keysym_rtrn);
|
||||||
|
|
||||||
if (keysym_rtrn != keysym) {
|
if (keysym_rtrn != keysym) {
|
||||||
release_mask |= (1 << mod_index);
|
release_mask |= (1 << mod_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// finally check if the combination of pressed modifiers that we chose to ignore affects the keysym
|
// finally check if the combination of pressed modifiers that we chose to ignore affects the keysym
|
||||||
unsigned int mods_rtrn;
|
unsigned int mods_rtrn;
|
||||||
KeySym keysym_rtrn;
|
KeySym keysym_rtrn;
|
||||||
XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn);
|
XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn);
|
||||||
if (keysym_rtrn != keysym) {
|
if (keysym_rtrn != keysym) {
|
||||||
// oh well, release all the modifiers we don't want
|
// oh well, release all the modifiers we don't want
|
||||||
|
release_mask = release_check_mask;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
release_mask = release_check_mask;
|
release_mask = release_check_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* release all modifiers */
|
/* set modifiers mask */
|
||||||
SendModifier(&event, release_mask, KeyRelease);
|
if ((release_mask | press_mask) & LockMask) {
|
||||||
|
SendModifiers(LockMask, true);
|
||||||
SendModifier(&event, press_mask, KeyPress);
|
SendModifiers(LockMask, false);
|
||||||
|
|
||||||
/* press and release key */
|
|
||||||
event.keycode = keycode;
|
|
||||||
if (isKeyDown) {
|
|
||||||
SendEvent(&event, KeyPress);
|
|
||||||
} else {
|
|
||||||
SendEvent(&event, KeyRelease);
|
|
||||||
}
|
}
|
||||||
|
SendModifiers(release_mask & ~LockMask, false);
|
||||||
|
SendModifiers(press_mask & ~LockMask, true);
|
||||||
|
|
||||||
/* release the modifiers */
|
/* press and release release key */
|
||||||
SendModifier(&event, press_mask, KeyRelease);
|
SendKeyEvent(keycode, true);
|
||||||
|
SendKeyEvent(keycode, false);
|
||||||
|
|
||||||
/* restore the old keyboard mask */
|
/* restore previous modifiers mask */
|
||||||
SendModifier(&event, release_mask, KeyPress);
|
SendModifiers(press_mask & ~LockMask, false);
|
||||||
|
SendModifiers(release_mask & ~LockMask, true);
|
||||||
|
if ((release_mask | press_mask) & LockMask) {
|
||||||
|
SendModifiers(LockMask, true);
|
||||||
|
SendModifiers(LockMask, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
|
int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
|
||||||
@ -848,12 +818,12 @@ AutoTypeExecutorX11::AutoTypeExecutorX11(AutoTypePlatformX11* platform)
|
|||||||
|
|
||||||
void AutoTypeExecutorX11::execChar(AutoTypeChar* action)
|
void AutoTypeExecutorX11::execChar(AutoTypeChar* action)
|
||||||
{
|
{
|
||||||
m_platform->SendKeyPressedEvent(m_platform->charToKeySym(action->character));
|
m_platform->SendKey(m_platform->charToKeySym(action->character));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTypeExecutorX11::execKey(AutoTypeKey* action)
|
void AutoTypeExecutorX11::execKey(AutoTypeKey* action)
|
||||||
{
|
{
|
||||||
m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(action->key));
|
m_platform->SendKey(m_platform->keyToKeySym(action->key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTypeExecutorX11::execClearField(AutoTypeClearField* action = nullptr)
|
void AutoTypeExecutorX11::execClearField(AutoTypeClearField* action = nullptr)
|
||||||
@ -864,19 +834,13 @@ void AutoTypeExecutorX11::execClearField(AutoTypeClearField* action = nullptr)
|
|||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 25 * 1000 * 1000;
|
ts.tv_nsec = 25 * 1000 * 1000;
|
||||||
|
|
||||||
m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Control), true);
|
m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Home), static_cast<unsigned int>(ControlMask));
|
||||||
m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(Qt::Key_Home));
|
|
||||||
m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Control), false);
|
|
||||||
nanosleep(&ts, nullptr);
|
nanosleep(&ts, nullptr);
|
||||||
|
|
||||||
m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Control), true);
|
m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_End), static_cast<unsigned int>(ControlMask | ShiftMask));
|
||||||
m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Shift), true);
|
|
||||||
m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(Qt::Key_End));
|
|
||||||
m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Shift), false);
|
|
||||||
m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Control), false);
|
|
||||||
nanosleep(&ts, nullptr);
|
nanosleep(&ts, nullptr);
|
||||||
|
|
||||||
m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(Qt::Key_Backspace));
|
m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Backspace));
|
||||||
nanosleep(&ts, nullptr);
|
nanosleep(&ts, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,8 +58,7 @@ public:
|
|||||||
KeySym charToKeySym(const QChar& ch);
|
KeySym charToKeySym(const QChar& ch);
|
||||||
KeySym keyToKeySym(Qt::Key key);
|
KeySym keyToKeySym(Qt::Key key);
|
||||||
|
|
||||||
void SendKeyPressedEvent(KeySym keysym);
|
void SendKey(KeySym keysym, unsigned int modifiers = 0);
|
||||||
void SendKey(KeySym keysym, bool isKeyDown);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void globalShortcutTriggered();
|
void globalShortcutTriggered();
|
||||||
@ -80,8 +79,8 @@ private:
|
|||||||
bool isRemapKeycodeValid();
|
bool isRemapKeycodeValid();
|
||||||
int AddKeysym(KeySym keysym);
|
int AddKeysym(KeySym keysym);
|
||||||
void AddModifier(KeySym keysym);
|
void AddModifier(KeySym keysym);
|
||||||
void SendEvent(XKeyEvent* event, int event_type);
|
void SendKeyEvent(unsigned keycode, bool press);
|
||||||
void SendModifier(XKeyEvent *event, unsigned int mask, int event_type);
|
void SendModifiers(unsigned int mask, bool press);
|
||||||
int GetKeycode(KeySym keysym, unsigned int *mask);
|
int GetKeycode(KeySym keysym, unsigned int *mask);
|
||||||
bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask);
|
bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user