This file is indexed.

/usr/share/pyshared/plwm/event.py is in python-plwm 2.6a+20080530-1.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
#
#    event.py -- X event handling framework
#
#    Copyright (C) 1999-2001  Peter Liljenberg <petli@ctrl-c.liu.se>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import types
import time
import select
import errno
from Xlib import X

__next_event_type = 256
def new_event_type():
    """Returns a new event type code.  The code is an integer, unique
    with respect to X event types and other event types allocated
    with new_event_type().
    """

    global __next_event_type
    t = __next_event_type
    __next_event_type = __next_event_type + 1
    return t


class TimerEvent:
    def __init__(self, event_type, after = 0, at = 0):
        self.type = event_type
        if at > 0:
            self.time = at
        else:
            self.time = time.time() + after

    def cancel(self):
        self.time = None

    def str(self):
        if self.time is None:
            return '<%s cancelled>' % self.__class__.__name__
        else:
            return '<%s at %d in %d seconds>' % (self.__class__.__name__, self.time,
                                                 time.time() - self.time)

class FileEvent:
    READ = 1
    WRITE = 2
    EXCEPTION = 4

    def __init__(self, event_type, file, mode = None):
        self.type = event_type
        self.file = file
        if mode is None:
            self.mode = 0
            if 'r' in self.file.mode:
                self.mode = self.mode | FileEvent.READ
            if 'w' in self.file.mode:
                self.mode = self.mode | FileEvent.WRITE
        else:
            self.mode = mode

        self.state = 0
        self.unhandled = 0

    def fileno(self):
        return self.file.fileno()

    def cancel(self):
        self.file = None

    def set_mode(self, newmode = None, set = 0, clear = 0):
        if newmode is not None:
            self.mode = newmode

        self.mode = (self.mode | set) & ~clear

    def str(self):
        if self.file is None:
            return '<%s cancelled>' % self.__class__.__name__
        else:
            mode = ''
            if self.mode & FileEvent.READ:
                mode = mode + 'R'
            if self.mode & FileEvent.WRITE:
                mode = mode + 'W'
            if self.mode & FileEvent.EXCEPTION:
                mode = mode + 'E'

            return '<%s for %s mode %s>' % (self.__class__.__name__, self.file, mode)

class EventFetcher:
    def __init__(self, display):
        self.display = display
        self.timers = []
        self.events = []
        self.x_events = []
        self.files = []

    def next_event(self, timeout = None):
        # If select is interrupted by a signal, we just want to
        # make everything from scratch
        while 1:
            # First return synthetic events
            if self.events:
                e = self.events[0]
                del self.events[0]

                # If e is an FileEvent, move unhandled to event state
                if isinstance(e, FileEvent):
                    e.state = e.unhandled
                    e.unhandled = 0

                return e

            # Return any read but unprocessed X events
            if self.x_events:
                xe = self.x_events[0]
                del self.x_events[0]
                return xe

            # Attempt to read any events, and if there are any return the first
            xe = self._read_x_events()
            if xe:
                return xe

            now = time.time()

            # Normalize negative timeout values
            if timeout is not None and timeout < 0:
                timeout = 0

            to = None
            # See if we have to wait for a timer
            while self.timers:
                te = self.timers[0]

                # Is this timer canceled?
                if te.time is None:
                    del self.timers[0]
                    continue

                to = te.time

                # This timer has already timed out, so return it
                if to <= now:
                    del self.timers[0]
                    return te

                # Is the general event timeout earlier than this timer?
                if timeout is not None and to > (timeout + now):
                    to = timeout + now
                    te = None

                # Break the loop, as we have found a valid timer
                break


            # Do we have a general event timeout?
            if to is None and timeout is not None:
                to = timeout + now
                te = None

            # Loop until we return an event
            while 1:
                # Wait for X data or a timeout
                read = [self.display]
                write = []
                exc = []

                # Iterate over all files, removing closed and cancelled.
                # The other are added to the corresponding lists

                i = 0
                while i < len(self.files):
                    f = self.files[i]

                    # FileEvent has been cancelled
                    if f.file is None:
                        del self.files[i]

                    # Uncancelled file event
                    else:

                        # Try to get the fileno, in an attempt to
                        # find closed but uncancelled files, so we
                        # can remove them.
                        try:
                            f.fileno()
                        except ValueError:
                            del self.files[i]

                        # Seems to be an open file, add it
                        else:

                            # Get the interested, as yet not recieved, modes
                            m = f.mode & ~f.unhandled

                            if m & FileEvent.READ:
                                read.append(f)
                            if m & FileEvent.WRITE:
                                write.append(f)
                            if m & FileEvent.EXCEPTION:
                                exc.append(f)

                            i = i + 1

                # Wrap select() in a loop, so that EINTRS are ignored
                # correctly

                while 1:
                    try:
                        if to is None:
                            readable, writable, excable = select.select(read, write, exc)
                        else:
                            wait = max(to - time.time(), 0)
                            readable, writable, excable = select.select(read, write, exc, wait)
                    except select.error, val:
                        if val[0] != errno.EINTR:
                            raise val
                    else:
                        break

                # We have timed out, return the timer event or None
                if not readable and not writable and not excable:
                    # Delete the timed out timer
                    if te is not None:
                        del self.timers[0]
                        # Don't return canceled timers
                        if te.time is not None:
                            return te

                        # break the inner while loop to find another timer
                        else:
                            break
                    else:
                        return None

                # Iterate over all ready files.  Add all ready
                # FileEvents to the synthetic event list, unless
                # they already are there, and 'or' in the mode

                xe = None

                for f in readable:

                    # By treating the display first, we ensure
                    # that X events are prioritized over file events

                    if f is self.display:
                        xe = self._read_x_events()
                    else:
                        if f.unhandled == 0:
                            self.events.append(f)
                        f.unhandled = f.unhandled | FileEvent.READ

                for f in writable:
                    if f.unhandled == 0:
                        self.events.append(f)
                    f.unhandled = f.unhandled | FileEvent.WRITE

                for f in excable:
                    if f.unhandled == 0:
                        self.events.append(f)
                    f.unhandled = f.unhandled | FileEvent.EXCEPTION

                # If there was an X event, return it immedieately
                if xe is not None:
                    return xe

                # If there was some file event, return it by breaking
                # out of the inner while-loop, so we get back to
                # the top of the function
                if self.events:
                    break

                # Something was recieved, but not an event.  Loop around
                # to select one more time

    def _read_x_events(self):
        # Read as many x events as possible, and return the first one.
        # Store the rest in x_events
        i = self.display.pending_events()
        if i > 0:
            # Store first event to be returned immediately,
            # and put remaining events on the events queue.
            xe = self.display.next_event()
            while i > 1:
                self.x_events.append(self.display.next_event())
                i = i - 1
            return xe
        else:
            return None




    def add_timer(self, timer):
        """Add a TimerEvent TIMER to the event list.
        """

        # We iterate over the entire timer list, to remove cancelled timers

        i = 0
        while i < len(self.timers):
            t = self.timers[i]

            # Remove cancelled timers
            if t.time is None:
                del self.timers[i]
            else:
                # If we haven't already inserted timer, perform checks
                if timer and timer.time < t.time:
                    self.timers.insert(i, timer)
                    i = i + 1
                    timer = None

                i = i + 1

        if timer:
            self.timers.append(timer)

    def add_file(self, file):
        """Add the FileEvent FILE to the list of files to watch.

        FILE will be sent when it is ready for reading or writing, as
        specified by its mode.

        Remove FILE from list of interesting events by calling
        FILE.cancel().
        """
        self.files.append(file)

    def put_event(self, event):
        """Add a synthesized EVENT.
        """
        self.events.append(event)


# A list of X events and their default event masks.

default_event_masks = {
    X.KeyPress: X.KeyPressMask,
    X.KeyRelease: X.KeyReleaseMask,

    X.ButtonPress: X.ButtonPressMask,
    X.ButtonRelease: X.ButtonReleaseMask,
    X.MotionNotify: [X.PointerMotionMask, X.ButtonMotionMask],

    X.EnterNotify: X.EnterWindowMask,
    X.LeaveNotify: X.LeaveWindowMask,

    X.FocusIn: X.FocusChangeMask,
    X.FocusOut: X.FocusChangeMask,

    X.KeymapNotify: X.KeymapStateMask,

    X.Expose: X.ExposureMask,
    X.GraphicsExpose: X.ExposureMask,
    X.NoExpose: X.ExposureMask,

    X.VisibilityNotify: X.VisibilityChangeMask,

    X.CreateNotify: X.SubstructureNotifyMask,

    # The following seven events can also be sent when
    # X.SubstructureNotifyMask is set, but the default
    # has to be considered to the the ordinary
    # X.StructureNotifyMask

    X.DestroyNotify: X.StructureNotifyMask,
    X.UnmapNotify: X.StructureNotifyMask,
    X.MapNotify: X.StructureNotifyMask,
    X.ReparentNotify: X.StructureNotifyMask,
    X.ConfigureNotify: X.StructureNotifyMask,
    X.GravityNotify: X.StructureNotifyMask,
    X.CirculateNotify: X.StructureNotifyMask,

    X.MapRequest: X.SubstructureRedirectMask,
    X.ConfigureRequest: X.SubstructureRedirectMask,
    X.CirculateRequest: X.SubstructureRedirectMask,
    X.ResizeRequest: X.ResizeRedirectMask,

    X.PropertyNotify: X.PropertyChangeMask,

    X.ColormapNotify: X.ColormapChangeMask,

    # The following events have no event mask:
    # X.SelectionClear
    # X.SelectionRequest
    # X.SelectionNotify
    # X.ClientMessage
    # X.MappingNotify
}


class EventHandler:
    def __init__(self, handler, masks, handlerid):
        self.handler = handler
        self.id = handlerid
        self.masks = masks

    def __cmp__(self, obj):
        return cmp(self.id, obj)

    def call(self, eventobj):
        self.handler(eventobj)

    def clear_masks(self, dispatcher):
        if self.masks is not None:
            dispatcher.unset_masks(self.masks)
            self.masks = None

class EventDispatcher:
    def __init__(self):
        self.system_events = {}
        self.grab_events = {}
        self.normal_events = {}


    def handle_event(self, eventobj, systemonly = 0):

        """Dispatch the event EVENTOBJ to all matching handlers.

        If SYSTEMONLY is true, skip calling grab and normal event
        handlers.

        Returns 1 if a grab event handler was called, 0 otherwise.
        """

        # Call all the system event handlers, and then
        # quit if systemonly is true.

        for eh in self.system_events.get(eventobj.type, []):
            eh.call(eventobj)

        if systemonly:
            return 1

        # If there are any grab events for this type,
        # call the last one and then quit.  Otherwise
        # call all the normal event handlers.

        try:
            eh = self.grab_events[eventobj.type][-1]
        except (KeyError, IndexError):
            eh = None

        if eh is not None:
            eh.call(eventobj)
            return 1
        else:
            for eh in self.normal_events.get(eventobj.type, []):
                eh.call(eventobj)
            return 0

    def add_handler(self, event, handler, masks = None, handlerid = None):

        """Add an event handler for this window.

        EVENT is an event type identifier.  This can be one of the
        numeric constants defined in X.py, a string, or any other
        object which can be used as a key in a mapping.

        HANDLER is a function which gets called with a single
        argument: the event object.  All event object has a `type'
        attribute which will have the value of EVENT.

        MASKS can be a tuple or list of X event masks to set on this
        window.  If omitted or None, default masks for this event will
        be set, if any.

        If HANDLERID is provided, it will be an object used to
        identify this handler when calling
        EventDispatcher.remove_handler().  If omitted, HANDLER itself
        will be used.
        """

        self.add_handler_type(self.normal_events, event, handler,
                              masks, handlerid)


    def add_system_handler(self, event, handler, masks = None, handlerid = None):

        """Add a system handler for this window.  The arguments are
        the same as for EventDispatcher.add_handler().

        A system handler will be called before any grab or normal handlers.
        """
        self.add_handler_type(self.system_events, event, handler,
                              masks, handlerid)


    def add_grab_handler(self, event, handler, masks = None, handlerid = None):

        """Add a grab handler for this window.  The arguments are
        the same as for EventDispatcher.add_handler().

        A grab handler will prevent previously added grab handlers and
        any normal handlers from being called.  System handlers will
        be called as normal, however.
        """

        self.add_handler_type(self.grab_events, event, handler,
                              masks, handlerid)


    def add_handler_type(self, dict, event, handler, masks, handlerid):

        """Internal function used to add handlers."""

        if masks is None:
            masks = default_event_masks.get(event, None)

        if handlerid is None:
            handlerid = handler

        eh = EventHandler(handler, masks, handlerid)
        if dict.has_key(event):
            dict[event].append(eh)
        else:
            dict[event] = [eh]

        if masks is not None:
            self.set_masks(masks)


    def remove_handler(self, handlerid):

        """Remove the handler identified by HANDLERID.

        This will also clear any masks this handler has set.
        """

        for dict in self.system_events, self.grab_events, self.normal_events:
            for hs in dict.values():
                ok = 1
                while ok:
                    try:
                        i = hs.index(handlerid)
                    except ValueError:
                        ok = 0
                    else:
                        hs[i].clear_masks(self)
                        del hs[i]

    def set_masks(self, masks, onerror = None):

        """Set MASKS on the window.

        MASKS can either be an X.*Mask constant or a list of such
        constants.
        """
        pass

    def unset_masks(self, masks, onerror = None):

        """Unset MASKS on the window.

        The inverse of EventDispatcher.set_masks().
        """
        pass

    def block_masks(self, masks, onerror = None):

        """Temporarily block MASKS on the window.

        MASKS can either be an X.*Mask constant or a list of such
        constants.
        """
        pass

    def unblock_masks(self, masks, onerror = None):

        """Remove block on MASKS on the window.

        The inverse of EventDispatcher.block_masks().
        """
        pass


class WindowDispatcher(EventDispatcher):
    def __init__(self, window):
        """Create an event dispatcher for WINDOW.

        WINDOW is the window object we should set masks on.  If
        omitted or None, no masks will be set but the event dispatcher
        can still be used for synthetic events.
        """

        EventDispatcher.__init__(self)

        self.window = window
        self.masks = {}
        self.blocked_masks = {}

    def set_masks(self, masks, onerror = None):

        """Set MASKS on the window.

        MASKS can either be an X.*Mask constant or a list of such
        constants.
        """

        if type(masks) is types.IntType:
            self.masks[masks] = self.masks.get(masks, 0) + 1
        else:
            for m in masks:
                self.masks[m] = self.masks.get(m, 0) + 1

        self.update_window_mask(onerror)


    def unset_masks(self, masks, onerror = None):

        """Unset MASKS on the window.

        The inverse of EventDispatcher.set_masks().
        """

        if type(masks) is types.IntType:
            masks = [masks]

        for m in masks:
            rc = self.masks.get(m, None)
            if rc is None:
                pass
            elif rc == 1:
                del self.masks[m]
            else:
                self.masks[m] = rc - 1

        self.update_window_mask(onerror)


    def block_masks(self, masks, onerror = None):

        """Temporarily block MASKS on the window.

        MASKS can either be an X.*Mask constant or a list of such
        constants.
        """

        if type(masks) is types.IntType:
            self.blocked_masks[masks] = self.blocked_masks.get(masks, 0) + 1
        else:
            for m in masks:
                self.blocked_masks[m] = self.blocked_masks.get(m, 0) + 1

        self.update_window_mask(onerror)


    def unblock_masks(self, masks, onerror = None):

        """Remove block on MASKS on the window.

        The inverse of EventDispatcher.block_masks().
        """

        if type(masks) is types.IntType:
            masks = [masks]

        for m in masks:
            rc = self.blocked_masks.get(m, None)
            if rc is None:
                pass
            elif rc == 1:
                del self.blocked_masks[m]
            else:
                self.blocked_masks[m] = rc - 1

        self.update_window_mask(onerror)


    def update_window_mask(self, onerror = None):

        """Configure the window mask to reflect any changes.
        """

        mask = 0
        for m in self.masks.keys():
            if not self.blocked_masks.has_key(m):
                mask = mask | m

        self.window.change_attributes(event_mask = mask, onerror = onerror)


class SlaveDispatcher(EventDispatcher):
    def __init__(self, masters):
        """Create a SlaveDispatcher for MASTERS.

        MASTERS is a list of other EventDispatchers which this class
        will call when setting, clearing, blocking and unblocking masks.
        """

        EventDispatcher.__init__(self)
        # Copy list, since we can modify list later
        self.masters = list(masters)

    def add_master(self, master):
        """Add a master dispatcher to this slave dispatcher.
        """
        self.masters.append(master)

    def set_masks(self, masks, onerror = None):

        """Set MASKS on the window.

        MASKS can either be an X.*Mask constant or a list of such
        constants.
        """
        for m in self.masters:
            m.set_masks(masks, onerror)

    def unset_masks(self, masks, onerror = None):

        """Unset MASKS on the window.

        The inverse of EventDispatcher.set_masks().
        """
        for m in self.masters:
            m.unset_masks(masks, onerror)

    def block_masks(self, masks, onerror = None):

        """Temporarily block MASKS on the window.

        MASKS can either be an X.*Mask constant or a list of such
        constants.
        """
        for m in self.masters:
            m.block_masks(masks, onerror)


    def unblock_masks(self, masks, onerror = None):

        """Remove block on MASKS on the window.

        The inverse of EventDispatcher.block_masks().
        """
        for m in self.masters:
            m.unblock_masks(masks, onerror)