diff options
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp')
| -rw-r--r-- | Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp | 79 |
1 files changed, 50 insertions, 29 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp index 9ec1c2be35..dac0c085fa 100644 --- a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp @@ -97,11 +97,11 @@ void PopulateDevices(void* const hwnd) // Apply the event mask to the device and all its slaves. Only used in the // constructor. Remember, each KeyboardMouse has its own copy of the event // stream, which is how multiple event masks can "coexist." -void KeyboardMouse::SelectEventsForDevice(Window window, XIEventMask* mask, int deviceid) +void KeyboardMouse::SelectEventsForDevice(XIEventMask* mask, int deviceid) { // Set the event mask for the master device. mask->deviceid = deviceid; - XISelectEvents(m_display, window, mask, 1); + XISelectEvents(m_display, DefaultRootWindow(m_display), mask, 1); // Query all the master device's slaves and set the same event mask for // those too. There are two reasons we want to do this. For mouse devices, @@ -109,20 +109,19 @@ void KeyboardMouse::SelectEventsForDevice(Window window, XIEventMask* mask, int // devices) emit those. For keyboard devices, selecting slaves avoids // dealing with key focus. - XIDeviceInfo* all_slaves; - XIDeviceInfo* current_slave; int num_slaves; - - all_slaves = XIQueryDevice(m_display, XIAllDevices, &num_slaves); + XIDeviceInfo* const all_slaves = XIQueryDevice(m_display, XIAllDevices, &num_slaves); for (int i = 0; i < num_slaves; i++) { - current_slave = &all_slaves[i]; - if ((current_slave->use != XISlavePointer && current_slave->use != XISlaveKeyboard) || - current_slave->attachment != deviceid) + XIDeviceInfo* const slave = &all_slaves[i]; + if ((slave->use != XISlavePointer && slave->use != XISlaveKeyboard) || + slave->attachment != deviceid) + { continue; - mask->deviceid = current_slave->deviceid; - XISelectEvents(m_display, window, mask, 1); + } + mask->deviceid = slave->deviceid; + XISelectEvents(m_display, DefaultRootWindow(m_display), mask, 1); } XIFreeDeviceInfo(all_slaves); @@ -138,34 +137,44 @@ KeyboardMouse::KeyboardMouse(Window window, int opcode, int pointer, int keyboar // "context." m_display = XOpenDisplay(nullptr); - int min_keycode, max_keycode; - XDisplayKeycodes(m_display, &min_keycode, &max_keycode); - - int unused; // should always be 1 - XIDeviceInfo* pointer_device = XIQueryDevice(m_display, pointer_deviceid, &unused); + // should always be 1 + int unused; + XIDeviceInfo* const pointer_device = XIQueryDevice(m_display, pointer_deviceid, &unused); name = std::string(pointer_device->name); XIFreeDeviceInfo(pointer_device); - XIEventMask mask; - unsigned char mask_buf[(XI_LASTEVENT + 7) / 8]; + { + unsigned char mask_buf[(XI_LASTEVENT + 7) / 8] = {}; + XISetMask(mask_buf, XI_ButtonPress); + XISetMask(mask_buf, XI_ButtonRelease); + XISetMask(mask_buf, XI_RawMotion); + + XIEventMask mask; + mask.mask = mask_buf; + mask.mask_len = sizeof(mask_buf); - mask.mask_len = sizeof(mask_buf); - mask.mask = mask_buf; - memset(mask_buf, 0, sizeof(mask_buf)); + SelectEventsForDevice(&mask, pointer_deviceid); + } + + { + unsigned char mask_buf[(XI_LASTEVENT + 7) / 8] = {}; + XISetMask(mask_buf, XI_KeyPress); + XISetMask(mask_buf, XI_KeyRelease); + XISetMask(mask_buf, XI_FocusOut); - XISetMask(mask_buf, XI_ButtonPress); - XISetMask(mask_buf, XI_ButtonRelease); - XISetMask(mask_buf, XI_RawMotion); - XISetMask(mask_buf, XI_KeyPress); - XISetMask(mask_buf, XI_KeyRelease); + XIEventMask mask; + mask.mask = mask_buf; + mask.mask_len = sizeof(mask_buf); - SelectEventsForDevice(DefaultRootWindow(m_display), &mask, pointer_deviceid); - SelectEventsForDevice(DefaultRootWindow(m_display), &mask, keyboard_deviceid); + SelectEventsForDevice(&mask, keyboard_deviceid); + } // Keyboard Keys + int min_keycode, max_keycode; + XDisplayKeycodes(m_display, &min_keycode, &max_keycode); for (int i = min_keycode; i <= max_keycode; ++i) { - Key* temp_key = new Key(m_display, i, m_state.keyboard); + Key* const temp_key = new Key(m_display, i, m_state.keyboard.data()); if (temp_key->m_keyname.length()) AddInput(temp_key); else @@ -284,6 +293,10 @@ void KeyboardMouse::UpdateInput() delta_y += delta_delta; } break; + case XI_FocusOut: + // Clear keyboard state on FocusOut as we will not be receiving KeyRelease events. + m_state.keyboard.fill(0); + break; } XFreeEventData(m_display, &event.xcookie); @@ -300,6 +313,14 @@ void KeyboardMouse::UpdateInput() // Get the absolute position of the mouse pointer if (mouse_moved) UpdateCursor(); + + // KeyRelease and FocusOut events are sometimes not received. + // Cycling Alt-Tab and landing on the same window results in a stuck "Alt" key. + // Unpressed keys are released here. + std::array<char, 32> keyboard; + XQueryKeymap(m_display, keyboard.data()); + for (size_t i = 0; i != keyboard.size(); ++i) + m_state.keyboard[i] &= keyboard[i]; } std::string KeyboardMouse::GetName() const |
