]> Pileus Git - ~andy/gtk/blob - gdk/broadway/gdkdevicemanager-broadway.c
Remove event translators
[~andy/gtk] / gdk / broadway / gdkdevicemanager-broadway.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include "gdkdevicemanager-broadway.h"
23
24 #include "gdktypes.h"
25 #include "gdkdevicemanager.h"
26 #include "gdkdevice-broadway.h"
27 #include "gdkkeysyms.h"
28 #include "gdkprivate-broadway.h"
29 #include "gdkx.h"
30
31 #ifdef HAVE_XKB
32 #include <X11/XKBlib.h>
33 #endif
34
35
36 #define HAS_FOCUS(toplevel)                           \
37   ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
38
39 static void    gdk_device_manager_core_finalize    (GObject *object);
40 static void    gdk_device_manager_core_constructed (GObject *object);
41
42 static GList * gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager,
43                                                      GdkDeviceType     type);
44 static GdkDevice * gdk_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager);
45
46 G_DEFINE_TYPE (GdkDeviceManagerCore, gdk_device_manager_core, GDK_TYPE_DEVICE_MANAGER)
47
48 static void
49 gdk_device_manager_core_class_init (GdkDeviceManagerCoreClass *klass)
50 {
51   GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
52   GObjectClass *object_class = G_OBJECT_CLASS (klass);
53
54   object_class->finalize = gdk_device_manager_core_finalize;
55   object_class->constructed = gdk_device_manager_core_constructed;
56   device_manager_class->list_devices = gdk_device_manager_core_list_devices;
57   device_manager_class->get_client_pointer = gdk_device_manager_core_get_client_pointer;
58 }
59
60 static GdkDevice *
61 create_core_pointer (GdkDeviceManager *device_manager,
62                      GdkDisplay       *display)
63 {
64   return g_object_new (GDK_TYPE_DEVICE_CORE,
65                        "name", "Core Pointer",
66                        "type", GDK_DEVICE_TYPE_MASTER,
67                        "input-source", GDK_SOURCE_MOUSE,
68                        "input-mode", GDK_MODE_SCREEN,
69                        "has-cursor", TRUE,
70                        "display", display,
71                        "device-manager", device_manager,
72                        NULL);
73 }
74
75 static GdkDevice *
76 create_core_keyboard (GdkDeviceManager *device_manager,
77                       GdkDisplay       *display)
78 {
79   return g_object_new (GDK_TYPE_DEVICE_CORE,
80                        "name", "Core Keyboard",
81                        "type", GDK_DEVICE_TYPE_MASTER,
82                        "input-source", GDK_SOURCE_KEYBOARD,
83                        "input-mode", GDK_MODE_SCREEN,
84                        "has-cursor", FALSE,
85                        "display", display,
86                        "device-manager", device_manager,
87                        NULL);
88 }
89
90 static void
91 gdk_device_manager_core_init (GdkDeviceManagerCore *device_manager)
92 {
93 }
94
95 static void
96 gdk_device_manager_core_finalize (GObject *object)
97 {
98   GdkDeviceManagerCore *device_manager_core;
99
100   device_manager_core = GDK_DEVICE_MANAGER_CORE (object);
101
102   g_object_unref (device_manager_core->core_pointer);
103   g_object_unref (device_manager_core->core_keyboard);
104
105   G_OBJECT_CLASS (gdk_device_manager_core_parent_class)->finalize (object);
106 }
107
108 static void
109 gdk_device_manager_core_constructed (GObject *object)
110 {
111   GdkDeviceManagerCore *device_manager;
112   GdkDisplay *display;
113
114   device_manager = GDK_DEVICE_MANAGER_CORE (object);
115   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
116   device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager), display);
117   device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager), display);
118
119   _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
120   _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
121 }
122
123 static void
124 translate_key_event (GdkDisplay           *display,
125                      GdkDeviceManagerCore *device_manager,
126                      GdkEvent             *event,
127                      XEvent               *xevent)
128 {
129   GdkKeymap *keymap = gdk_keymap_get_for_display (display);
130   GdkModifierType consumed, state;
131   gunichar c = 0;
132   gchar buf[7];
133
134   event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
135   event->key.time = xevent->xkey.time;
136   gdk_event_set_device (event, device_manager->core_keyboard);
137
138   event->key.state = (GdkModifierType) xevent->xkey.state;
139   event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
140   event->key.hardware_keycode = xevent->xkey.keycode;
141
142   event->key.keyval = GDK_KEY_VoidSymbol;
143
144   gdk_keymap_translate_keyboard_state (keymap,
145                                        event->key.hardware_keycode,
146                                        event->key.state,
147                                        event->key.group,
148                                        &event->key.keyval,
149                                        NULL, NULL, &consumed);
150
151   state = event->key.state & ~consumed;
152   _gdk_keymap_add_virtual_modifiers_compat (keymap, &state);
153   event->key.state |= state;
154
155   event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
156
157   /* Fill in event->string crudely, since various programs
158    * depend on it.
159    */
160   event->key.string = NULL;
161
162   if (event->key.keyval != GDK_KEY_VoidSymbol)
163     c = gdk_keyval_to_unicode (event->key.keyval);
164
165   if (c)
166     {
167       gsize bytes_written;
168       gint len;
169
170       /* Apply the control key - Taken from Xlib
171        */
172       if (event->key.state & GDK_CONTROL_MASK)
173         {
174           if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
175           else if (c == '2')
176             {
177               event->key.string = g_memdup ("\0\0", 2);
178               event->key.length = 1;
179               buf[0] = '\0';
180               goto out;
181             }
182           else if (c >= '3' && c <= '7') c -= ('3' - '\033');
183           else if (c == '8') c = '\177';
184           else if (c == '/') c = '_' & 0x1F;
185         }
186
187       len = g_unichar_to_utf8 (c, buf);
188       buf[len] = '\0';
189
190       event->key.string = g_locale_from_utf8 (buf, len,
191                                               NULL, &bytes_written,
192                                               NULL);
193       if (event->key.string)
194         event->key.length = bytes_written;
195     }
196   else if (event->key.keyval == GDK_KEY_Escape)
197     {
198       event->key.length = 1;
199       event->key.string = g_strdup ("\033");
200     }
201   else if (event->key.keyval == GDK_KEY_Return ||
202           event->key.keyval == GDK_KEY_KP_Enter)
203     {
204       event->key.length = 1;
205       event->key.string = g_strdup ("\r");
206     }
207
208   if (!event->key.string)
209     {
210       event->key.length = 0;
211       event->key.string = g_strdup ("");
212     }
213
214  out:
215 #ifdef G_ENABLE_DEBUG
216   if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
217     {
218       g_message ("%s:\t\twindow: %ld     key: %12s  %d",
219                  event->type == GDK_KEY_PRESS ? "key press  " : "key release",
220                  xevent->xkey.window,
221                  event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
222                  event->key.keyval);
223
224       if (event->key.length > 0)
225         g_message ("\t\tlength: %4d string: \"%s\"",
226                    event->key.length, buf);
227     }
228 #endif /* G_ENABLE_DEBUG */
229   return;
230 }
231
232 #ifdef G_ENABLE_DEBUG
233 static const char notify_modes[][19] = {
234   "NotifyNormal",
235   "NotifyGrab",
236   "NotifyUngrab",
237   "NotifyWhileGrabbed"
238 };
239
240 static const char notify_details[][23] = {
241   "NotifyAncestor",
242   "NotifyVirtual",
243   "NotifyInferior",
244   "NotifyNonlinear",
245   "NotifyNonlinearVirtual",
246   "NotifyPointer",
247   "NotifyPointerRoot",
248   "NotifyDetailNone"
249 };
250 #endif
251
252 static void
253 set_user_time (GdkWindow *window,
254                GdkEvent  *event)
255 {
256   g_return_if_fail (event != NULL);
257
258   window = gdk_window_get_toplevel (event->client.window);
259   g_return_if_fail (GDK_IS_WINDOW (window));
260
261   /* If an event doesn't have a valid timestamp, we shouldn't use it
262    * to update the latest user interaction time.
263    */
264   if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
265     gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
266                                   gdk_event_get_time (event));
267 }
268
269 static void
270 generate_focus_event (GdkDeviceManagerCore *device_manager,
271                       GdkWindow            *window,
272                       gboolean              in)
273 {
274   GdkEvent *event;
275
276   event = gdk_event_new (GDK_FOCUS_CHANGE);
277   event->focus_change.window = g_object_ref (window);
278   event->focus_change.send_event = FALSE;
279   event->focus_change.in = in;
280   gdk_event_set_device (event, device_manager->core_keyboard);
281
282   gdk_event_put (event);
283   gdk_event_free (event);
284 }
285
286 static gboolean
287 set_screen_from_root (GdkDisplay *display,
288                       GdkEvent   *event,
289                       Window      xrootwin)
290 {
291   GdkScreen *screen;
292
293   screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
294
295   if (screen)
296     {
297       gdk_event_set_screen (event, screen);
298
299       return TRUE;
300     }
301
302   return FALSE;
303 }
304
305 static GdkCrossingMode
306 translate_crossing_mode (int mode)
307 {
308   switch (mode)
309     {
310     case NotifyNormal:
311       return GDK_CROSSING_NORMAL;
312     case NotifyGrab:
313       return GDK_CROSSING_GRAB;
314     case NotifyUngrab:
315       return GDK_CROSSING_UNGRAB;
316     default:
317       g_assert_not_reached ();
318     }
319 }
320
321 static GdkNotifyType
322 translate_notify_type (int detail)
323 {
324   switch (detail)
325     {
326     case NotifyInferior:
327       return GDK_NOTIFY_INFERIOR;
328     case NotifyAncestor:
329       return GDK_NOTIFY_ANCESTOR;
330     case NotifyVirtual:
331       return GDK_NOTIFY_VIRTUAL;
332     case NotifyNonlinear:
333       return GDK_NOTIFY_NONLINEAR;
334     case NotifyNonlinearVirtual:
335       return GDK_NOTIFY_NONLINEAR_VIRTUAL;
336     default:
337       g_assert_not_reached ();
338     }
339 }
340
341 static gboolean
342 is_parent_of (GdkWindow *parent,
343               GdkWindow *child)
344 {
345   GdkWindow *w;
346
347   w = child;
348   while (w != NULL)
349     {
350       if (w == parent)
351         return TRUE;
352
353       w = gdk_window_get_parent (w);
354     }
355
356   return FALSE;
357 }
358
359 static GList *
360 gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager,
361                                       GdkDeviceType     type)
362 {
363   GdkDeviceManagerCore *device_manager_core;
364   GList *devices = NULL;
365
366   if (type == GDK_DEVICE_TYPE_MASTER)
367     {
368       device_manager_core = (GdkDeviceManagerCore *) device_manager;
369       devices = g_list_prepend (devices, device_manager_core->core_keyboard);
370       devices = g_list_prepend (devices, device_manager_core->core_pointer);
371     }
372
373   return devices;
374 }
375
376 static GdkDevice *
377 gdk_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager)
378 {
379   GdkDeviceManagerCore *device_manager_core;
380
381   device_manager_core = (GdkDeviceManagerCore *) device_manager;
382   return device_manager_core->core_pointer;
383 }
384
385 GdkDeviceManager *
386 _gdk_device_manager_new (GdkDisplay *display)
387 {
388   return g_object_new (GDK_TYPE_DEVICE_MANAGER_CORE,
389                        "display", display,
390                        NULL);
391 }