]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkdevice-core-quartz.c
Merge branch 'bgo593793-filechooser-recent-folders-master'
[~andy/gtk] / gdk / quartz / gdkdevice-core-quartz.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
3  * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include <gdk/gdkdeviceprivate.h>
24 #include <gdk/gdkdisplayprivate.h>
25
26 #import "GdkQuartzView.h"
27 #include "gdkquartzwindow.h"
28 #include "gdkquartzcursor.h"
29 #include "gdkprivate-quartz.h"
30 #include "gdkquartzdevice-core.h"
31
32 struct _GdkQuartzDeviceCore
33 {
34   GdkDevice parent_instance;
35 };
36
37 struct _GdkQuartzDeviceCoreClass
38 {
39   GdkDeviceClass parent_class;
40 };
41
42 static gboolean gdk_quartz_device_core_get_history (GdkDevice      *device,
43                                                     GdkWindow      *window,
44                                                     guint32         start,
45                                                     guint32         stop,
46                                                     GdkTimeCoord ***events,
47                                                     gint           *n_events);
48 static void gdk_quartz_device_core_get_state (GdkDevice       *device,
49                                               GdkWindow       *window,
50                                               gdouble         *axes,
51                                               GdkModifierType *mask);
52 static void gdk_quartz_device_core_set_window_cursor (GdkDevice *device,
53                                                       GdkWindow *window,
54                                                       GdkCursor *cursor);
55 static void gdk_quartz_device_core_warp (GdkDevice *device,
56                                          GdkScreen *screen,
57                                          gint       x,
58                                          gint       y);
59 static gboolean gdk_quartz_device_core_query_state (GdkDevice        *device,
60                                                     GdkWindow        *window,
61                                                     GdkWindow       **root_window,
62                                                     GdkWindow       **child_window,
63                                                     gint             *root_x,
64                                                     gint             *root_y,
65                                                     gint             *win_x,
66                                                     gint             *win_y,
67                                                     GdkModifierType  *mask);
68 static GdkGrabStatus gdk_quartz_device_core_grab   (GdkDevice     *device,
69                                                     GdkWindow     *window,
70                                                     gboolean       owner_events,
71                                                     GdkEventMask   event_mask,
72                                                     GdkWindow     *confine_to,
73                                                     GdkCursor     *cursor,
74                                                     guint32        time_);
75 static void          gdk_quartz_device_core_ungrab (GdkDevice     *device,
76                                                     guint32        time_);
77 static GdkWindow * gdk_quartz_device_core_window_at_position (GdkDevice       *device,
78                                                               gint            *win_x,
79                                                               gint            *win_y,
80                                                               GdkModifierType *mask,
81                                                               gboolean         get_toplevel);
82 static void      gdk_quartz_device_core_select_window_events (GdkDevice       *device,
83                                                               GdkWindow       *window,
84                                                               GdkEventMask     event_mask);
85
86
87 G_DEFINE_TYPE (GdkQuartzDeviceCore, gdk_quartz_device_core, GDK_TYPE_DEVICE)
88
89 static void
90 gdk_quartz_device_core_class_init (GdkQuartzDeviceCoreClass *klass)
91 {
92   GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
93
94   device_class->get_history = gdk_quartz_device_core_get_history;
95   device_class->get_state = gdk_quartz_device_core_get_state;
96   device_class->set_window_cursor = gdk_quartz_device_core_set_window_cursor;
97   device_class->warp = gdk_quartz_device_core_warp;
98   device_class->query_state = gdk_quartz_device_core_query_state;
99   device_class->grab = gdk_quartz_device_core_grab;
100   device_class->ungrab = gdk_quartz_device_core_ungrab;
101   device_class->window_at_position = gdk_quartz_device_core_window_at_position;
102   device_class->select_window_events = gdk_quartz_device_core_select_window_events;
103 }
104
105 static void
106 gdk_quartz_device_core_init (GdkQuartzDeviceCore *quartz_device_core)
107 {
108   GdkDevice *device;
109
110   device = GDK_DEVICE (quartz_device_core);
111
112   _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_X, 0, 0, 1);
113   _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_Y, 0, 0, 1);
114 }
115
116 static gboolean
117 gdk_quartz_device_core_get_history (GdkDevice      *device,
118                                     GdkWindow      *window,
119                                     guint32         start,
120                                     guint32         stop,
121                                     GdkTimeCoord ***events,
122                                     gint           *n_events)
123 {
124   return FALSE;
125 }
126
127 static void
128 gdk_quartz_device_core_get_state (GdkDevice       *device,
129                                   GdkWindow       *window,
130                                   gdouble         *axes,
131                                   GdkModifierType *mask)
132 {
133   gint x_int, y_int;
134
135   gdk_window_get_pointer (window, &x_int, &y_int, mask);
136
137   if (axes)
138     {
139       axes[0] = x_int;
140       axes[1] = y_int;
141     }
142 }
143
144 static void
145 translate_coords_to_child_coords (GdkWindow *parent,
146                                   GdkWindow *child,
147                                   gint      *x,
148                                   gint      *y)
149 {
150   GdkWindow *current = child;
151
152   if (child == parent)
153     return;
154
155   while (current != parent)
156     {
157       gint tmp_x, tmp_y;
158
159       gdk_window_get_origin (current, &tmp_x, &tmp_y);
160
161       *x -= tmp_x;
162       *y -= tmp_y;
163
164       current = gdk_window_get_effective_parent (current);
165     }
166 }
167
168 static void
169 gdk_quartz_device_core_set_window_cursor (GdkDevice *device,
170                                           GdkWindow *window,
171                                           GdkCursor *cursor)
172 {
173   NSCursor *nscursor;
174
175   if (GDK_WINDOW_DESTROYED (window))
176     return;
177
178   nscursor = _gdk_quartz_cursor_get_ns_cursor (cursor);
179
180   [nscursor set];
181 }
182
183 static void
184 gdk_quartz_device_core_warp (GdkDevice *device,
185                              GdkScreen *screen,
186                              gint       x,
187                              gint       y)
188 {
189   CGDisplayMoveCursorToPoint (CGMainDisplayID (), CGPointMake (x, y));
190 }
191
192 static GdkWindow *
193 gdk_quartz_device_core_query_state_helper (GdkWindow       *window,
194                                            GdkDevice       *device,
195                                            gint            *x,
196                                            gint            *y,
197                                            GdkModifierType *mask)
198 {
199   GdkWindow *toplevel;
200   NSPoint point;
201   gint x_tmp, y_tmp;
202   GdkWindow *found_window;
203
204   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
205
206   if (GDK_WINDOW_DESTROYED (window))
207     {
208       *x = 0;
209       *y = 0;
210       *mask = 0;
211       return NULL;
212     }
213
214   toplevel = gdk_window_get_effective_toplevel (window);
215
216   if (mask)
217     *mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
218         _gdk_quartz_events_get_current_mouse_modifiers ();
219
220   /* Get the y coordinate, needs to be flipped. */
221   if (window == _gdk_root)
222     {
223       point = [NSEvent mouseLocation];
224       _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
225     }
226   else
227     {
228       GdkWindowImplQuartz *impl;
229       NSWindow *nswindow;
230
231       impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
232       nswindow = impl->toplevel;
233
234       point = [nswindow mouseLocationOutsideOfEventStream];
235
236       x_tmp = point.x;
237       y_tmp = toplevel->height - point.y;
238
239       window = toplevel;
240     }
241
242   found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp,
243                                                 FALSE);
244
245   if (found_window == _gdk_root)
246     found_window = NULL;
247   else if (found_window)
248     translate_coords_to_child_coords (window, found_window,
249                                       &x_tmp, &y_tmp);
250
251   if (x)
252     *x = x_tmp;
253
254   if (y)
255     *y = y_tmp;
256
257   return found_window;
258 }
259
260 static gboolean
261 gdk_quartz_device_core_query_state (GdkDevice        *device,
262                                     GdkWindow        *window,
263                                     GdkWindow       **root_window,
264                                     GdkWindow       **child_window,
265                                     gint             *root_x,
266                                     gint             *root_y,
267                                     gint             *win_x,
268                                     gint             *win_y,
269                                     GdkModifierType  *mask)
270 {
271   GdkDisplay *display;
272   GdkWindow *found_window;
273   NSPoint point;
274   gint x_tmp, y_tmp;
275
276   found_window = gdk_quartz_device_core_query_state_helper (window, device,
277                                                             win_x, win_y,
278                                                             mask);
279   if (!found_window)
280     return FALSE;
281
282   display = gdk_window_get_display (window);
283
284   if (root_window)
285     *root_window = _gdk_root;
286
287   if (child_window)
288     *child_window = found_window;
289
290   point = [NSEvent mouseLocation];
291   _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
292
293   if (root_x)
294     *root_x = x_tmp;
295
296   if (root_y)
297     *root_y = y_tmp;
298
299   return TRUE;
300 }
301
302 static GdkGrabStatus
303 gdk_quartz_device_core_grab (GdkDevice    *device,
304                              GdkWindow    *window,
305                              gboolean      owner_events,
306                              GdkEventMask  event_mask,
307                              GdkWindow    *confine_to,
308                              GdkCursor    *cursor,
309                              guint32       time_)
310 {
311   /* Should remain empty */
312   return GDK_GRAB_SUCCESS;
313 }
314
315 static void
316 gdk_quartz_device_core_ungrab (GdkDevice *device,
317                                guint32    time_)
318 {
319   GdkDeviceGrabInfo *grab;
320
321   grab = _gdk_display_get_last_device_grab (_gdk_display, device);
322   if (grab)
323     grab->serial_end = 0;
324
325   _gdk_display_device_grab_update (_gdk_display, device, NULL, 0);
326 }
327
328 static GdkWindow *
329 gdk_quartz_device_core_window_at_position (GdkDevice       *device,
330                                            gint            *win_x,
331                                            gint            *win_y,
332                                            GdkModifierType *mask,
333                                            gboolean         get_toplevel)
334 {
335   GdkDisplay *display;
336   GdkScreen *screen;
337   GdkWindow *found_window;
338   NSPoint point;
339   gint x_tmp, y_tmp;
340
341   display = gdk_device_get_display (device);
342   screen = gdk_display_get_default_screen (display);
343
344   /* Get mouse coordinates, find window under the mouse pointer */
345   point = [NSEvent mouseLocation];
346   _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
347
348   found_window = _gdk_quartz_window_find_child (_gdk_root, x_tmp, y_tmp,
349                                                 get_toplevel);
350
351   if (found_window)
352     translate_coords_to_child_coords (_gdk_root, found_window,
353                                       &x_tmp, &y_tmp);
354
355   if (win_x)
356     *win_x = found_window ? x_tmp : -1;
357
358   if (win_y)
359     *win_y = found_window ? y_tmp : -1;
360
361   if (mask)
362     *mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
363         _gdk_quartz_events_get_current_mouse_modifiers ();
364
365   return found_window;
366 }
367
368 static void
369 gdk_quartz_device_core_select_window_events (GdkDevice    *device,
370                                              GdkWindow    *window,
371                                              GdkEventMask  event_mask)
372 {
373   /* The mask is set in the common code. */
374 }