Skip to content

Commit ec71413

Browse files
committed
Extension interface, error callbacks, incorrect threading code
1 parent 224b6fb commit ec71413

12 files changed

Lines changed: 697 additions & 164 deletions

File tree

Xlib/display.py

Lines changed: 182 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: display.py,v 1.4 2000-08-08 09:55:18 petli Exp $
1+
# $Id: display.py,v 1.5 2000-08-21 10:03:45 petli Exp $
22
#
33
# Xlib.display -- high level display object
44
#
@@ -18,9 +18,12 @@
1818
# along with this program; if not, write to the Free Software
1919
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2020

21+
# Python modules
22+
import new
2123

2224
# Xlib modules
2325
import error
26+
import ext
2427

2528
# Xlib.protocol modules
2629
import protocol.display
@@ -33,22 +36,66 @@
3336
import xobject.colormap
3437
import xobject.cursor
3538

39+
_resource_baseclasses = {
40+
'resource': xobject.resource.Resource,
41+
'drawable': xobject.drawable.Drawable,
42+
'window': xobject.drawable.Window,
43+
'pixmap': xobject.drawable.Pixmap,
44+
'fontable': xobject.fontable.Fontable,
45+
'font': xobject.fontable.Font,
46+
'gc': xobject.fontable.GC,
47+
'colormap': xobject.colormap.Colormap,
48+
'cursor': xobject.cursor.Cursor,
49+
}
50+
51+
_resource_hierarchy = {
52+
'resource': ('drawable', 'window', 'pixmap',
53+
'fontable', 'font', 'gc',
54+
'colormap', 'cursor'),
55+
'drawable': ('window', 'pixmap'),
56+
'fontable': ('font', 'gc')
57+
}
58+
3659
class _BaseDisplay(protocol.display.Display):
37-
resource_classes = {
38-
'resource': xobject.resource.Resource,
39-
'drawable': xobject.drawable.Drawable,
40-
'window': xobject.drawable.Window,
41-
'pixmap': xobject.drawable.Pixmap,
42-
'font': xobject.fontable.Font,
43-
'gc': xobject.fontable.GC,
44-
'colormap': xobject.colormap.Colormap,
45-
'cursor': xobject.cursor.Cursor,
46-
}
47-
60+
resource_classes = _resource_baseclasses.copy()
61+
4862
class Display:
4963
def __init__(self, display = None):
5064
self.display = _BaseDisplay(display)
5165

66+
# Find all supported extensions
67+
self.extensions = self.list_extensions()
68+
self.class_extension_dicts = {}
69+
70+
# Go through all extension modules
71+
for extname, modname in ext.__extensions__:
72+
if extname in self.extensions:
73+
74+
# Import the module and fetch it
75+
__import__('Xlib.ext.' + modname)
76+
mod = getattr(ext, modname)
77+
78+
info = self.query_extension(extname)
79+
self.display.set_extension_major(extname, info.major_opcode)
80+
81+
# Call initialiasation function
82+
mod.init(self, info)
83+
84+
# Finalize extensions by creating new classes
85+
for type, dict in self.class_extension_dicts.items():
86+
origcls = self.display.resource_classes[type]
87+
self.display.resource_classes[type] = new.classobj(origcls.__name__,
88+
(origcls,),
89+
dict)
90+
91+
# Problem: we have already created some objects without the
92+
# extensions: the screen roots and default colormaps.
93+
# Fix that by reinstantiating them.
94+
for screen in self.display.info.roots:
95+
screen.root = self.display.resource_classes['window'](self.display, screen.root.id)
96+
screen.default_colormap = self.display.resource_classes['colormap'](self.display, screen.default_colormap.id)
97+
98+
5299
def fileno(self):
53100
return self.display.fileno()
54101

@@ -58,6 +105,11 @@ def close(self):
58105
def flush(self):
59106
self.display.flush()
60107

108+
def sync(self):
109+
# Do a light-weight replyrequest to sync. There must
110+
# be a better way to do it...
111+
self.get_pointer_control()
112+
61113
def next_event(self):
62114
return self.display.next_event()
63115

@@ -73,7 +125,72 @@ def screen(self, sno = None):
73125
return self.display.info.roots[self.display.default_screen]
74126
else:
75127
return self.display.info.roots[sno]
76-
128+
129+
###
130+
### Extension module interface
131+
###
132+
133+
def extension_add_method(self, object, name, function):
134+
"""extension_add_method(object, name, function)
135+
136+
Add an X extension module method. OBJECT is the type of
137+
object to add the function to, a string from this list:
138+
139+
display
140+
resource
141+
drawable
142+
window
143+
pixmap
144+
fontable
145+
font
146+
gc
147+
colormap
148+
cursor
149+
150+
NAME is the name of the method, a string. FUNCTION is a
151+
normal function whose first argument is a 'self'.
152+
"""
153+
154+
if object == 'display':
155+
if hasattr(self, name):
156+
raise error.MethodOverrideError('attempting to replace display method: %s' % name)
157+
158+
setattr(self, name, new.instancemethod(function, self, self.__class__))
159+
160+
else:
161+
types = (object, ) + _resource_hierarchy.get(object, ())
162+
for type in types:
163+
cls = _resource_baseclasses[type]
164+
if hasattr(cls, name):
165+
raise error.MethodOverrideError('attempting to replace %s method: %s' % (type, name))
166+
167+
method = new.instancemethod(function, None, cls)
168+
169+
# Maybe should check extension overrides too
170+
try:
171+
self.class_extension_dicts[type][name] = method
172+
except KeyError:
173+
self.class_extension_dicts[type] = { name: method }
174+
175+
def add_extension_event(self, code, evt):
176+
"""add_extension_event(code, evt)
177+
178+
Add an extension event. CODE is the numeric code, and EVT is
179+
the event class.
180+
"""
181+
182+
self.display.add_extension_event(code, evt)
183+
184+
def add_extension_error(self, code, err):
185+
"""add_extension_error(code, err)
186+
187+
Add an extension error. CODE is the numeric code, and ERR is
188+
the error class.
189+
"""
190+
191+
self.display.add_extension_error(code, err)
192+
193+
77194
###
78195
### X requests
79196
###
@@ -94,42 +211,52 @@ def get_selection_owner(self, selection):
94211
selection = selection)
95212
return r.owner
96213

97-
def send_event(self, destination, event, propagate = 0, event_mask = 0):
214+
def send_event(self, destination, event, propagate = 0, event_mask = 0,
215+
onerror = None):
216+
98217
request.SendEvent(display = self.display,
218+
onerror = onerror,
99219
propagate = propagate,
100220
destination = destination,
101221
event_mask = event_mask,
102222
event = event)
103223

104-
def ungrab_pointer(self, time):
224+
def ungrab_pointer(self, time, onerror = None):
105225
request.UngrabPointer(display = self.display,
226+
onerror = onerror,
106227
time = time)
107228

108-
def change_active_pointer_grab(self, event_mask, cursor, time):
229+
def change_active_pointer_grab(self, event_mask, cursor, time, onerror = None):
109230
request.ChangeActivePointerGrab(display = self.display,
231+
onerror = onerror,
110232
cursor = cursor,
111233
time = time,
112234
event_mask = event_mask)
113235

114-
def ungrab_keyboard(self, time):
236+
def ungrab_keyboard(self, time, onerror = None):
115237
request.UngrabKeyboard(display = self.display,
238+
onerror = onerror,
116239
time = time)
117240

118-
def allow_events(self, mode, time):
241+
def allow_events(self, mode, time, onerror = None):
119242
request.AllowEvents(display = self.display,
243+
onerror = onerror,
120244
mode = mode,
121245
time = time)
122246

123-
def grab_server(self):
247+
def grab_server(self, onerror = None):
124248
request.GrabServer(display = self.display)
249+
onerror = onerror,
125250

126-
def ungrab_server(self):
251+
def ungrab_server(self, onerror = None):
127252
request.UngrabServer(display = self.display)
253+
onerror = onerror,
128254

129255
def warp_pointer(self, x, y, src_window = 0, src_x = 0, src_y = 0,
130-
src_width = 0, src_height = 0):
256+
src_width = 0, src_height = 0, onerror = None):
131257

132258
request.WarpPointer(display = self.display,
259+
onerror = onerror,
133260
src_window = src_window,
134261
dst_window = X.NONE,
135262
src_x = src_x,
@@ -139,8 +266,9 @@ def warp_pointer(self, x, y, src_window = 0, src_x = 0, src_y = 0,
139266
dst_x = x,
140267
dst_y = y)
141268

142-
def set_input_focus(self, focus, revert_to, time):
269+
def set_input_focus(self, focus, revert_to, time, onerror = None):
143270
request.SetInputFocus(display = self.display,
271+
onerror = onerror,
144272
revert_to = revert_to,
145273
focus = focus,
146274
time = time)
@@ -154,11 +282,19 @@ def query_keymap(self):
154282

155283
def open_font(self, name):
156284
fid = self.display.allocate_resource_id()
285+
ec = error.CatchError(error.BadName)
286+
157287
request.OpenFont(display = self.display,
288+
onerror = ec,
158289
fid = fid,
159290
name = name)
291+
self.sync()
160292

161-
return fontable.Font(self.display, fid, owner = 1)
293+
if ec.get_error():
294+
self.display.free_resource_id(fid)
295+
return None
296+
else:
297+
return fontable.Font(self.display, fid, owner = 1)
162298

163299
def list_fonts(self, pattern, max_names):
164300
r = request.ListFonts(display = self.display,
@@ -171,8 +307,9 @@ def list_fonts_with_info(self, pattern, max_names):
171307
max_names = max_names,
172308
pattern = pattern)
173309

174-
def set_font_path(self, path):
310+
def set_font_path(self, path, onerror = None):
175311
request.SetFontPath(display = self.display,
312+
onerror = onerror,
176313
path = path)
177314

178315
def get_font_path(self):
@@ -191,8 +328,9 @@ def list_extensions(self):
191328
r = request.ListExtensions(display = self.display)
192329
return r.names
193330

194-
def change_keyboard_mapping(self, first_keycode, keysyms):
331+
def change_keyboard_mapping(self, first_keycode, keysyms, onerror = None):
195332
request.ChangeKeyboardMapping(display = self.display,
333+
onerror = onerror,
196334
first_keycode = first_keycode,
197335
keysyms = keysyms)
198336

@@ -202,18 +340,20 @@ def get_keyboard_mapping(self, first_keycode, count):
202340
count = count)
203341
return r.keysyms
204342

205-
def change_keyboard_control(self, **keys):
343+
def change_keyboard_control(self, onerror = None, **keys):
206344
request.ChangeKeyboardControl(display = self.display,
345+
onerror = onerror,
207346
attrs = keys)
208347

209348
def get_keyboard_control(self):
210349
return request.GetKeyboardControl(display = self.display)
211350

212-
def bell(self, percent = 0):
351+
def bell(self, percent = 0, onerror = None):
213352
request.Bell(display = self.display,
353+
onerror = onerror,
214354
percent = percent)
215355

216-
def change_pointer_control(self, accel = None, threshold = None):
356+
def change_pointer_control(self, accel = None, threshold = None, onerror = None):
217357

218358
if accel is None:
219359
do_accel = 0
@@ -229,6 +369,7 @@ def change_pointer_control(self, accel = None, threshold = None):
229369
do_threshold = 1
230370

231371
request.ChangePointerControl(display = self.display,
372+
onerror = onerror,
232373
do_accel = do_accel,
233374
do_thres = do_threshold,
234375
accel_num = accel_num,
@@ -238,8 +379,9 @@ def change_pointer_control(self, accel = None, threshold = None):
238379
def get_pointer_control(self):
239380
return request.GetPointerControl(display = self.display)
240381

241-
def set_screen_saver(self, timeout, interval, prefer_blank, allow_exposures):
382+
def set_screen_saver(self, timeout, interval, prefer_blank, allow_exposures, onerror = None):
242383
request.SetScreenSaver(display = self.display,
384+
onerror = onerror,
243385
timeout = timeout,
244386
interval = interval,
245387
prefer_blank = prefer_blank,
@@ -248,25 +390,29 @@ def set_screen_saver(self, timeout, interval, prefer_blank, allow_exposures):
248390
def get_screen_saver(self):
249391
return request.GetScreenSaver(display = self.display)
250392

251-
def change_hosts(self, mode, host_family, host):
393+
def change_hosts(self, mode, host_family, host, onerror = None):
252394
request.ChangeHosts(display = self.display,
395+
onerror = onerror,
253396
mode = mode,
254397
host_family = host_family,
255398
host = host)
256399

257400
def list_hosts(self):
258401
return request.ListHosts(display = self.display)
259402

260-
def set_access_control(self, mode):
403+
def set_access_control(self, mode, onerror = None):
261404
request.SetAccessControl(display = self.display,
405+
onerror = onerror,
262406
mode = mode)
263407

264-
def set_close_down_mode(self, mode):
408+
def set_close_down_mode(self, mode, onerror = None):
265409
request.SetCloseDownMode(display = self.display,
410+
onerror = onerror,
266411
mode = mode)
267412

268-
def force_screen_saver(self, mode):
413+
def force_screen_saver(self, mode, onerror = None):
269414
request.ForceScreenSaver(display = self.display,
415+
onerror = onerror,
270416
mode = mode)
271417

272418
def set_pointer_mapping(self, map):
@@ -287,6 +433,7 @@ def get_modifier_mapping(self):
287433
r = request.GetModifierMapping(display = self.display)
288434
return r.keycodes
289435

290-
def no_operation(self):
291-
request.NoOperation(self)
436+
def no_operation(self, onerror = None):
437+
request.NoOperation(display = self.display,
438+
onerror = onerror)
292439

0 commit comments

Comments
 (0)