~aw/sabayon-template/trunk

1 by Sebastien Bacher
Import upstream version 2.11.90
1
#
2
# Copyright (C) 2005 Red Hat, Inc.
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
#
18
19
import gobject
20
import gtk
21
import gtk.gdk
22
import xlib
23
import util
1.1.6 by Christoph Maerz
Import upstream version 2.19.1
24
import debuglog
1 by Sebastien Bacher
Import upstream version 2.11.90
25
26
def dprint (fmt, *args):
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
27
    debuglog.debug_log (False, debuglog.DEBUG_LOG_DOMAIN_SESSION_WIDGET, fmt % args)
1 by Sebastien Bacher
Import upstream version 2.11.90
28
    
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
29
def session_window_subwindow_created_cb (xid, user_data):
30
    self = user_data
31
32
    dprint ("subwindow got created with xid %x", xid)
33
34
    self.xephyr_window = gtk.gdk.window_foreign_new_for_display (gtk.gdk.display_get_default (), xid)
35
    dprint ("gdk foreign window created, %s", self.xephyr_window)
36
1 by Sebastien Bacher
Import upstream version 2.11.90
37
class SessionWidget (gtk.Widget):
38
    # FIXME:
39
    #   Should be able override do_size_allocate() without this
40
    #   See bug #308099
41
    __gsignals__ = { 'size-allocate' : 'override' }
42
    
43
    def __init__ (self, session_width, session_height):
44
        gtk.Widget.__init__ (self)
45
        
46
        self.set_flags (self.flags() | gtk.NO_WINDOW)
47
        self.set_property ("can-focus", True)
48
49
        self.session_width  = session_width
50
        self.session_height = session_height
51
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
52
        self.xephyr_window = None
53
1 by Sebastien Bacher
Import upstream version 2.11.90
54
    def do_size_request (self, requisition):
55
        focus_width = self.style_get_property ("focus-line-width")
56
        focus_pad   = self.style_get_property ("focus-padding")
57
        
58
        requisition.width  = self.session_width  + 2 * focus_width + 2 * focus_pad
59
        requisition.height = self.session_height + 2 * focus_width + 2 * focus_pad
60
61
    def __calculate_position (self, allocation):
62
        focus_width = self.style_get_property ("focus-line-width")
63
        focus_pad   = self.style_get_property ("focus-padding")
64
65
        x = allocation.x + focus_width + focus_pad
66
        y = allocation.y + focus_width + focus_pad
67
            
68
        alloc_width  = allocation.width  - 2 * focus_width - 2 * focus_pad
69
        alloc_height = allocation.height - 2 * focus_width - 2 * focus_pad
70
71
        x += max (0, (alloc_width  - self.session_width)  / 2)
72
        y += max (0, (alloc_height - self.session_height) / 2)
73
74
        return (x, y)
75
76
    def do_size_allocate (self, allocation):
77
        self.allocation = allocation
78
79
        if self.flags() & gtk.REALIZED:
80
            (x, y) = self.__calculate_position (allocation)
81
            
82
            self.session_window.move_resize (x, y, self.session_width, self.session_height)
83
            self.input_window.move_resize   (x, y, self.session_width, self.session_height)
84
85
    def do_realize (self):
86
        gtk.Widget.do_realize (self)
87
88
        (x, y) = self.__calculate_position (self.allocation)
89
90
        self.session_window = gtk.gdk.Window (parent = self.get_parent_window (),
91
                                              window_type = gtk.gdk.WINDOW_CHILD,
92
                                              x = x,
93
                                              y = y,
94
                                              width  = self.session_width,
95
                                              height = self.session_height,
96
                                              wclass = gtk.gdk.INPUT_OUTPUT,
97
                                              visual = self.get_visual (),
98
                                              colormap = self.get_colormap (),
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
99
                                              event_mask = gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.SUBSTRUCTURE_MASK)
1 by Sebastien Bacher
Import upstream version 2.11.90
100
        self.session_window.set_user_data (self)
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
101
        dprint ("session window has xid %x", self.session_window.xid)
102
103
        # We use Xephyr's "-parent" option to tell it where to create
104
        # its window.  However, Xephyr does not use our window
105
        # directly for drawing.  Instead, it creates a subwindow in
106
        # our parent window, and uses *that*.  So, the events that we
107
        # proxy to Xephyr must be sent to the window that it creates.
108
        #
109
        # To get notified when Xephyr creates its window inside ours,
110
        # we select for gtk.gdk.SUBSTRUCTURE_MASK above.  However,
111
        # there's no GDK_* event for CreateNotify events.  In an ideal
112
        # world, we could just install a window event filter to
113
        # extract that event ourselves.
114
        #
115
        # However, PyGTK is buggy and doesn't implement
116
        # gdk_window_add_filter() correctly (see
117
        # http://bugzilla.gnome.org/show_bug.cgi?id=156948).  So, we
118
        # use our own wrapper for that function...
119
        xlib.window_capture_create_notify (self.session_window, session_window_subwindow_created_cb, self)
1 by Sebastien Bacher
Import upstream version 2.11.90
120
121
        event_mask = gtk.gdk.BUTTON_PRESS_MASK   | \
122
                     gtk.gdk.BUTTON_RELEASE_MASK | \
123
                     gtk.gdk.POINTER_MOTION_MASK | \
124
                     gtk.gdk.ENTER_NOTIFY_MASK   | \
125
                     gtk.gdk.LEAVE_NOTIFY_MASK   | \
126
                     gtk.gdk.KEY_PRESS_MASK      | \
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
127
                     gtk.gdk.KEY_RELEASE_MASK
1 by Sebastien Bacher
Import upstream version 2.11.90
128
129
        self.input_window = gtk.gdk.Window (parent = self.get_parent_window (),
130
                                            window_type = gtk.gdk.WINDOW_CHILD,
131
                                            x = x,
132
                                            y = y,
133
                                            width  = self.session_width,
134
                                            height = self.session_height,
135
                                            wclass = gtk.gdk.INPUT_ONLY,
136
                                            visual = self.get_visual (),
137
                                            colormap = self.get_colormap (),
138
                                            event_mask = event_mask)
139
        self.input_window.set_user_data (self)
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
140
        dprint ("Created input_only window for child session")
1 by Sebastien Bacher
Import upstream version 2.11.90
141
142
    def do_unrealize (self):
143
        # FIXME:
144
        #   Causes a warning with pygtk 2.6.2
145
        #   See bug #308384
146
        self.input_window.set_user_data (None)
147
        self.input_window.destroy ()
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
148
        dprint ("Destroyed input_only window for child session")
1 by Sebastien Bacher
Import upstream version 2.11.90
149
        
150
        self.session_window.set_user_data (None)
151
        self.session_window.destroy ()
152
        
153
        gtk.Widget.do_unrealize (self)
154
155
    def do_map (self):
156
        gtk.Widget.do_map (self)
157
        self.session_window.show ()
158
        self.input_window.show ()
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
159
        dprint ("Showed input_only window for child session")
1 by Sebastien Bacher
Import upstream version 2.11.90
160
161
    def do_unmap (self):
162
        self.input_window.hide ()
163
        self.session_window.hide ()
164
        gtk.Widget.do_unmap (self)
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
165
        dprint ("Hid input_only window for child session")
1 by Sebastien Bacher
Import upstream version 2.11.90
166
167
    def do_expose_event (self, event):
168
        if self.flags() & gtk.HAS_FOCUS:
169
            focus_width = self.style_get_property ("focus-line-width")
170
            focus_pad   = self.style_get_property ("focus-padding")
171
            
172
            (x, y) = self.__calculate_position (self.allocation)
173
174
            self.style.paint_focus (self.window,
175
                                    self.state,
176
                                    event.area,
177
                                    self,
178
                                    "sabayon-session",
179
                                    x - focus_width - focus_pad,
180
                                    y - focus_width - focus_pad,
181
                                    self.session_width  + 2 * focus_width + 2 * focus_pad,
182
                                    self.session_height + 2 * focus_width + 2 * focus_pad)
183
        return False
184
185
    def __update_input_only_window (self):
186
        if not self.flags() & gtk.REALIZED:
187
            return
188
        
189
        if self.flags() & gtk.HAS_FOCUS:
190
            self.input_window.hide ()
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
191
            dprint ("Focus in: hiding input_only window for child session")
1 by Sebastien Bacher
Import upstream version 2.11.90
192
        else:
193
            self.input_window.show ()
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
194
            dprint ("Focus out: showing input_only window for child session")
1 by Sebastien Bacher
Import upstream version 2.11.90
195
            
196
    def do_focus_in_event (self, event):
197
        self.__update_input_only_window ()
198
        return gtk.Widget.do_focus_in_event (self, event)
199
200
    def do_focus_out_event (self, event):
201
        self.__update_input_only_window ()
202
        return gtk.Widget.do_focus_in_event (self, event)
203
204
    def do_button_press_event (self, event):
205
        if not self.flags() & gtk.HAS_FOCUS:
206
            self.grab_focus ()
207
            
208
        if not event.send_event:
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
209
            if self.xephyr_window:
210
                dprint ("Resending button press; button = %d, state = 0x%x", event.button, event.state)
211
                xlib.send_button_event (self.xephyr_window, True, event.time, event.button, event.state)
1 by Sebastien Bacher
Import upstream version 2.11.90
212
        
213
        return True
214
    
215
    def do_button_release_event (self, event):
216
        if not event.send_event:
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
217
            if self.xephyr_window:
218
                dprint ("Resending button release; button = %d, state = 0x%x", event.button, event.state)
219
                xlib.send_button_event (self.xephyr_window, False, event.time, event.button, event.state)
1 by Sebastien Bacher
Import upstream version 2.11.90
220
        
221
        return True
222
223
    def do_motion_notify_event (self, event):
224
        if not event.send_event:
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
225
            if self.xephyr_window:
226
                dprint ("Resending motion notify; x = %d, y = %d", event.x, event.y)
227
                xlib.send_motion_event (self.xephyr_window, event.time, event.x, event.y);
1 by Sebastien Bacher
Import upstream version 2.11.90
228
        
229
        return True
230
    
231
    def do_enter_notify_event (self, event):
232
        if not event.send_event:
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
233
            if self.xephyr_window:
234
                dprint ("Resending enter notify; x = %d, y = %d, detail = %d", event.x, event.y, event.detail)
235
                xlib.send_crossing_event (self.xephyr_window, False, event.time, event.x, event.y, event.detail);
1 by Sebastien Bacher
Import upstream version 2.11.90
236
        
237
        return True
238
    
239
    def do_leave_notify_event (self, event):
240
        if not event.send_event:
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
241
            if self.xephyr_window:
242
                dprint ("Resending leave notify; x = %d, y = %d, detail = %d", event.x, event.y, event.detail)
243
                xlib.send_crossing_event (self.xephyr_window, False, event.time, event.x, event.y, event.detail);
1 by Sebastien Bacher
Import upstream version 2.11.90
244
        
245
        return True
246
    
247
    def do_key_press_event (self, event):
248
        if not event.send_event:
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
249
            if self.xephyr_window:
250
                dprint ("Resending key press; keycode = 0x%x, state = 0x%x", event.hardware_keycode, event.state)
251
                xlib.send_key_event (self.xephyr_window, True, event.time, event.hardware_keycode, event.state)
1 by Sebastien Bacher
Import upstream version 2.11.90
252
        
253
        return True
254
255
    def do_key_release_event (self, event):
256
        if not event.send_event:
1.1.13 by Christophe Sauthier
Import upstream version 2.27.0
257
            if self.xephyr_window:
258
                dprint ("Resending key release; keycode = 0x%x, state = 0x%x", event.hardware_keycode, event.state)
259
                xlib.send_key_event (self.xephyr_window, False, event.time, event.hardware_keycode, event.state)
1 by Sebastien Bacher
Import upstream version 2.11.90
260
        
261
        return True
262
263
gobject.type_register (SessionWidget)