Open elParaguayo opened 12 months ago
Yeah, I agree that it looks like BarrierHitEvent won't work since its opcode is too high. What problems were you having with SendEvent, though? The man page says it should work with extension events too.
Thanks for the reply.
The problem is my handle_BarrierHit
method is not called at all after sending the event. Current code is here: https://github.com/elParaguayo/qtile/blob/pointer-barrier-test/test/backend/x11/test_pointer_barriers.py
I'm not entirely sure what I should put for the mask
value here (I've tried with xcffib.xinput.XIEventMask.BarrierHit
and that doesn't work either).
Hum, I'll take a little bit later today. I think you have to use xproto.EventMask.* with SendEvent, but it's not obvious to me which one of those barrier corresponds to:
https://tronche.com/gui/x/xlib/events/mask.html
Maybe try to set all the bits and see?
Didn't work with all of those set either sadly.
I've got an idea what the problem might be. Let me test something.
Didn't work. I tried to use the GeGenericEvent
(that gets hoisted to the correct event by xcffib) and send that instead but it's still not working. That's also an xge event though...
Yeah, just reading the code it looks like it maybe won't work, in spite of what the man page says. Sorry, I didn't get a chance to look last night, perhaps later this week.
No problem at all. Appreciate you taking a look. Happy to work on a fix if there is a problem within xcffib
.
Hi, just wanted to say that I have not forgotten about this :). Here is a smaller xcffib test case:
diff --git a/test/test_barrier_hit.py b/test/test_barrier_hit.py
new file mode 100644
index 0000000..718cc7a
--- /dev/null
+++ b/test/test_barrier_hit.py
@@ -0,0 +1,40 @@
+import xcffib
+import xcffib.xproto
+import xcffib.xinput
+
+from .conftest import XcffibTest
+
+class TestPythonCode:
+
+ def test_send_BarrierHitEvent(self, xcffib_test):
+ conn = xcffib_test
+ barrier = 5
+ event = xcffib.xinput.BarrierHitEvent.synthetic(
+ 2,
+ xcffib.xproto.Time.CurrentTime,
+ 1,
+ conn.default_screen.root,
+ conn.default_screen.root,
+ barrier,
+ 0,
+ 0,
+ 11,
+ 799 << 16,
+ 100 << 16,
+ (0, 0),
+ (0, 0)
+ )
+ mask = xcffib.xproto.EventMask.NoEvent
+ xinput = xcffib_test.conn(xcffib.xinput.key)
+ print(conn.conn._event_offsets.offsets)
+ xinput.SendExtensionEventChecked(
+ conn.default_screen.root,
+ 1, # device id
+ True,
+ 1,
+ 1,
+ [event.pack()],
+ [66+24]
+ ).check()
+ conn.conn.core.GetInputFocus().reply()
+ assert False
Which I've been using with these (manual) patches to the bindings:
--- xinput.py 2023-11-17 07:34:29.110212168 -0700
+++ xinput.py.patched 2023-11-17 07:34:38.778375457 -0700
@@ -3896,11 +3896,11 @@
unpacker.pad(FP3232)
self.dy = FP3232(unpacker)
self.bufsize = unpacker.offset - base
def pack(self):
buf = io.BytesIO()
- buf.write(struct.pack("=B", 25))
+ buf.write(struct.pack("=B", 66+25))
buf.write(struct.pack("=x2xHIIIIIIIH2xii", self.deviceid, self.time, self.eventid, self.root, self.event, self.barrier, self.dtime, self.flags, self.sourceid, self.root_x, self.root_y))
buf.write(self.dx.pack() if hasattr(self.dx, "pack") else FP3232.synthetic(*self.dx).pack())
buf.write(self.dy.pack() if hasattr(self.dy, "pack") else FP3232.synthetic(*self.dy).pack())
buf_len = len(buf.getvalue())
if buf_len < 32:
@@ -4333,9 +4333,9 @@
buf.write(xcffib.pack_list(barriers, BarrierReleasePointerInfo))
return self.send_request(61, buf, is_checked=is_checked)
def SendExtensionEvent(self, destination, device_id, propagate, num_classes, num_events, events, classes, is_checked=False):
buf = io.BytesIO()
buf.write(struct.pack("=xx2xIBBHB3x", destination, device_id, propagate, num_classes, num_events))
- buf.write(xcffib.pack_list(events, EventForSend))
+ buf.write(xcffib.pack_list(events, BarrierHitEvent))
buf.write(xcffib.pack_list(classes, "I"))
return self.send_request(31, buf, is_checked=is_checked)
xcffib._add_ext(key, xinputExtension, _events, _errors)
I've managed to crash xtrace,
[433633.963184] xtrace[249393]: segfault at c ip 00005558f33296f7 sp 00007ffd89f4d5f0 error 4 in xtrace[5558f3326000+10000]
so I guess they're not quite as good as the actual x server, which renders a LengthError. In any case, the x server really doesn't accept variable length events here, so the comment from the xml is right.
googling around a little bit, these patches do not seem like they ever landed: https://xorg-devel.x.narkive.com/OPQdsFiP/handling-genericevents-in-xsendevent#post9
so maybe it's just not possible right now? anyway, I will keep digging. maybe we need to write some xserver code to make it work.
I've got an open PR in qtile (https://github.com/qtile/qtile/pull/4557) using PointerBarriers from xfixes and xinput. I'd like to write a test for this and have had limited success using
FakeInput
from xtest. I was hoping I could just send a synthetic event but have had no joy with that either.I see xinput has
SendExtensionEvent
which sounds promising but I'm not clear how to use it. Do I need to put the event into a buffer object rather than passing the packed data? I also have no idea whatclasses
(https://gitlab.freedesktop.org/xorg/proto/xcbproto/-/blob/master/src/xinput.xml?ref_type=heads#L2725) are meant to be.Lastly, I'm also concerned that this won't at all as the notes on xcbproto suggest we can't send xge events which would include the
BarrierHitEvent
.Any tips would be greatly appreciated.