1# -*- Mode: Python; py-indent-offset: 4 -*-
2# vim: tabstop=4 shiftwidth=4 expandtab
3#
4# Copyright (C) 2009 Johan Dahlin <johan@gnome.org>
5#               2010 Simon van der Linden <svdlinden@src.gnome.org>
6#
7# This library is free software; you can redistribute it and/or
8# modify it under the terms of the GNU Lesser General Public
9# License as published by the Free Software Foundation; either
10# version 2.1 of the License, or (at your option) any later version.
11#
12# This library 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 GNU
15# Lesser General Public License for more details.
16#
17# You should have received a copy of the GNU Lesser General Public
18# License along with this library; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
20# USA
21
22from ..overrides import override
23from ..importer import modules
24
25import sys
26
27Gdk = modules['Gdk']._introspection_module
28
29__all__ = []
30
31class Color(Gdk.Color):
32
33    def __init__(self, red, green, blue):
34        Gdk.Color.__init__(self)
35        self.red = red
36        self.green = green
37        self.blue = blue
38
39    def __new__(cls, *args, **kwargs):
40        return Gdk.Color.__new__(cls)
41
42    def __eq__(self, other):
43        return self.equal(other)
44
45    def __repr__(self):
46        return '<Gdk.Color(red=%d, green=%d, blue=%d)>' % (self.red, self.green, self.blue)
47
48Color = override(Color)
49__all__.append('Color')
50
51if Gdk._version == '3.0':
52    class RGBA(Gdk.RGBA):
53        def __init__(self, red=1.0, green=1.0, blue=1.0, alpha=1.0):
54            Gdk.RGBA.__init__(self)
55            self.red = red
56            self.green = green
57            self.blue = blue
58            self.alpha = alpha
59
60        def __new__(cls, *args, **kwargs):
61            return Gdk.RGBA.__new__(cls)
62
63        def __eq__(self, other):
64            return self.equal(other)
65
66        def __repr__(self):
67            return '<Gdk.Color(red=%f, green=%f, blue=%f, alpha=%f)>' % (self.red, self.green, self.blue, self.alpha)
68
69    RGBA = override(RGBA)
70    __all__.append('RGBA')
71
72if Gdk._version == '2.0':
73    class Rectangle(Gdk.Rectangle):
74
75        def __init__(self, x, y, width, height):
76            Gdk.Rectangle.__init__(self)
77            self.x = x
78            self.y = y
79            self.width = width
80            self.height = height
81
82        def __new__(cls, *args, **kwargs):
83            return Gdk.Rectangle.__new__(cls)
84
85        def __repr__(self):
86            return '<Gdk.Rectangle(x=%d, y=%d, width=%d, height=%d)>' % (self.x, self.y, self.height, self.width)
87
88    Rectangle = override(Rectangle)
89    __all__.append('Rectangle')
90else:
91    from gi.repository import cairo as _cairo
92    Rectangle = _cairo.RectangleInt
93
94    __all__.append('Rectangle')
95
96if Gdk._version == '2.0':
97    class Drawable(Gdk.Drawable):
98        def cairo_create(self):
99            return Gdk.cairo_create(self)
100
101    Drawable = override(Drawable)
102    __all__.append('Drawable')
103else:
104    class Window(Gdk.Window):
105        def __new__(cls, parent, attributes, attributes_mask):
106            # Gdk.Window had to be made abstract,
107            # this override allows using the standard constructor
108            return Gdk.Window.new(parent, attributes, attributes_mask)
109        def __init__(self, parent, attributes, attributes_mask):
110            pass
111        def cairo_create(self):
112            return Gdk.cairo_create(self)
113
114    Window = override(Window)
115    __all__.append('Window')
116
117Gdk.EventType._2BUTTON_PRESS = getattr(Gdk.EventType, "2BUTTON_PRESS")
118Gdk.EventType._3BUTTON_PRESS = getattr(Gdk.EventType, "3BUTTON_PRESS")
119
120class Event(Gdk.Event):
121    _UNION_MEMBERS = {
122        Gdk.EventType.DELETE: 'any',
123        Gdk.EventType.DESTROY: 'any',
124        Gdk.EventType.EXPOSE: 'expose',
125        Gdk.EventType.MOTION_NOTIFY: 'motion',
126        Gdk.EventType.BUTTON_PRESS: 'button',
127        Gdk.EventType._2BUTTON_PRESS: 'button',
128        Gdk.EventType._3BUTTON_PRESS: 'button',
129        Gdk.EventType.BUTTON_RELEASE: 'button',
130        Gdk.EventType.KEY_PRESS: 'key',
131        Gdk.EventType.KEY_RELEASE: 'key',
132        Gdk.EventType.ENTER_NOTIFY: 'crossing',
133        Gdk.EventType.LEAVE_NOTIFY: 'crossing',
134        Gdk.EventType.FOCUS_CHANGE: 'focus_change',
135        Gdk.EventType.CONFIGURE: 'configure',
136        Gdk.EventType.MAP: 'any',
137        Gdk.EventType.UNMAP: 'any',
138        Gdk.EventType.PROPERTY_NOTIFY: 'property',
139        Gdk.EventType.SELECTION_CLEAR: 'selection',
140        Gdk.EventType.SELECTION_REQUEST: 'selection',
141        Gdk.EventType.SELECTION_NOTIFY: 'selection',
142        Gdk.EventType.PROXIMITY_IN: 'proximity',
143        Gdk.EventType.PROXIMITY_OUT: 'proximity',
144        Gdk.EventType.DRAG_ENTER: 'dnd',
145        Gdk.EventType.DRAG_LEAVE: 'dnd',
146        Gdk.EventType.DRAG_MOTION: 'dnd',
147        Gdk.EventType.DRAG_STATUS: 'dnd',
148        Gdk.EventType.DROP_START: 'dnd',
149        Gdk.EventType.DROP_FINISHED: 'dnd',
150        Gdk.EventType.CLIENT_EVENT: 'client',
151        Gdk.EventType.VISIBILITY_NOTIFY: 'visibility',
152    }
153
154    if Gdk._version == '2.0':
155        _UNION_MEMBERS[Gdk.EventType.NO_EXPOSE] = 'no_expose'
156
157    def __new__(cls, *args, **kwargs):
158        return Gdk.Event.__new__(cls)
159
160    def __getattr__(self, name):
161        real_event = getattr(self, '_UNION_MEMBERS').get(self.type)
162        if real_event:
163            return getattr(getattr(self, real_event), name)
164        else:
165            raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
166
167Event = override(Event)
168__all__.append('Event')
169
170# manually bind GdkEvent members to GdkEvent
171
172modname = globals()['__name__']
173module = sys.modules[modname]
174
175# right now we can't get the type_info from the
176# field info so manually list the class names
177event_member_classes = ['EventAny',
178                        'EventExpose',
179                        'EventVisibility',
180                        'EventMotion',
181                        'EventButton',
182                        'EventScroll',
183                        'EventKey',
184                        'EventCrossing',
185                        'EventFocus',
186                        'EventConfigure',
187                        'EventProperty',
188                        'EventSelection',
189                        'EventOwnerChange',
190                        'EventProximity',
191                        'EventDND',
192                        'EventWindowState',
193                        'EventSetting',
194                        'EventGrabBroken']
195
196if Gdk._version == '2.0':
197    event_member_classes.append('EventNoExpose')
198
199# whitelist all methods that have a success return we want to mask
200gsuccess_mask_funcs = ['get_state',
201                       'get_axis',
202                       'get_coords',
203                       'get_root_coords']
204
205def _gsuccess_mask(func):
206    def cull_success(*args):
207        result = func(*args)
208        success = result[0]
209        if success == False:
210            return None
211        else:
212            if len(result) == 2:
213                return result[1]
214            else:
215                return result[1:]
216    return cull_success
217
218for event_class in event_member_classes:
219    override_class = type(event_class, (getattr(Gdk, event_class),), {})
220    # add the event methods
221    for method_info in Gdk.Event.__info__.get_methods():
222        name = method_info.get_name()
223        event_method = getattr(Gdk.Event, name)
224        # python2 we need to use the __func__ attr to avoid internal
225        # instance checks
226        event_method = getattr(event_method, '__func__', event_method)
227
228        # use the _gsuccess_mask decorator if this method is whitelisted
229        if name in gsuccess_mask_funcs:
230            event_method = _gsuccess_mask(event_method)
231        setattr(override_class, name, event_method)
232
233    setattr(module, event_class, override_class)
234    __all__.append(event_class)
235
236# end GdkEvent overrides
237
238class DragContext(Gdk.DragContext):
239    def finish(self, success, del_, time):
240        Gtk = modules['Gtk']._introspection_module
241        Gtk.drag_finish(self, success, del_, time)
242
243DragContext = override(DragContext)
244__all__.append('DragContext')
245
246class Cursor(Gdk.Cursor):
247    def __new__(cls, *args, **kwds):
248        arg_len = len(args)
249        kwd_len = len(kwds)
250        total_len = arg_len + kwd_len
251
252        def _new(cursor_type):
253            return cls.new(cursor_type)
254
255        def _new_for_display(display, cursor_type):
256            return cls.new_for_display(display, cursor_type)
257
258        def _new_from_pixbuf(display, pixbuf, x, y):
259            return cls.new_from_pixbuf(display, pixbuf, x, y)
260
261        def _new_from_pixmap(source, mask, fg, bg, x, y):
262            return cls.new_from_pixmap(source, mask, fg, bg, x, y)
263
264        _constructor = None
265        if total_len == 1:
266            _constructor = _new
267        elif total_len == 2:
268            _constructor = _new_for_display
269        elif total_len == 4:
270            _constructor = _new_from_pixbuf
271        elif total_len == 6:
272            if Gdk._version != '2.0':
273                # pixmaps don't exist in Gdk 3.0
274                raise ValueError("Wrong number of parameters")
275            _constructor = _new_from_pixmap
276        else:
277            raise ValueError("Wrong number of parameters")
278
279        return _constructor(*args, **kwds)
280
281    def __init__(self, *args, **kwargs):
282        Gdk.Cursor.__init__(self)
283
284Cursor = override(Cursor)
285__all__.append('Cursor')
286
287import sys
288
289initialized, argv = Gdk.init_check(sys.argv)
290if not initialized:
291    raise RuntimeError("Gdk couldn't be initialized")
292