Skip to content

Commit e8cf018

Browse files
danislavasily-v-ryabov
authored andcommitted
XFixes: add support for XFixesCursorNotify
1 parent c9d2428 commit e8cf018

File tree

2 files changed

+132
-1
lines changed

2 files changed

+132
-1
lines changed

Xlib/ext/xfixes.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,23 @@
2525
ShowCursor requests and SelectionNotify events are provided.
2626
'''
2727

28-
from Xlib.protocol import rq
28+
from Xlib import X
29+
from Xlib.protocol import rq, structs
2930

3031
extname = 'XFIXES'
3132

3233
XFixesSelectionNotify = 0
34+
XFixesCursorNotify = 1
3335

3436
XFixesSetSelectionOwnerNotifyMask = (1 << 0)
3537
XFixesSelectionWindowDestroyNotifyMask = (1 << 1)
3638
XFixesSelectionClientCloseNotifyMask = (1 << 2)
39+
XFixesDisplayCursorNotifyMask = (1 << 0)
3740

3841
XFixesSetSelectionOwnerNotify = 0
3942
XFixesSelectionWindowDestroyNotify = 1
4043
XFixesSelectionClientCloseNotify = 2
44+
XFixesDisplayCursorNotify = 0
4145

4246
class QueryVersion(rq.ReplyRequest):
4347
_request = rq.Struct(rq.Card8('opcode'),
@@ -131,12 +135,67 @@ class SelectionClientCloseNotify(SelectionNotify):
131135
pass
132136

133137

138+
class SelectCursorInput(rq.Request):
139+
_request = rq.Struct(rq.Card8('opcode'),
140+
rq.Opcode(3),
141+
rq.RequestLength(),
142+
rq.Window('window'),
143+
rq.Card32('mask')
144+
)
145+
146+
def select_cursor_input(self, window, mask):
147+
return SelectCursorInput(opcode=self.display.get_extension_major(extname),
148+
display=self.display,
149+
window=window,
150+
cursor_serial=0,
151+
mask=mask)
152+
153+
154+
class GetCursorImage(rq.ReplyRequest):
155+
_request = rq.Struct(rq.Card8('opcode'),
156+
rq.Opcode(4),
157+
rq.RequestLength()
158+
)
159+
_reply = rq.Struct(rq.ReplyCode(),
160+
rq.Pad(1),
161+
rq.Card16('sequence_number'),
162+
rq.ReplyLength(),
163+
rq.Int16('x'),
164+
rq.Int16('y'),
165+
rq.Card16('width'),
166+
rq.Card16('height'),
167+
rq.Card16('xhot'),
168+
rq.Card16('yhot'),
169+
rq.Card32('cursor_serial'),
170+
rq.Pad(8),
171+
rq.List('cursor_image', rq.Card32)
172+
)
173+
174+
def get_cursor_image(self, window):
175+
return GetCursorImage(opcode=self.display.get_extension_major(extname),
176+
display=self.display,
177+
)
178+
179+
180+
class DisplayCursorNotify(rq.Event):
181+
_code = None
182+
_fields = rq.Struct(rq.Card8('type'),
183+
rq.Card8('sub_code'),
184+
rq.Card16('sequence_number'),
185+
rq.Window('window'),
186+
rq.Card32('cursor_serial'),
187+
rq.Card32('timestamp'))
188+
189+
134190
def init(disp, info):
135191
disp.extension_add_method('display', 'xfixes_select_selection_input', select_selection_input)
136192
disp.extension_add_method('display', 'xfixes_query_version', query_version)
137193
disp.extension_add_method('window', 'xfixes_hide_cursor', hide_cursor)
138194
disp.extension_add_method('window', 'xfixes_show_cursor', show_cursor)
195+
disp.extension_add_method('display', 'xfixes_select_cursor_input', select_cursor_input)
196+
disp.extension_add_method('display', 'xfixes_get_cursor_image', get_cursor_image)
139197

140198
disp.extension_add_subevent(info.first_event + XFixesSelectionNotify, XFixesSetSelectionOwnerNotify, SetSelectionOwnerNotify)
141199
disp.extension_add_subevent(info.first_event + XFixesSelectionNotify, XFixesSelectionWindowDestroyNotify, SelectionWindowDestroyNotify)
142200
disp.extension_add_subevent(info.first_event + XFixesSelectionNotify, XFixesSelectionClientCloseNotify, SelectionClientCloseNotify)
201+
disp.extension_add_subevent(info.first_event + XFixesCursorNotify, XFixesDisplayCursorNotify, DisplayCursorNotify)

examples/xfixes-cursor-notify.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/python3
2+
#
3+
# examples/xfixes-cursor-notify.py -- demonstrate the XFIXES extension
4+
# CursorNotify event.
5+
#
6+
# Copyright (C) 2022
7+
# Dan Isla <dan.isla@gmail.com>
8+
#
9+
# This library is free software; you can redistribute it and/or
10+
# modify it under the terms of the GNU Lesser General Public License
11+
# as published by the Free Software Foundation; either version 2.1
12+
# of the License, or (at your option) any later version.
13+
#
14+
# This library is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17+
# See the GNU Lesser General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU Lesser General Public
20+
# License along with this library; if not, write to the
21+
# Free Software Foundation, Inc.,
22+
# 59 Temple Place,
23+
# Suite 330,
24+
# Boston, MA 02111-1307 USA
25+
26+
# Python 2/3 compatibility.
27+
from __future__ import print_function
28+
29+
import sys
30+
from Xlib.display import Display
31+
from Xlib.ext import xfixes
32+
33+
def main():
34+
display = Display()
35+
36+
if not display.has_extension('XFIXES'):
37+
if display.query_extension('XFIXES') is None:
38+
print('XFIXES extension not supported')
39+
return 1
40+
41+
xfixes_version = display.xfixes_query_version()
42+
print('Found XFIXES version {}.{}'.format(
43+
xfixes_version.major_version,
44+
xfixes_version.minor_version
45+
))
46+
47+
screen = display.screen()
48+
49+
display.xfixes_select_cursor_input(screen.root, xfixes.XFixesDisplayCursorNotifyMask)
50+
51+
cursor_cache = {}
52+
53+
while True:
54+
e = display.next_event()
55+
print(e)
56+
57+
if (e.type, e.sub_code) == display.extension_event.DisplayCursorNotify:
58+
print("DisplayCursorNotify: cursor_serial={}".format(e.cursor_serial))
59+
image = display.xfixes_get_cursor_image(screen.root)
60+
cached = False
61+
if cursor_cache.get(image.cursor_serial):
62+
cached = True
63+
else:
64+
cursor_cache[image.cursor_serial] = image.cursor_image
65+
66+
print("Cursor position={},{}, size={}x{}, xyhot={},{}, cursor_serial={}, cached={}".format(
67+
image.x, image.y, image.width,image.height, image.xhot, image.yhot, image.cursor_serial, cached
68+
))
69+
70+
71+
if __name__ == "__main__":
72+
sys.exit(main())

0 commit comments

Comments
 (0)