This file is indexed.

/usr/share/pyshared/wimpiggy/world_window.py is in python-wimpiggy 0.0.7.36+dfsg-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
# This file is part of Parti.
# Copyright (C) 2008, 2009 Nathaniel Smith <njs@pobox.com>
# Parti is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

import gtk
import gobject
import wimpiggy.window
import wimpiggy.prop
from wimpiggy.error import trap
from wimpiggy.log import Logger
from wimpiggy.lowlevel import (
               const,                           #@UnresolvedImport
               send_wm_take_focus               #@UnresolvedImport
               )
log = Logger()

# This file defines Wimpiggy's top-level widget.  It is a magic window that
# always and exactly covers the entire screen (possibly crossing multiple
# screens, in the Xinerama case); it also mediates between the GTK+ and X
# focus models.
# 
# This requires a very long comment, because focus management is teh awesome.
# The basic problems are:
#    1) X focus management sucks
#    2) GDK/GTK know this, and sensibly avoids it
# (1) is a problem by itself, but (2) makes it worse, because we have to wedge
# them together somehow anyway.
#
# In more detail: X tracks which X-level window has (keyboard) focus at each
# point in time.  This is the window which receives KeyPress and KeyRelease
# events.  GTK also has a notion of focus; at any given time (within a
# particular toplevel) exactly one widget is focused.  This is the widget
# which receives key-press-event and key-release-event signals.  However,
# at the level of implementation, these two ideas of focus are actually kept
# entirely separate.  In fact, when a GTK toplevel gets focus, it sets the X
# input focus to a special hidden window, reads X events off of that window,
# and then internally routes these events to whatever the appropriate widget
# would be at any given time.
#
# The other thing which GTK does with focus is simply tweak the drawing style
# of widgets.  A widget that is focused within its toplevel can/will look
# different from a widget that does not have focus within its toplevel.
# Similarly, a widget may look different depending on whether the toplevel
# that contains it has toplevel focus or not.
#
# Unfortunately, we cannot read keyboard events out of the special hidden
# window and route them to client windows; to be a proper window manager, we
# must actually assign X focus to client windows, while pretending to GTK+
# that nothing funny is going on, and our client windows are just ordinary
# widgets.
#
# So there are a few pieces to this.  Firstly, GTK tracks focus on toplevels
# by watching for focus events from X, which ultimately come from the window
# manager.  Since we *are* the window manager, this is not particularly
# useful.  Instead, we create a special subclass of gtk.Window that fills the
# whole screen, and trick GTK into thinking that this toplevel *always* has
# (GTK) focus.
#
# Then, to manage the actual X focus, we do a little dance, watching the GTK
# focus within our special toplevel.  Whenever it moves to a widget that
# actually represents a client window, we send the X focus to that client
# window.  Whenever it moves to a widget that is actually an ordinary widget,
# we take the X focus back to our special toplevel.
#
# Note that this means that we do violate our overall goal of making client
# window widgets indistinguishable from ordinary GTK widgets, because client
# window widgets can only be placed inside this special toplevel, and this
# toplevel has special-cased handling for our particular client-wrapping
# widget.  In practice this should not be a problem.
#
# Finally, we have to notice when the root window gets focused (as it can when
# a client misbehaves, or perhaps exits in a weird way), and regain the
# focus.  The Wm object is actually responsible for doing this (since it is
# responsible for all root-window event handling); we just expose an API
# ('reset_x_focus') that people should call whenever they think that focus may
# have gone wonky.

class WorldWindow(gtk.Window):
    def __init__(self):
        super(WorldWindow, self).__init__()

        # FIXME: This would better be a default handler, but there is a bug in
        # the superclass's default handler that means we can't call it
        # properly[0], so as a workaround we let the real default handler run,
        # and then come in afterward to do what we need to.  (See also
        # Viewport._after_set_focus_child.)
        #   [0] http://bugzilla.gnome.org/show_bug.cgi?id=462368
        self.connect_after("set-focus", self._after_set_focus)

        # Make sure that we are always the same size as the screen
        self.set_resizable(False)
        gtk.gdk.screen_get_default().connect("size-changed", self._resize)
        self.move(0, 0)
        self._resize()
        
    def _resize(self, *args):
        x = gtk.gdk.screen_width()
        y = gtk.gdk.screen_height()
        log("sizing world to %sx%s", x, y)
        self.set_size_request(x, y)
        self.resize(x, y)
        wimpiggy.prop.prop_set(gtk.gdk.get_default_root_window(),
                            "_NET_DESKTOP_GEOMETRY",
                            ["u32"], [x, y])

    # We want to fake GTK out into thinking that this window always has
    # toplevel focus, no matter what happens.  There are two parts to this:
    # (1) getting has-toplevel-focus set to start with, (2) making sure it is
    # never unset.  (2) is easy -- we just override do_focus_out_event to
    # silently swallow all FocusOut events, so we never notice losing the
    # focus.  (1) is harder, because we can't just go ahead and set
    # has-toplevel-focus to true; there is a bunch of other stuff that GTK
    # does from the focus-in-event handler, and we want to do all of that.  To
    # make it worse, we cannot call the focus-in-event handler unless we
    # actually have a GdkEvent to pass it, and PyGtk does not expose any
    # constructor for GdkEvents!  So instead, we:
    #   -- force focus to ourselves for real, once, when becoming visible
    #   -- let the normal GTK machinery handle this first FocusIn
    #      -- it is possible that we should not in fact have the X focus at
    #         this time, though, so then give it to whoever should
    #   -- and finally ignore all subsequent focus-in-events
    def do_map(self, *args):
        gtk.Window.do_map(self, *args)

        # We are being mapped, so we can focus ourselves.
        # Check for the property, just in case this is the second time we are
        # being mapped -- otherwise we might miss the special call to
        # reset_x_focus in do_focus_in_event:
        if not self.get_property("has-toplevel-focus"):
            # Take initial focus upon being mapped.  Technically it is illegal
            # (ICCCM violating) to use CurrentTime in a WM_TAKE_FOCUS message,
            # but GTK doesn't happen to care, and this guarantees that we
            # *will* get the focus, and thus a real FocusIn event.
            current_time = const["CurrentTime"]
            send_wm_take_focus(self.window, current_time)

    def do_focus_in_event(self, *args):
        log("world window got focus", type="focus")
        if not self.get_property("has-toplevel-focus"):
            #super(WorldWindow, self).do_focus_in_event(*args)
            gtk.Window.do_focus_in_event(self, *args)
            self.reset_x_focus()

    def do_focus_out_event(self, *args):
        # Do nothing -- harder:
        self.stop_emission("focus-out-event")
        return False

    def _take_focus(self):
        log("Focus -> world window", type="focus")
        assert self.flags() & gtk.REALIZED
        # Weird hack: we are a GDK window, and the only way to properly get
        # input focus to a GDK window is to send it WM_TAKE_FOCUS.  So this is
        # sending a WM_TAKE_FOCUS to our own window, which will go to the X
        # server and then come back to our own process, which will then issue
        # an XSetInputFocus on itself.  Note not swallowing errors here, this
        # should always succeed.
        now = gtk.gdk.x11_get_server_time(self.window)
        send_wm_take_focus(self.window, now)

    def reset_x_focus(self):
        focus = self.get_focus()
        log("widget with focus: %s", focus, type="focus")
        if isinstance(focus, wimpiggy.window.WindowView):
            # FIXME: ugly:
            focus.model.give_client_focus()
            trap.swallow(wimpiggy.prop.prop_set, gtk.gdk.get_default_root_window(),
                         "_NET_ACTIVE_WINDOW", "window",
                         focus.model.get_property("client-window"))
        else:
            self._take_focus()
            wimpiggy.prop.prop_set(gtk.gdk.get_default_root_window(),
                                   "_NET_ACTIVE_WINDOW", "u32", const["XNone"])

    def _after_set_focus(self, *args):
        # GTK focus has changed.  See comment in __init__ for why this isn't a
        # default handler.
        if self.get_focus() is not None:
            self.reset_x_focus()

gobject.type_register(WorldWindow)