1
# -*- coding: latin-1 -*-
3
# Xlib.protocol.display -- core display communication
5
# Copyright (C) 2000-2002 Peter Liljenberg <petli@ctrl-c.liu.se>
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 2 of the License, or
10
# (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, write to the Free Software
19
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
from Xlib import error
31
from Xlib.support import lock, connect
33
# Xlib.protocol modules
39
extension_major_opcodes = {}
40
error_classes = error.xerror_class.copy()
41
event_classes = event.event_class.copy()
43
def __init__(self, display = None):
44
name, host, displayno, screenno = connect.get_display(display)
46
self.display_name = name
47
self.default_screen = screenno
49
self.socket = connect.get_socket(name, host, displayno)
51
auth_name, auth_data = connect.get_auth(self.socket,
52
name, host, displayno)
54
# Internal structures for communication, grouped
55
# by their function and locks
57
# Socket error indicator, set when the socket is closed
58
# in one way or another
59
self.socket_error_lock = lock.allocate_lock()
60
self.socket_error = None
63
self.event_queue_read_lock = lock.allocate_lock()
64
self.event_queue_write_lock = lock.allocate_lock()
67
# Unsent request queue and sequence number counter
68
self.request_queue_lock = lock.allocate_lock()
69
self.request_serial = 1
70
self.request_queue = []
72
# Send-and-recieve loop, see function send_and_recive
73
# for a detailed explanation
74
self.send_recv_lock = lock.allocate_lock()
78
self.event_waiting = 0
79
self.event_wait_lock = lock.allocate_lock()
80
self.request_waiting = 0
81
self.request_wait_lock = lock.allocate_lock()
83
# Data used by the send-and-recieve loop
84
self.sent_requests = []
85
self.request_length = 0
88
self.data_sent_bytes = 0
90
# Resource ID structures
91
self.resource_id_lock = lock.allocate_lock()
92
self.resource_ids = {}
93
self.last_resource_id = 0
95
# Use an default error handler, one which just prints the error
96
self.error_handler = None
99
# Right, now we're all set up for the connection setup
100
# request with the server.
102
# Figure out which endianess the hardware uses
103
self.big_endian = struct.unpack('BB', struct.pack('H', 0x0100))[0]
110
# Send connection setup
111
r = ConnectionSetupRequest(self,
115
auth_prot_name = auth_name,
116
auth_prot_data = auth_data)
118
# Did connection fail?
120
raise error.DisplayConnectionError(self.display_name, r.reason)
122
# Set up remaining info
124
self.default_screen = min(self.default_screen, len(self.info.roots) - 1)
131
def get_display_name(self):
132
return self.display_name
134
def get_default_screen(self):
135
return self.default_screen
138
self.check_for_error()
139
return self.socket.fileno()
141
def next_event(self):
142
self.check_for_error()
144
# Main lock, so that only one thread at a time performs the
145
# event waiting code. This at least guarantees that the first
146
# thread calling next_event() will get the next event, although
147
# no order is guaranteed among other threads calling next_event()
148
# while the first is blocking.
150
self.event_queue_read_lock.acquire()
152
# Lock event queue, so we can check if it is empty
153
self.event_queue_write_lock.acquire()
155
# We have too loop until we get an event, as
156
# we might be woken up when there is no event.
158
while not self.event_queue:
160
# Lock send_recv so no send_and_recieve
161
# can start or stop while we're checking
162
# whether there are one active.
163
self.send_recv_lock.acquire()
165
# Release event queue to allow an send_and_recv to
167
self.event_queue_write_lock.release()
169
# Call send_and_recv, which will return when
170
# something has occured
171
self.send_and_recv(event = 1)
173
# Before looping around, lock the event queue against
175
self.event_queue_write_lock.acquire()
177
# Whiew, we have an event! Remove it from
178
# the event queue and relaese its write lock.
180
event = self.event_queue[0]
181
del self.event_queue[0]
182
self.event_queue_write_lock.release()
184
# Finally, allow any other threads which have called next_event()
185
# while we were waiting to proceed.
187
self.event_queue_read_lock.release()
189
# And return the event!
192
def pending_events(self):
193
self.check_for_error()
195
# Make a send_and_recv pass, receiving any events
196
self.send_recv_lock.acquire()
197
self.send_and_recv(recv = 1)
199
# Lock the queue, get the event count, and unlock again.
200
self.event_queue_write_lock.acquire()
201
count = len(self.event_queue)
202
self.event_queue_write_lock.release()
207
self.check_for_error()
208
self.send_recv_lock.acquire()
209
self.send_and_recv(flush = 1)
213
self.close_internal('client')
215
def set_error_handler(self, handler):
216
self.error_handler = handler
219
def allocate_resource_id(self):
220
"""id = d.allocate_resource_id()
222
Allocate a new X resource id number ID.
224
Raises ResourceIDError if there are no free resource ids.
227
self.resource_id_lock.acquire()
229
i = self.last_resource_id
230
while self.resource_ids.has_key(i):
232
if i > self.info.resource_id_mask:
234
if i == self.last_resource_id:
235
raise error.ResourceIDError('out of resource ids')
237
self.resource_ids[i] = None
238
self.last_resource_id = i
239
return self.info.resource_id_base | i
241
self.resource_id_lock.release()
243
def free_resource_id(self, rid):
244
"""d.free_resource_id(rid)
246
Free resource id RID. Attempts to free a resource id which
247
isn't allocated by us are ignored.
250
self.resource_id_lock.acquire()
252
i = rid & self.info.resource_id_mask
254
# Attempting to free a resource id outside our range
255
if rid - i != self.info.resource_id_base:
259
del self.resource_ids[i]
263
self.resource_id_lock.release()
267
def get_resource_class(self, class_name, default = None):
268
"""class = d.get_resource_class(class_name, default = None)
270
Return the class to be used for X resource objects of type
271
CLASS_NAME, or DEFAULT if no such class is set.
274
return self.resource_classes.get(class_name, default)
276
def set_extension_major(self, extname, major):
277
self.extension_major_opcodes[extname] = major
279
def get_extension_major(self, extname):
280
return self.extension_major_opcodes[extname]
282
def add_extension_event(self, code, evt):
283
self.event_classes[code] = evt
285
def add_extension_error(self, code, err):
286
self.error_classes[code] = err
293
def check_for_error(self):
294
self.socket_error_lock.acquire()
295
err = self.socket_error
296
self.socket_error_lock.release()
301
def send_request(self, request, wait_for_response):
302
if self.socket_error:
303
raise self.socket_error
305
self.request_queue_lock.acquire()
307
request._serial = self.request_serial
308
self.request_serial = (self.request_serial + 1) % 65536
310
self.request_queue.append((request, wait_for_response))
311
qlen = len(self.request_queue)
313
self.request_queue_lock.release()
318
def close_internal(self, whom):
319
# Clear out data structures
320
self.request_queue = None
321
self.sent_requests = None
322
self.event_queue = None
323
self.data_send = None
324
self.data_recv = None
326
# Close the connection
329
# Set a connection closed indicator
330
self.socket_error_lock.acquire()
331
self.socket_error = error.ConnectionClosedError(whom)
332
self.socket_error_lock.release()
335
def send_and_recv(self, flush = None, event = None, request = None, recv = None):
336
"""send_and_recv(flush = None, event = None, request = None, recv = None)
338
Perform I/O, or wait for some other thread to do it for us.
340
send_recv_lock MUST be LOCKED when send_and_recv is called.
341
It will be UNLOCKED at return.
343
Exactly or one of the parameters flush, event, request and recv must
344
be set to control the return condition.
346
To attempt to send all requests in the queue, flush should
347
be true. Will return immediately if another thread is
348
already doing send_and_recv.
350
To wait for an event to be recieved, event should be true.
352
To wait for a response to a certain request (either an error
353
or a response), request should be set the that request's
356
To just read any pending data from the server, recv should be true.
358
It is not guaranteed that the return condition has been
359
fulfilled when the function returns, so the caller has to loop
360
until it is finished.
363
# We go to sleep if there is already a thread doing what we
366
# If flushing, we want to send
367
# If waiting for a response to a request, we want to send
368
# (to ensure that the request was sent - we alway recv
369
# when we get to the main loop, but sending is the important
371
# If waiting for an event, we want to recv
372
# If just trying to receive anything we can, we want to recv
374
if (((flush or request is not None) and self.send_active)
375
or ((event or recv) and self.recv_active)):
377
# Signal that we are waiting for something. These locks
378
# together with the *_waiting variables are used as
379
# semaphores. When an event or a request response arrives,
380
# it will zero the *_waiting and unlock the lock. The
381
# locks will also be unlocked when an active send_and_recv
382
# finishes to signal the other waiting threads that one of
383
# them has to take over the send_and_recv function.
385
# All this makes these locks and variables a part of the
386
# send_and_recv control logic, and hence must be modified
387
# only when we have the send_recv_lock locked.
389
wait_lock = self.event_wait_lock
390
if not self.event_waiting:
391
self.event_waiting = 1
394
elif request is not None:
395
wait_lock = self.request_wait_lock
396
if not self.request_waiting:
397
self.request_waiting = 1
400
# Release send_recv, allowing a send_and_recive
401
# to terminate or other threads to queue up
402
self.send_recv_lock.release()
404
# Return immediately if flushing, even if that
405
# might mean that not necessarily all requests
410
# Wait for something to happen, as the wait locks are
411
# unlocked either when what we wait for has arrived (not
412
# necessarily the exact object we're waiting for, though),
413
# or when an active send_and_recv exits.
415
# Release it immediately afterwards as we're only using
416
# the lock for synchonization. Since we're not modifying
417
# event_waiting or request_waiting here we don't have
418
# to lock send_and_recv_lock. In fact, we can't do that
419
# or we trigger a dead-lock.
424
# Return to caller to let it check whether it has
425
# got the data it was waiting for
429
# There's no thread doing what we need to do. Find out exactly
432
# There must always be some thread recieving data, but it must not
435
if not self.recv_active:
444
# Loop, recieving and sending data.
447
# We might want to start sending data
448
if sending or not self.send_active:
450
# Turn all requests on request queue into binary form
451
# and append them to self.data_send
453
self.request_queue_lock.acquire()
454
for req, wait in self.request_queue:
455
self.data_send = self.data_send + req._binary
457
self.sent_requests.append(req)
459
del self.request_queue[:]
460
self.request_queue_lock.release()
462
# If there now is data to send, mark us as senders
471
# We've done all setup, so release the lock and start waiting
472
# for the network to fire up
473
self.send_recv_lock.release()
475
# If we're flushing, figure out how many bytes we
476
# have to send so that we're not caught in an interminable
477
# loop if other threads continuously append requests.
478
if flush and flush_bytes is None:
479
flush_bytes = self.data_sent_bytes + len(self.data_send)
483
# We're only checking for the socket to be writable
484
# if we're the sending thread. We always check for it
485
# to become readable: either we are the recieving thread
486
# and should take care of the data, or the recieving thread
487
# might finish recieving after having read the data
490
writeset = [self.socket]
494
# Timeout immediately if we're only checking for
495
# something to read or if we're flushing, otherwise block
502
rs, ws, es = select.select([self.socket], writeset, [], timeout)
504
# Ignore errors caused by a signal recieved while blocking.
505
# All other errors are re-raised.
506
except select.error, err:
507
if err[0] != errno.EINTR:
510
# We must lock send_and_recv before we can loop to
511
# the start of the loop
513
self.send_recv_lock.acquire()
517
# Socket is ready for sending data, send as much as possible.
520
i = self.socket.send(self.data_send)
521
except socket.error, err:
522
self.close_internal('server: %s' % err[1])
523
raise self.socket_error
525
self.data_send = self.data_send[i:]
526
self.data_sent_bytes = self.data_sent_bytes + i
529
# There is data to read
533
# We're the recieving thread, parse the data
536
bytes_recv = self.socket.recv(2048)
537
except socket.error, err:
538
self.close_internal('server: %s' % err[1])
539
raise self.socket_error
542
# Clear up, set a connection closed indicator and raise it
543
self.close_internal('server')
544
raise self.socket_error
546
self.data_recv = self.data_recv + bytes_recv
547
gotreq = self.parse_response(request)
549
# Otherwise return, allowing the calling thread to figure
550
# out if it has got the data it needs
552
# We must be a sending thread if we're here, so reset
554
self.send_recv_lock.acquire()
556
self.send_recv_lock.release()
558
# And return to the caller
562
# There are three different end of send-recv-loop conditions.
563
# However, we don't leave the loop immediately, instead we
564
# try to send and recieve any data that might be left. We
565
# do this by giving a timeout of 0 to select to poll
568
# When flushing: all requests have been sent
569
if flush and flush_bytes >= self.data_sent_bytes:
572
# When waiting for an event: an event has been read
573
if event and self.event_queue:
576
# When processing a certain request: got its reply
577
if request is not None and gotreq:
580
# Always break if we just want to recieve as much as possible
584
# Else there's may still data which must be sent, or
585
# we haven't got the data we waited for. Lock and loop
587
self.send_recv_lock.acquire()
590
# We have accomplished the callers request.
591
# Record that there are now no active send_and_recv,
592
# and wake up all waiting thread
594
self.send_recv_lock.acquire()
601
if self.event_waiting:
602
self.event_waiting = 0
603
self.event_wait_lock.release()
605
if self.request_waiting:
606
self.request_waiting = 0
607
self.request_wait_lock.release()
609
self.send_recv_lock.release()
612
def parse_response(self, request):
615
Parse data recieved from server. If REQUEST is not None
616
true is returned if the request with that serial number
617
was recieved, otherwise false is returned.
619
If REQUEST is -1, we're parsing the server connection setup
624
return self.parse_connection_setup()
626
# Parse ordinary server response
629
# Are we're waiting for additional data for a request response?
630
if self.request_length:
631
if len(self.data_recv) < self.request_length:
634
gotreq = self.parse_request_response(request) or gotreq
637
# Every response is at least 32 bytes long, so don't bother
638
# until we have recieved that much
639
if len(self.data_recv) < 32:
642
# Check the first byte to find out what kind of response it is
643
rtype = ord(self.data_recv[0])
647
gotreq = self.parse_error_response(request) or gotreq
651
# Set reply length, and loop around to see if
652
# we have got the full response
653
rlen = int(struct.unpack('=L', self.data_recv[4:8])[0])
654
self.request_length = 32 + rlen * 4
656
# Else event response
658
self.parse_event_response(rtype)
661
def parse_error_response(self, request):
662
# Code is second byte
663
code = ord(self.data_recv[1])
666
estruct = self.error_classes.get(code, error.XError)
668
e = estruct(self, self.data_recv[:32])
669
self.data_recv = buffer(self.data_recv, 32)
671
# print 'recv Error:', e
673
req = self.get_waiting_request(e.sequence_number)
675
# Error for a request whose response we are waiting for,
676
# or which have an error handler. However, if the error
677
# handler indicates that it hasn't taken care of the
678
# error, pass it on to the default error handler
680
if req and req._set_error(e):
682
# If this was a ReplyRequest, unlock any threads waiting
683
# for a request to finish
685
if isinstance(req, rq.ReplyRequest):
686
self.send_recv_lock.acquire()
688
if self.request_waiting:
689
self.request_waiting = 0
690
self.request_wait_lock.release()
692
self.send_recv_lock.release()
694
return request == e.sequence_number
696
# Else call the error handler
698
if self.error_handler:
699
rq.call_error_handler(self.error_handler, e, None)
701
self.default_error_handler(e)
706
def default_error_handler(self, err):
707
sys.stderr.write('X protocol error:\n%s\n' % err)
710
def parse_request_response(self, request):
711
req = self.get_waiting_replyrequest()
713
# Sequence number is always data[2:4]
714
# Do sanity check before trying to parse the data
715
sno = struct.unpack('=H', self.data_recv[2:4])[0]
716
if sno != req._serial:
717
raise RuntimeError("Expected reply for request %s, but got %s. Can't happen!"
718
% (req._serial, sno))
720
req._parse_response(self.data_recv[:self.request_length])
721
# print 'recv Request:', req
723
self.data_recv = buffer(self.data_recv, self.request_length)
724
self.request_length = 0
727
# Unlock any response waiting threads
729
self.send_recv_lock.acquire()
731
if self.request_waiting:
732
self.request_waiting = 0
733
self.request_wait_lock.release()
735
self.send_recv_lock.release()
738
return req.sequence_number == request
741
def parse_event_response(self, etype):
742
# Skip bit 8 at lookup, that is set if this event came from an
744
estruct = self.event_classes.get(etype & 0x7f, event.AnyEvent)
746
e = estruct(display = self, binarydata = self.data_recv[:32])
748
self.data_recv = buffer(self.data_recv, 32)
750
# Drop all requests having an error handler,
751
# but which obviously succeded.
753
# Decrement it by one, so that we don't remove the request
754
# that generated these events, if there is such a one.
755
# Bug reported by Ilpo Nyyss�nen
756
self.get_waiting_request((e.sequence_number - 1) % 65536)
758
# print 'recv Event:', e
760
# Insert the event into the queue
761
self.event_queue_write_lock.acquire()
762
self.event_queue.append(e)
763
self.event_queue_write_lock.release()
765
# Unlock any event waiting threads
766
self.send_recv_lock.acquire()
768
if self.event_waiting:
769
self.event_waiting = 0
770
self.event_wait_lock.release()
772
self.send_recv_lock.release()
775
def get_waiting_request(self, sno):
776
if not self.sent_requests:
779
# Normalize sequence numbers, even if they have wrapped.
783
# self.sent_requests[0]._serial <= last_serial
785
if self.sent_requests[0]._serial > self.request_serial:
786
last_serial = self.request_serial + 65536
787
if sno < self.request_serial:
791
last_serial = self.request_serial
792
if sno > self.request_serial:
795
# No matching events at all
796
if sno < self.sent_requests[0]._serial:
799
# Find last req <= sno
801
reqpos = len(self.sent_requests)
805
for i in range(0, len(self.sent_requests)):
806
rno = self.sent_requests[i]._serial + adj
808
# Did serial numbers just wrap around?
816
req = self.sent_requests[i]
824
# Delete all request such as req <= sno
825
del self.sent_requests[:reqpos]
829
def get_waiting_replyrequest(self):
830
for i in range(0, len(self.sent_requests)):
831
if hasattr(self.sent_requests[i], '_reply'):
832
req = self.sent_requests[i]
833
del self.sent_requests[:i + 1]
836
# Reply for an unknown request? No, that can't happen.
838
raise RuntimeError("Request reply to unknown request. Can't happen!")
840
def parse_connection_setup(self):
841
"""Internal function used to parse connection setup response.
844
# Only the ConnectionSetupRequest has been sent so far
845
r = self.sent_requests[0]
848
# print 'data_send:', repr(self.data_send)
849
# print 'data_recv:', repr(self.data_recv)
852
alen = r._data['additional_length'] * 4
854
# The full response haven't arrived yet
855
if len(self.data_recv) < alen:
858
# Connection failed or further authentication is needed.
859
# Set reason to the reason string
860
if r._data['status'] != 1:
861
r._data['reason'] = self.data_recv[:r._data['reason_length']]
863
# Else connection succeeded, parse the reply
865
x, d = r._success_reply.parse_binary(self.data_recv[:alen],
869
del self.sent_requests[0]
871
self.data_recv = self.data_recv[alen:]
876
# The base reply is 8 bytes long
877
if len(self.data_recv) < 8:
880
r._data, d = r._reply.parse_binary(self.data_recv[:8],
882
self.data_recv = self.data_recv[8:]
884
# Loop around to see if we have got the additional data
888
PixmapFormat = rq.Struct( rq.Card8('depth'),
889
rq.Card8('bits_per_pixel'),
890
rq.Card8('scanline_pad'),
894
VisualType = rq.Struct ( rq.Card32('visual_id'),
895
rq.Card8('visual_class'),
896
rq.Card8('bits_per_rgb_value'),
897
rq.Card16('colormap_entries'),
898
rq.Card32('red_mask'),
899
rq.Card32('green_mask'),
900
rq.Card32('blue_mask'),
904
Depth = rq.Struct( rq.Card8('depth'),
906
rq.LengthOf('visuals', 2),
908
rq.List('visuals', VisualType)
911
Screen = rq.Struct( rq.Window('root'),
912
rq.Colormap('default_colormap'),
913
rq.Card32('white_pixel'),
914
rq.Card32('black_pixel'),
915
rq.Card32('current_input_mask'),
916
rq.Card16('width_in_pixels'),
917
rq.Card16('height_in_pixels'),
918
rq.Card16('width_in_mms'),
919
rq.Card16('height_in_mms'),
920
rq.Card16('min_installed_maps'),
921
rq.Card16('max_installed_maps'),
922
rq.Card32('root_visual'),
923
rq.Card8('backing_store'),
924
rq.Card8('save_unders'),
925
rq.Card8('root_depth'),
926
rq.LengthOf('allowed_depths', 1),
927
rq.List('allowed_depths', Depth)
931
class ConnectionSetupRequest(rq.GetAttrData):
932
_request = rq.Struct( rq.Set('byte_order', 1, (0x42, 0x6c)),
934
rq.Card16('protocol_major'),
935
rq.Card16('protocol_minor'),
936
rq.LengthOf('auth_prot_name', 2),
937
rq.LengthOf('auth_prot_data', 2),
939
rq.String8('auth_prot_name'),
940
rq.String8('auth_prot_data') )
942
_reply = rq.Struct ( rq.Card8('status'),
943
rq.Card8('reason_length'),
944
rq.Card16('protocol_major'),
945
rq.Card16('protocol_minor'),
946
rq.Card16('additional_length') )
948
_success_reply = rq.Struct( rq.Card32('release_number'),
949
rq.Card32('resource_id_base'),
950
rq.Card32('resource_id_mask'),
951
rq.Card32('motion_buffer_size'),
952
rq.LengthOf('vendor', 2),
953
rq.Card16('max_request_length'),
954
rq.LengthOf('roots', 1),
955
rq.LengthOf('pixmap_formats', 1),
956
rq.Card8('image_byte_order'),
957
rq.Card8('bitmap_format_bit_order'),
958
rq.Card8('bitmap_format_scanline_unit'),
959
rq.Card8('bitmap_format_scanline_pad'),
960
rq.Card8('min_keycode'),
961
rq.Card8('max_keycode'),
963
rq.String8('vendor'),
964
rq.List('pixmap_formats', PixmapFormat),
965
rq.List('roots', Screen),
969
def __init__(self, display, *args, **keys):
970
self._binary = apply(self._request.to_binary, args, keys)
973
# Don't bother about locking, since no other threads have
974
# access to the display yet
976
display.request_queue.append((self, 1))
978
# However, we must lock send_and_recv, but we don't have
981
display.send_recv_lock.acquire()
982
display.send_and_recv(request = -1)