New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create virtual input device to allow the use of kloak #194
Conversation
…ents are working. Mouse events are not currently. Having trouble with getting the cursor into the right position.
When the input device is created, notifications are generated mentioning that qubes.InputKeyboard and qubes.InputMouse were denied originating from the qube that started. The input device still works fine. This pull request in qubes-app-linux-input-proxy repository stops qubes-input-trigger from running on the virtual input device created, preventing the notifications from being triggered. |
You may want to use a device with absolute events ( |
I'll get those changes implemented. One thing I forgot is that I had to add user to the input group so that xinit had enough permissions to be able to access the device. I'll find the correct repository to implement that and send a pull for that as well. This pull request will be dependent on that request as well once it's in. |
It's probably just about adding appropriate udev rule, it can be done in this repo. |
… to user so xinit can access the device when it's created
…the qvm-service 'gui-agent-virtual-input-device'
…tual input device creation was requested or not.
OpenQA test summaryComplete test suite and dependencies: https://openqa.qubes-os.org/tests/overview?distri=qubesos&version=4.2&build=2023091804-4.2&flavor=pull-requests New failures, excluding unstableCompared to: https://openqa.qubes-os.org/tests/overview?distri=qubesos&version=4.2&build=2023071104-4.2&flavor=update
Failed tests8 failures
Fixed failuresCompared to: https://openqa.qubes-os.org/tests/77326#dependencies 23 fixed
Unstable tests
|
gui-agent/vmside.c
Outdated
|
||
feed_xdriver(g, 'K', key.keycode, key.type == KeyPress ? 1 : 0); | ||
|
||
if(!g->createdInputDevice) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But this way, modifiers are set using Xorg-internal keyboard, while actual key using uinput. It's asking for race conditions, if it works at all (I haven't checked).
Consider following scenario:
- You press (and hold) shift
- You switch window focus (with a mouse for example)
- You press and release
A
- You release shift
What should happen, is the VM seeing:
- press shift
- press A
- release A
- release shift
On the same input device.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I adjusted it now so when virtual input device creation has been requested, modifiers are synced through the uinput fd instead of the xserver fd.
They are completely separate from each other now:
if(virtual input device NOT requested){
// original handle_keypress
} else {
// new handle_keypress (only writes to the uinput fd, never to the xserver fd)
}
Before these changes, all of the modifiers worked correctly when switching between qubes, except when pressing down the modifier and switching into a qube.
Now, all of the following scenarios work as expected:
Start in qube 1
Hold down shift
Switch to qube 2
Start typing while still holding down shift
This results in uppercase characters being typed out into qube 2 as expected
Start in qube 1
Hold down shift
Switch to qube 2
Release shift
Switch back to qube 1
Start typing
This results in lowercase characters being typed out into qube 1 as expected
Open a text file in nano in qube 1
Switch to qube 2
Hold down ctrl
Switch back to qube 1
Press s while still holding down ctrl
nano receives a ctrl+s and attempts to save the file
Modifiers still work exactly as expected when not switching between qubes as well.
… to get that in this PR and will work on it in a future one
… the same naming convention as other variables
…esigned for the virtual input device. When input device creation is requested, modifier sync now happens through the uinput_fd instead of the xserver_fd. All modifiers are working as expected when switching between qubes.
I adjusted it now so when virtual input device creation has been requested, modifiers are synced through the uinput fd instead of the xserver fd. They are completely separate from each other now: if(virtual input device NOT requested){ Before these changes, all of the modifiers worked correctly when switching between qubes, except when pressing down the modifier and switching into a qube. Now, all of the following scenarios work as expected: Start in qube 1 Start in qube 1 Open a text file in nano in qube 1 Modifiers still work exactly as expected when not switching between qubes as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functionally it looks mostly fine now (with remarks below). But last commits introduced several repeated blank lines and whitespaces at the end of empty lines. There is also small merge conflict now, please rebase on the updated main branch.
@@ -0,0 +1 @@ | |||
ATTRS{name}=="Qubes Virtual Input Device", ACTION=="add", GROUP="user" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is not installed anywhere (add it to makefile, and then both rpm spec file and debian "install" file).
And it should be GROUP="qubes"
gui-agent/vmside.c
Outdated
@@ -285,6 +295,29 @@ static int compare_supported_cursors(const void *a, | |||
((struct supported_cursor *)b)->name); | |||
} | |||
|
|||
|
|||
void send_event(Ghandles * g, const struct input_event *iev) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
void send_event(Ghandles * g, const struct input_event *iev) { | |
static void send_event(Ghandles * g, const struct input_event *iev) { |
gui-agent/vmside.c
Outdated
|
||
// set all keys | ||
for(int i = 1; i < KEY_MAX; i++) { | ||
if(i != KEY_RESERVED && ioctl(g.uinput_fd, UI_SET_KEYBIT, i) < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With all keys set, udev (and so Xorg) detects this as a combo keyboard+mouse device now. See udevadm info -q all -n /dev/input/event1
(or whatever device node it will get). It should not have ID_INPUT_MOUSE
set. I guess you need to exclude BTN_*
range (BTN_MISC
.. BTN_GEAR_UP
- various buttons of mouses, tablets, game pads etc)
… to install the file in Makefile, appvm-scripts/lib/udev/rules.d/90-qubes-virtual-input-device.rules, debian/qubes-gui-agent.install, and rpm_spec/gui-agent.spec.in
You still need to rebase to resolve the conflict. |
…solved. Removed that line since the variable is unused and stops the build
It should be all set now. |
I did some more tests and Caps Lock behaves funny. When it's enabled, only some letter are capital, not all. But disabling it when the VM has focus doesn't seems to work (then, all letters typed into VM are capital). I guess it's related to modifiers sync, as this one is press-and-release to change the state, not press-and-hold. |
…n states and needs to be excluded from the key send below
Got it working now. The line to flip its associated bit in last_known_modifier_states was missing and caps lock needed to be excluded from key press/release below. |
iev.type = EV_KEY; | ||
// only used in here to see if modifier is disabled | ||
XModifierKeymap *modmap; | ||
modmap = XGetModifierMapping(g->display); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to handle also when this call fails (see above).
gui-agent/vmside.c
Outdated
} | ||
} | ||
} | ||
|
||
if(key.keycode-8 != KEY_CAPSLOCK) { | ||
XFreeModifiermap(modmap); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
freeing should be outside of this if, no?
…f the if statement checking if the current keycode is capslock.
Partial resolution of issue QubesOS/qubes-issues#1850. Keyboard events are sent to the virtual input device, but mouse events are not yet.
This creates an input device with the name "Qubes Virtual Input Device" on gui agent startup and translates KeyPress events into EV_KEY events and writes them to /dev/uinput. This allows the use of kloak within a qube.
Mouse events are currently not translated or written to /dev/uinput yet as I'm having trouble getting the cursor in the right location, they are still handled by the feed_xdriver function.