-
-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(linux): Implement ordered output sentinel in keyman-system-s…
…ervice This change allows to press F24 as ordered output sentinel from keyman-system-service. This is part of implementing serialized output with keyman-system-service instead of requiring a patched ibus. The problem both approaches try to solve is that with non-compliant apps it is not possible to directly delete characters from the context. Instead we have to emit a backspace key before we can commit the new characters. However, the backspace key press goes through a different code path in ibus and so it can happen that the commit gets processed before the backspace which then deletes from the characters we just added instead of from the old content. The previous implementation solved this by forwarding a F24 ordered output sentinel key to ibus and relying on the patched ibus to send that back to us. When we received the F24 key we committed the characters that we queued when we forwarded the F24 key (implemented in #7079). The new approach implemented in this change instead sends the F24 ordered output sentinel key through keyman-system-service and so follows the regular key processing without requiring a patched ibus to send the key back to us. The rest of the algorithm stays the same: when we receive the F24 key we commit the characters previously queued. Part of #10799.
- Loading branch information
1 parent
071b178
commit 1212710
Showing
10 changed files
with
188 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#include <dirent.h> | ||
#include <fcntl.h> | ||
#include <iostream> | ||
#include <string.h> | ||
#include <string> | ||
#include <syslog.h> | ||
#include <unistd.h> | ||
#include "OrderOutputDevice.h" | ||
|
||
using namespace std; | ||
|
||
#define KEYMAN_F24_KEYCODE_OUTPUT_SENTINEL 194 // 0xC2 | ||
|
||
OrderOutputDevice::OrderOutputDevice() { | ||
uinput_dev = nullptr; | ||
} | ||
|
||
OrderOutputDevice::~OrderOutputDevice() { | ||
Close(); | ||
} | ||
|
||
void | ||
OrderOutputDevice::Close() { | ||
if (uinput_dev) { | ||
libevdev_uinput_destroy(uinput_dev); | ||
uinput_dev = nullptr; | ||
} | ||
} | ||
|
||
bool | ||
OrderOutputDevice::Initialize() { | ||
struct libevdev* dev; | ||
|
||
syslog(LOG_USER | LOG_ALERT, "%s: creating fake device", __FUNCTION__); | ||
|
||
dev = libevdev_new(); | ||
libevdev_set_name(dev, "Ordered Output Keyman Keyboard Device"); | ||
|
||
libevdev_enable_event_type(dev, EV_KEY); | ||
|
||
// F24 is the only key we support. | ||
libevdev_enable_event_code(dev, EV_KEY, KEYMAN_F24_KEYCODE_OUTPUT_SENTINEL, NULL); | ||
|
||
int rc = libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uinput_dev); | ||
if (rc < 0) { | ||
syslog(LOG_USER | LOG_ERR, "%s: Failed to create Ordered Output keyman keyboard device: %s", | ||
__FUNCTION__, strerror(-rc)); | ||
libevdev_free(dev); | ||
Close(); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
bool | ||
OrderOutputDevice::PressSentinelKey(bool isKeyDown) { | ||
int error = libevdev_uinput_write_event(uinput_dev, EV_KEY, KEYMAN_F24_KEYCODE_OUTPUT_SENTINEL, | ||
isKeyDown ? 1 : 0); | ||
if (error < 0) { | ||
syslog(LOG_USER | LOG_ERR, | ||
"%s: Error writing send key event for sentinel key (down: %d): %s", | ||
__FUNCTION__, isKeyDown, strerror(-error)); | ||
return false; | ||
} | ||
error = libevdev_uinput_write_event(uinput_dev, EV_SYN, SYN_REPORT, 0); | ||
if (error < 0) { | ||
syslog(LOG_USER | LOG_ERR, | ||
"%s: Error writing syn event for sentinel key (down: %d): %s", | ||
__FUNCTION__, isKeyDown, strerror(-error)); | ||
return false; | ||
} | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#ifndef __ORDEROUTPUTDEVICE_H__ | ||
#define __ORDEROUTPUTDEVICE_H__ | ||
|
||
#include <libevdev/libevdev-uinput.h> | ||
|
||
// The fake keyboard we use to force the serializing of the output (#10799/#7079) | ||
// Generate a fake key event to get the correct order of events so that any backspace key we | ||
// generated will be processed before the character we're adding. We need to send a | ||
// valid keycode so that it doesn't get swallowed by GTK but which isn't very likely used | ||
// in real keyboards. F24 seems to work for that. | ||
class OrderOutputDevice { | ||
public: | ||
OrderOutputDevice(); | ||
virtual ~OrderOutputDevice(); | ||
|
||
bool Initialize(); | ||
bool PressSentinelKey(bool isKeyDown); | ||
|
||
private: | ||
void Close(); | ||
struct libevdev_uinput *uinput_dev; | ||
}; | ||
|
||
#endif // __ORDEROUTPUTDEVICE_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
service_files = files( | ||
'KeyboardDevice.cpp', | ||
'KeymanSystemService.cpp', | ||
'OrderOutputDevice.cpp', | ||
'main.cpp', | ||
) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters