~bennabiy/+junk/python-xlib

« back to all changes in this revision

Viewing changes to .pc/python3.patch/Xlib/protocol/display.py

  • Committer: Package Import Robot
  • Author(s): Andrew Shadura, Ramkumar Ramachandra, Andrew Shadura
  • Date: 2015-08-13 08:14:19 UTC
  • mfrom: (6.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20150813081419-hdefinnghp2iydkx
Tags: 0.14+20091101-3
[ Ramkumar Ramachandra ]
* Remove useless debugging output (Closes: #565996)

[ Andrew Shadura ]
* Switch to 3.0 (quilt) format.
* Rename patches.
* Use debhelper 9 in its short form.
* Use pybuild.
* Bump Standards-Version.
* Don't build or install PostScript documentation and info files.
* Use system-provided texi2html instead of a shipped version
  (Closes: #795057).
* Update debian/copyright (Closes: #795057).
* Don't install Makefile or texi2html with the documentation.
* Set executable bit for examples.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: latin-1 -*-
 
2
#
 
3
# Xlib.protocol.display -- core display communication
 
4
#
 
5
#    Copyright (C) 2000-2002 Peter Liljenberg <petli@ctrl-c.liu.se>
 
6
#
 
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.
 
11
#
 
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.
 
16
#
 
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
 
20
 
 
21
# Standard modules
 
22
import sys
 
23
import select
 
24
import struct
 
25
import errno
 
26
import socket
 
27
 
 
28
# Xlib modules
 
29
from Xlib import error
 
30
 
 
31
from Xlib.support import lock, connect
 
32
 
 
33
# Xlib.protocol modules
 
34
import rq
 
35
import event
 
36
 
 
37
class Display:
 
38
    resource_classes = {}
 
39
    extension_major_opcodes = {}
 
40
    error_classes = error.xerror_class.copy()
 
41
    event_classes = event.event_class.copy()
 
42
 
 
43
    def __init__(self, display = None):
 
44
        name, host, displayno, screenno = connect.get_display(display)
 
45
 
 
46
        self.display_name = name
 
47
        self.default_screen = screenno
 
48
 
 
49
        self.socket = connect.get_socket(name, host, displayno)
 
50
 
 
51
        auth_name, auth_data = connect.get_auth(self.socket,
 
52
                                                name, host, displayno)
 
53
 
 
54
        # Internal structures for communication, grouped
 
55
        # by their function and locks
 
56
 
 
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
 
61
 
 
62
        # Event queue
 
63
        self.event_queue_read_lock = lock.allocate_lock()
 
64
        self.event_queue_write_lock = lock.allocate_lock()
 
65
        self.event_queue = []
 
66
 
 
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 = []
 
71
 
 
72
        # Send-and-recieve loop, see function send_and_recive
 
73
        # for a detailed explanation
 
74
        self.send_recv_lock = lock.allocate_lock()
 
75
        self.send_active = 0
 
76
        self.recv_active = 0
 
77
 
 
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()
 
82
 
 
83
        # Data used by the send-and-recieve loop
 
84
        self.sent_requests = []
 
85
        self.request_length = 0
 
86
        self.data_send = ''
 
87
        self.data_recv = ''
 
88
        self.data_sent_bytes = 0
 
89
 
 
90
        # Resource ID structures
 
91
        self.resource_id_lock = lock.allocate_lock()
 
92
        self.resource_ids = {}
 
93
        self.last_resource_id = 0
 
94
 
 
95
        # Use an default error handler, one which just prints the error
 
96
        self.error_handler = None
 
97
 
 
98
 
 
99
        # Right, now we're all set up for the connection setup
 
100
        # request with the server.
 
101
 
 
102
        # Figure out which endianess the hardware uses
 
103
        self.big_endian = struct.unpack('BB', struct.pack('H', 0x0100))[0]
 
104
 
 
105
        if self.big_endian:
 
106
            order = 0x42
 
107
        else:
 
108
            order = 0x6c
 
109
 
 
110
        # Send connection setup
 
111
        r = ConnectionSetupRequest(self,
 
112
                                   byte_order = order,
 
113
                                   protocol_major = 11,
 
114
                                   protocol_minor = 0,
 
115
                                   auth_prot_name = auth_name,
 
116
                                   auth_prot_data = auth_data)
 
117
 
 
118
        # Did connection fail?
 
119
        if r.status != 1:
 
120
            raise error.DisplayConnectionError(self.display_name, r.reason)
 
121
 
 
122
        # Set up remaining info
 
123
        self.info = r
 
124
        self.default_screen = min(self.default_screen, len(self.info.roots) - 1)
 
125
 
 
126
 
 
127
    #
 
128
    # Public interface
 
129
    #
 
130
 
 
131
    def get_display_name(self):
 
132
        return self.display_name
 
133
 
 
134
    def get_default_screen(self):
 
135
        return self.default_screen
 
136
 
 
137
    def fileno(self):
 
138
        self.check_for_error()
 
139
        return self.socket.fileno()
 
140
 
 
141
    def next_event(self):
 
142
        self.check_for_error()
 
143
 
 
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.
 
149
 
 
150
        self.event_queue_read_lock.acquire()
 
151
 
 
152
        # Lock event queue, so we can check if it is empty
 
153
        self.event_queue_write_lock.acquire()
 
154
 
 
155
        # We have too loop until we get an event, as
 
156
        # we might be woken up when there is no event.
 
157
 
 
158
        while not self.event_queue:
 
159
 
 
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()
 
164
 
 
165
            # Release event queue to allow an send_and_recv to
 
166
            # insert any now.
 
167
            self.event_queue_write_lock.release()
 
168
 
 
169
            # Call send_and_recv, which will return when
 
170
            # something has occured
 
171
            self.send_and_recv(event = 1)
 
172
 
 
173
            # Before looping around, lock the event queue against
 
174
            # modifications.
 
175
            self.event_queue_write_lock.acquire()
 
176
 
 
177
        # Whiew, we have an event!  Remove it from
 
178
        # the event queue and relaese its write lock.
 
179
 
 
180
        event = self.event_queue[0]
 
181
        del self.event_queue[0]
 
182
        self.event_queue_write_lock.release()
 
183
 
 
184
        # Finally, allow any other threads which have called next_event()
 
185
        # while we were waiting to proceed.
 
186
 
 
187
        self.event_queue_read_lock.release()
 
188
 
 
189
        # And return the event!
 
190
        return event
 
191
 
 
192
    def pending_events(self):
 
193
        self.check_for_error()
 
194
 
 
195
        # Make a send_and_recv pass, receiving any events
 
196
        self.send_recv_lock.acquire()
 
197
        self.send_and_recv(recv = 1)
 
198
 
 
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()
 
203
 
 
204
        return count
 
205
 
 
206
    def flush(self):
 
207
        self.check_for_error()
 
208
        self.send_recv_lock.acquire()
 
209
        self.send_and_recv(flush = 1)
 
210
 
 
211
    def close(self):
 
212
        self.flush()
 
213
        self.close_internal('client')
 
214
 
 
215
    def set_error_handler(self, handler):
 
216
        self.error_handler = handler
 
217
 
 
218
 
 
219
    def allocate_resource_id(self):
 
220
        """id = d.allocate_resource_id()
 
221
 
 
222
        Allocate a new X resource id number ID.
 
223
 
 
224
        Raises ResourceIDError if there are no free resource ids.
 
225
        """
 
226
 
 
227
        self.resource_id_lock.acquire()
 
228
        try:
 
229
            i = self.last_resource_id
 
230
            while self.resource_ids.has_key(i):
 
231
                i = i + 1
 
232
                if i > self.info.resource_id_mask:
 
233
                    i = 0
 
234
                if i == self.last_resource_id:
 
235
                    raise error.ResourceIDError('out of resource ids')
 
236
 
 
237
            self.resource_ids[i] = None
 
238
            self.last_resource_id = i
 
239
            return self.info.resource_id_base | i
 
240
        finally:
 
241
            self.resource_id_lock.release()
 
242
 
 
243
    def free_resource_id(self, rid):
 
244
        """d.free_resource_id(rid)
 
245
 
 
246
        Free resource id RID.  Attempts to free a resource id which
 
247
        isn't allocated by us are ignored.
 
248
        """
 
249
 
 
250
        self.resource_id_lock.acquire()
 
251
        try:
 
252
            i = rid & self.info.resource_id_mask
 
253
 
 
254
            # Attempting to free a resource id outside our range
 
255
            if rid - i != self.info.resource_id_base:
 
256
                return None
 
257
 
 
258
            try:
 
259
                del self.resource_ids[i]
 
260
            except KeyError:
 
261
                pass
 
262
        finally:
 
263
            self.resource_id_lock.release()
 
264
 
 
265
 
 
266
 
 
267
    def get_resource_class(self, class_name, default = None):
 
268
        """class = d.get_resource_class(class_name, default = None)
 
269
 
 
270
        Return the class to be used for X resource objects of type
 
271
        CLASS_NAME, or DEFAULT if no such class is set.
 
272
        """
 
273
 
 
274
        return self.resource_classes.get(class_name, default)
 
275
 
 
276
    def set_extension_major(self, extname, major):
 
277
        self.extension_major_opcodes[extname] = major
 
278
 
 
279
    def get_extension_major(self, extname):
 
280
        return self.extension_major_opcodes[extname]
 
281
 
 
282
    def add_extension_event(self, code, evt):
 
283
        self.event_classes[code] = evt
 
284
 
 
285
    def add_extension_error(self, code, err):
 
286
        self.error_classes[code] = err
 
287
 
 
288
 
 
289
    #
 
290
    # Private functions
 
291
    #
 
292
 
 
293
    def check_for_error(self):
 
294
        self.socket_error_lock.acquire()
 
295
        err = self.socket_error
 
296
        self.socket_error_lock.release()
 
297
 
 
298
        if err:
 
299
            raise err
 
300
 
 
301
    def send_request(self, request, wait_for_response):
 
302
        if self.socket_error:
 
303
            raise self.socket_error
 
304
 
 
305
        self.request_queue_lock.acquire()
 
306
 
 
307
        request._serial = self.request_serial
 
308
        self.request_serial = (self.request_serial + 1) % 65536
 
309
 
 
310
        self.request_queue.append((request, wait_for_response))
 
311
        qlen = len(self.request_queue)
 
312
 
 
313
        self.request_queue_lock.release()
 
314
 
 
315
#       if qlen > 10:
 
316
#           self.flush()
 
317
 
 
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
 
325
 
 
326
        # Close the connection
 
327
        self.socket.close()
 
328
 
 
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()
 
333
 
 
334
 
 
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)
 
337
 
 
338
        Perform I/O, or wait for some other thread to do it for us.
 
339
 
 
340
        send_recv_lock MUST be LOCKED when send_and_recv is called.
 
341
        It will be UNLOCKED at return.
 
342
 
 
343
        Exactly or one of the parameters flush, event, request and recv must
 
344
        be set to control the return condition.
 
345
 
 
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.
 
349
 
 
350
        To wait for an event to be recieved, event should be true.
 
351
 
 
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
 
354
        serial number.
 
355
 
 
356
        To just read any pending data from the server, recv should be true.
 
357
 
 
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.
 
361
        """
 
362
 
 
363
        # We go to sleep if there is already a thread doing what we
 
364
        # want to do:
 
365
 
 
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
 
370
        #     thing here)
 
371
        #  If waiting for an event, we want to recv
 
372
        #  If just trying to receive anything we can, we want to recv
 
373
 
 
374
        if (((flush or request is not None) and self.send_active)
 
375
            or ((event or recv) and self.recv_active)):
 
376
 
 
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.
 
384
 
 
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.
 
388
            if event:
 
389
                wait_lock = self.event_wait_lock
 
390
                if not self.event_waiting:
 
391
                    self.event_waiting = 1
 
392
                    wait_lock.acquire()
 
393
 
 
394
            elif request is not None:
 
395
                wait_lock = self.request_wait_lock
 
396
                if not self.request_waiting:
 
397
                    self.request_waiting = 1
 
398
                    wait_lock.acquire()
 
399
 
 
400
            # Release send_recv, allowing a send_and_recive
 
401
            # to terminate or other threads to queue up
 
402
            self.send_recv_lock.release()
 
403
 
 
404
            # Return immediately if flushing, even if that
 
405
            # might mean that not necessarily all requests
 
406
            # have been sent.
 
407
            if flush or recv:
 
408
                return
 
409
 
 
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.
 
414
 
 
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.
 
420
 
 
421
            wait_lock.acquire()
 
422
            wait_lock.release()
 
423
 
 
424
            # Return to caller to let it check whether it has
 
425
            # got the data it was waiting for
 
426
            return
 
427
 
 
428
 
 
429
        # There's no thread doing what we need to do.  Find out exactly
 
430
        # what to do
 
431
 
 
432
        # There must always be some thread recieving data, but it must not
 
433
        # necessarily be us
 
434
 
 
435
        if not self.recv_active:
 
436
            recieving = 1
 
437
            self.recv_active = 1
 
438
        else:
 
439
            recieving = 0
 
440
 
 
441
        flush_bytes = None
 
442
        sending = 0
 
443
 
 
444
        # Loop, recieving and sending data.
 
445
        while 1:
 
446
 
 
447
            # We might want to start sending data
 
448
            if sending or not self.send_active:
 
449
 
 
450
                # Turn all requests on request queue into binary form
 
451
                # and append them to self.data_send
 
452
 
 
453
                self.request_queue_lock.acquire()
 
454
                for req, wait in self.request_queue:
 
455
                    self.data_send = self.data_send + req._binary
 
456
                    if wait:
 
457
                        self.sent_requests.append(req)
 
458
 
 
459
                del self.request_queue[:]
 
460
                self.request_queue_lock.release()
 
461
 
 
462
                # If there now is data to send, mark us as senders
 
463
 
 
464
                if self.data_send:
 
465
                    self.send_active = 1
 
466
                    sending = 1
 
467
                else:
 
468
                    self.send_active = 0
 
469
                    sending = 0
 
470
 
 
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()
 
474
 
 
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)
 
480
 
 
481
 
 
482
            try:
 
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
 
488
 
 
489
                if sending:
 
490
                    writeset = [self.socket]
 
491
                else:
 
492
                    writeset = []
 
493
 
 
494
                # Timeout immediately if we're only checking for
 
495
                # something to read or if we're flushing, otherwise block
 
496
 
 
497
                if recv or flush:
 
498
                    timeout = 0
 
499
                else:
 
500
                    timeout = None
 
501
 
 
502
                rs, ws, es = select.select([self.socket], writeset, [], timeout)
 
503
 
 
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:
 
508
                    raise err
 
509
 
 
510
                # We must lock send_and_recv before we can loop to
 
511
                # the start of the loop
 
512
 
 
513
                self.send_recv_lock.acquire()
 
514
                continue
 
515
 
 
516
 
 
517
            # Socket is ready for sending data, send as much as possible.
 
518
            if ws:
 
519
                try:
 
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
 
524
 
 
525
                self.data_send = self.data_send[i:]
 
526
                self.data_sent_bytes = self.data_sent_bytes + i
 
527
 
 
528
 
 
529
            # There is data to read
 
530
            gotreq = 0
 
531
            if rs:
 
532
 
 
533
                # We're the recieving thread, parse the data
 
534
                if recieving:
 
535
                    try:
 
536
                        bytes_recv = self.socket.recv(4096)
 
537
                    except socket.error, err:
 
538
                        self.close_internal('server: %s' % err[1])
 
539
                        raise self.socket_error
 
540
 
 
541
                    if not bytes_recv:
 
542
                        # Clear up, set a connection closed indicator and raise it
 
543
                        self.close_internal('server')
 
544
                        raise self.socket_error
 
545
 
 
546
                    self.data_recv = self.data_recv + bytes_recv
 
547
                    gotreq = self.parse_response(request)
 
548
 
 
549
                # Otherwise return, allowing the calling thread to figure
 
550
                # out if it has got the data it needs
 
551
                else:
 
552
                    # We must be a sending thread if we're here, so reset
 
553
                    # that indicator.
 
554
                    self.send_recv_lock.acquire()
 
555
                    self.send_active = 0
 
556
                    self.send_recv_lock.release()
 
557
 
 
558
                    # And return to the caller
 
559
                    return
 
560
 
 
561
 
 
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
 
566
            # the socket.
 
567
 
 
568
            # When flushing: all requests have been sent
 
569
            if flush and flush_bytes >= self.data_sent_bytes:
 
570
                break
 
571
 
 
572
            # When waiting for an event: an event has been read
 
573
            if event and self.event_queue:
 
574
                break
 
575
 
 
576
            # When processing a certain request: got its reply
 
577
            if request is not None and gotreq:
 
578
                break
 
579
 
 
580
            # Always break if we just want to recieve as much as possible
 
581
            if recv:
 
582
                break
 
583
 
 
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
 
586
 
 
587
            self.send_recv_lock.acquire()
 
588
 
 
589
 
 
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
 
593
 
 
594
        self.send_recv_lock.acquire()
 
595
 
 
596
        if sending:
 
597
            self.send_active = 0
 
598
        if recieving:
 
599
            self.recv_active = 0
 
600
 
 
601
        if self.event_waiting:
 
602
            self.event_waiting = 0
 
603
            self.event_wait_lock.release()
 
604
 
 
605
        if self.request_waiting:
 
606
            self.request_waiting = 0
 
607
            self.request_wait_lock.release()
 
608
 
 
609
        self.send_recv_lock.release()
 
610
 
 
611
 
 
612
    def parse_response(self, request):
 
613
        """Internal method.
 
614
 
 
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.
 
618
 
 
619
        If REQUEST is -1, we're parsing the server connection setup
 
620
        response.
 
621
        """
 
622
 
 
623
        if request == -1:
 
624
            return self.parse_connection_setup()
 
625
 
 
626
        # Parse ordinary server response
 
627
        gotreq = 0
 
628
        while 1:
 
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:
 
632
                    return gotreq
 
633
                else:
 
634
                    gotreq = self.parse_request_response(request) or gotreq
 
635
 
 
636
 
 
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:
 
640
                return gotreq
 
641
 
 
642
            # Check the first byte to find out what kind of response it is
 
643
            rtype = ord(self.data_recv[0])
 
644
 
 
645
            # Error resposne
 
646
            if rtype == 0:
 
647
                gotreq = self.parse_error_response(request) or gotreq
 
648
 
 
649
            # Request response
 
650
            elif rtype == 1:
 
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
 
655
 
 
656
            # Else event response
 
657
            else:
 
658
                self.parse_event_response(rtype)
 
659
 
 
660
 
 
661
    def parse_error_response(self, request):
 
662
        # Code is second byte
 
663
        code = ord(self.data_recv[1])
 
664
 
 
665
        # Fetch error class
 
666
        estruct = self.error_classes.get(code, error.XError)
 
667
 
 
668
        e = estruct(self, self.data_recv[:32])
 
669
        self.data_recv = buffer(self.data_recv, 32)
 
670
 
 
671
        # print 'recv Error:', e
 
672
 
 
673
        req = self.get_waiting_request(e.sequence_number)
 
674
 
 
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
 
679
 
 
680
        if req and req._set_error(e):
 
681
 
 
682
            # If this was a ReplyRequest, unlock any threads waiting
 
683
            # for a request to finish
 
684
 
 
685
            if isinstance(req, rq.ReplyRequest):
 
686
                self.send_recv_lock.acquire()
 
687
 
 
688
                if self.request_waiting:
 
689
                    self.request_waiting = 0
 
690
                    self.request_wait_lock.release()
 
691
 
 
692
                self.send_recv_lock.release()
 
693
 
 
694
            return request == e.sequence_number
 
695
 
 
696
        # Else call the error handler
 
697
        else:
 
698
            if self.error_handler:
 
699
                rq.call_error_handler(self.error_handler, e, None)
 
700
            else:
 
701
                self.default_error_handler(e)
 
702
 
 
703
            return 0
 
704
 
 
705
 
 
706
    def default_error_handler(self, err):
 
707
        sys.stderr.write('X protocol error:\n%s\n' % err)
 
708
 
 
709
 
 
710
    def parse_request_response(self, request):
 
711
        req = self.get_waiting_replyrequest()
 
712
 
 
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))
 
719
 
 
720
        req._parse_response(self.data_recv[:self.request_length])
 
721
        # print 'recv Request:', req
 
722
 
 
723
        self.data_recv = buffer(self.data_recv, self.request_length)
 
724
        self.request_length = 0
 
725
 
 
726
 
 
727
        # Unlock any response waiting threads
 
728
 
 
729
        self.send_recv_lock.acquire()
 
730
 
 
731
        if self.request_waiting:
 
732
            self.request_waiting = 0
 
733
            self.request_wait_lock.release()
 
734
 
 
735
        self.send_recv_lock.release()
 
736
 
 
737
 
 
738
        return req.sequence_number == request
 
739
 
 
740
 
 
741
    def parse_event_response(self, etype):
 
742
        # Skip bit 8 at lookup, that is set if this event came from an
 
743
        # SendEvent
 
744
        estruct = self.event_classes.get(etype & 0x7f, event.AnyEvent)
 
745
 
 
746
        e = estruct(display = self, binarydata = self.data_recv[:32])
 
747
 
 
748
        self.data_recv = buffer(self.data_recv, 32)
 
749
 
 
750
        # Drop all requests having an error handler,
 
751
        # but which obviously succeded.
 
752
 
 
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)
 
757
 
 
758
        # print 'recv Event:', e
 
759
 
 
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()
 
764
 
 
765
        # Unlock any event waiting threads
 
766
        self.send_recv_lock.acquire()
 
767
 
 
768
        if self.event_waiting:
 
769
            self.event_waiting = 0
 
770
            self.event_wait_lock.release()
 
771
 
 
772
        self.send_recv_lock.release()
 
773
 
 
774
 
 
775
    def get_waiting_request(self, sno):
 
776
        if not self.sent_requests:
 
777
            return None
 
778
 
 
779
        # Normalize sequence numbers, even if they have wrapped.
 
780
        # This ensures that
 
781
        #   sno <= last_serial
 
782
        # and
 
783
        #   self.sent_requests[0]._serial <= last_serial
 
784
 
 
785
        if self.sent_requests[0]._serial > self.request_serial:
 
786
            last_serial = self.request_serial + 65536
 
787
            if sno < self.request_serial:
 
788
                sno = sno + 65536
 
789
 
 
790
        else:
 
791
            last_serial = self.request_serial
 
792
            if sno > self.request_serial:
 
793
                sno = sno - 65536
 
794
 
 
795
        # No matching events at all
 
796
        if sno < self.sent_requests[0]._serial:
 
797
            return None
 
798
 
 
799
        # Find last req <= sno
 
800
        req = None
 
801
        reqpos = len(self.sent_requests)
 
802
        adj = 0
 
803
        last = 0
 
804
 
 
805
        for i in range(0, len(self.sent_requests)):
 
806
            rno = self.sent_requests[i]._serial + adj
 
807
 
 
808
            # Did serial numbers just wrap around?
 
809
            if rno < last:
 
810
                adj = 65536
 
811
                rno = rno + adj
 
812
 
 
813
            last = rno
 
814
 
 
815
            if sno == rno:
 
816
                req = self.sent_requests[i]
 
817
                reqpos = i + 1
 
818
                break
 
819
            elif sno < rno:
 
820
                req = None
 
821
                reqpos = i
 
822
                break
 
823
 
 
824
        # Delete all request such as req <= sno
 
825
        del self.sent_requests[:reqpos]
 
826
 
 
827
        return req
 
828
 
 
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]
 
834
                return req
 
835
 
 
836
        # Reply for an unknown request?  No, that can't happen.
 
837
        else:
 
838
            raise RuntimeError("Request reply to unknown request.  Can't happen!")
 
839
 
 
840
    def parse_connection_setup(self):
 
841
        """Internal function used to parse connection setup response.
 
842
        """
 
843
 
 
844
        # Only the ConnectionSetupRequest has been sent so far
 
845
        r = self.sent_requests[0]
 
846
 
 
847
        while 1:
 
848
            # print 'data_send:', repr(self.data_send)
 
849
            # print 'data_recv:', repr(self.data_recv)
 
850
 
 
851
            if r._data:
 
852
                alen = r._data['additional_length'] * 4
 
853
 
 
854
                # The full response haven't arrived yet
 
855
                if len(self.data_recv) < alen:
 
856
                    return 0
 
857
 
 
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']]
 
862
 
 
863
                # Else connection succeeded, parse the reply
 
864
                else:
 
865
                    x, d = r._success_reply.parse_binary(self.data_recv[:alen],
 
866
                                                         self, rawdict = 1)
 
867
                    r._data.update(x)
 
868
 
 
869
                del self.sent_requests[0]
 
870
 
 
871
                self.data_recv = self.data_recv[alen:]
 
872
 
 
873
                return 1
 
874
 
 
875
            else:
 
876
                # The base reply is 8 bytes long
 
877
                if len(self.data_recv) < 8:
 
878
                    return 0
 
879
 
 
880
                r._data, d = r._reply.parse_binary(self.data_recv[:8],
 
881
                                                   self, rawdict = 1)
 
882
                self.data_recv = self.data_recv[8:]
 
883
 
 
884
                # Loop around to see if we have got the additional data
 
885
                # already
 
886
 
 
887
 
 
888
PixmapFormat = rq.Struct( rq.Card8('depth'),
 
889
                          rq.Card8('bits_per_pixel'),
 
890
                          rq.Card8('scanline_pad'),
 
891
                          rq.Pad(5)
 
892
                          )
 
893
 
 
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'),
 
901
                         rq.Pad(4)
 
902
                         )
 
903
 
 
904
Depth = rq.Struct( rq.Card8('depth'),
 
905
                   rq.Pad(1),
 
906
                   rq.LengthOf('visuals', 2),
 
907
                   rq.Pad(4),
 
908
                   rq.List('visuals', VisualType)
 
909
                   )
 
910
 
 
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)
 
928
                    )
 
929
 
 
930
 
 
931
class ConnectionSetupRequest(rq.GetAttrData):
 
932
    _request = rq.Struct( rq.Set('byte_order', 1, (0x42, 0x6c)),
 
933
                          rq.Pad(1),
 
934
                          rq.Card16('protocol_major'),
 
935
                          rq.Card16('protocol_minor'),
 
936
                          rq.LengthOf('auth_prot_name', 2),
 
937
                          rq.LengthOf('auth_prot_data', 2),
 
938
                          rq.Pad(2),
 
939
                          rq.String8('auth_prot_name'),
 
940
                          rq.String8('auth_prot_data') )
 
941
 
 
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') )
 
947
 
 
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'),
 
962
                                rq.Pad(4),
 
963
                                rq.String8('vendor'),
 
964
                                rq.List('pixmap_formats', PixmapFormat),
 
965
                                rq.List('roots', Screen),
 
966
                                )
 
967
 
 
968
 
 
969
    def __init__(self, display, *args, **keys):
 
970
        self._binary = apply(self._request.to_binary, args, keys)
 
971
        self._data = None
 
972
 
 
973
        # Don't bother about locking, since no other threads have
 
974
        # access to the display yet
 
975
 
 
976
        display.request_queue.append((self, 1))
 
977
 
 
978
        # However, we must lock send_and_recv, but we don't have
 
979
        # to loop.
 
980
 
 
981
        display.send_recv_lock.acquire()
 
982
        display.send_and_recv(request = -1)