]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkdevice-core-quartz.c
9aaba34395b81a055fed8d75006c4237cd4465ff
[~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/gdkdisplayprivate.h>
24
25 #import "GdkQuartzView.h"
26 #include "gdkwindow-quartz.h"
27 #include "gdkcursor-quartz.h"
28 #include "gdkprivate-quartz.h"
29 #include "gdkdevice-core-quartz.h"
30
31 static gboolean gdk_quartz_device_core_get_history (GdkDevice      *device,
32                                                     GdkWindow      *window,
33                                                     guint32         start,
34                                                     guint32         stop,
35                                                     GdkTimeCoord ***events,
36                                                     gint           *n_events);
37 static void gdk_quartz_device_core_get_state (GdkDevice       *device,
38                                               GdkWindow       *window,
39                                               gdouble         *axes,
40                                               GdkModifierType *mask);
41 static void gdk_quartz_device_core_set_window_cursor (GdkDevice *device,
42                                                       GdkWindow *window,
43                                                       GdkCursor *cursor);
44 static void gdk_quartz_device_core_warp (GdkDevice *device,
45                                          GdkScreen *screen,
46                                          gint       x,
47                                          gint       y);
48 static gboolean gdk_quartz_device_core_query_state (GdkDevice        *device,
49                                                     GdkWindow        *window,
50                                                     GdkWindow       **root_window,
51                                                     GdkWindow       **child_window,
52                                                     gint             *root_x,
53                                                     gint             *root_y,
54                                                     gint             *win_x,
55                                                     gint             *win_y,
56                                                     GdkModifierType  *mask);
57 static GdkGrabStatus gdk_quartz_device_core_grab   (GdkDevice     *device,
58                                                     GdkWindow     *window,
59                                                     gboolean       owner_events,
60                                                     GdkEventMask   event_mask,
61                                                     GdkWindow     *confine_to,
62                                                     GdkCursor     *cursor,
63                                                     guint32        time_);
64 static void          gdk_quartz_device_core_ungrab (GdkDevice     *device,
65                                                     guint32        time_);
66 static GdkWindow * gdk_quartz_device_core_window_at_position (GdkDevice       *device,
67                                                               gint            *win_x,
68                                                               gint            *win_y,
69                                                               GdkModifierType *mask,
70                                                               gboolean         get_toplevel);
71 static void      gdk_quartz_device_core_select_window_events (GdkDevice       *device,
72                                                               GdkWindow       *window,
73                                                               GdkEventMask     event_mask);
74
75
76 G_DEFINE_TYPE (GdkQuartzDeviceCore, gdk_quartz_device_core, GDK_TYPE_DEVICE)
77
78 static void
79 gdk_quartz_device_core_class_init (GdkQuartzDeviceCoreClass *klass)
80 {
81   GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
82
83   device_class->get_history = gdk_quartz_device_core_get_history;
84   device_class->get_state = gdk_quartz_device_core_get_state;
85   device_class->set_window_cursor = gdk_quartz_device_core_set_window_cursor;
86   device_class->warp = gdk_quartz_device_core_warp;
87   device_class->query_state = gdk_quartz_device_core_query_state;
88   device_class->grab = gdk_quartz_device_core_grab;
89   device_class->ungrab = gdk_quartz_device_core_ungrab;
90   device_class->window_at_position = gdk_quartz_device_core_window_at_position;
91   device_class->select_window_events = gdk_quartz_device_core_select_window_events;
92 }
93
94 static void
95 gdk_quartz_device_core_init (GdkQuartzDeviceCore *quartz_device_core)
96 {
97   GdkDevice *device;
98
99   device = GDK_DEVICE (quartz_device_core);
100
101   _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_X, 0, 0, 1);
102   _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_Y, 0, 0, 1);
103 }
104
105 static gboolean
106 gdk_quartz_device_core_get_history (GdkDevice      *device,
107                                     GdkWindow      *window,
108                                     guint32         start,
109                                     guint32         stop,
110                                     GdkTimeCoord ***events,
111                                     gint           *n_events)
112 {
113   return FALSE;
114 }
115
116 static void
117 gdk_quartz_device_core_get_state (GdkDevice       *device,
118                                   GdkWindow       *window,
119                                   gdouble         *axes,
120                                   GdkModifierType *mask)
121 {
122   gint x_int, y_int;
123
124   gdk_window_get_pointer (window, &x_int, &y_int, mask);
125
126   if (axes)
127     {
128       axes[0] = x_int;
129       axes[1] = y_int;
130     }
131 }
132
133 static void
134 translate_coords_to_child_coords (GdkWindow *parent,
135                                   GdkWindow *child,
136                                   gint      *x,
137                                   gint      *y)
138 {
139   GdkWindow *current = child;
140
141   if (child == parent)
142     return;
143
144   while (current != parent)
145     {
146       gint tmp_x, tmp_y;
147
148       gdk_window_get_origin (current, &tmp_x, &tmp_y);
149
150       *x -= tmp_x;
151       *y -= tmp_y;
152
153       current = gdk_window_get_effective_parent (current);
154     }
155 }
156
157 static void
158 gdk_quartz_device_core_set_window_cursor (GdkDevice *device,
159                                           GdkWindow *window,
160                                           GdkCursor *cursor)
161 {
162   GdkQuartzCursor *cursor_private;
163   NSCursor *nscursor;
164
165   cursor_private = (GdkQuartzCursor *) cursor;
166
167   if (GDK_WINDOW_DESTROYED (window))
168     return;
169
170   if (!cursor)
171     nscursor = [NSCursor arrowCursor];
172   else
173     nscursor = cursor_private->nscursor;
174
175   [nscursor set];
176 }
177
178 static void
179 gdk_quartz_device_core_warp (GdkDevice *device,
180                              GdkScreen *screen,
181                              gint       x,
182                              gint       y)
183 {
184   CGDisplayMoveCursorToPoint (CGMainDisplayID (), CGPointMake (x, y));
185 }
186
187 static GdkWindow *
188 gdk_quartz_device_core_query_state_helper (GdkWindow       *window,
189                                            GdkDevice       *device,
190                                            gint            *x,
191                                            gint            *y,
192                                            GdkModifierType *mask)
193 {
194   GdkWindow *toplevel;
195   NSPoint point;
196   gint x_tmp, y_tmp;
197   GdkWindow *found_window;
198
199   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
200
201   if (GDK_WINDOW_DESTROYED (window))
202     {
203       *x = 0;
204       *y = 0;
205       *mask = 0;
206       return NULL;
207     }
208
209   toplevel = gdk_window_get_effective_toplevel (window);
210
211   *mask = _gdk_quartz_events_get_current_event_mask ();
212
213   /* Get the y coordinate, needs to be flipped. */
214   if (window == _gdk_root)
215     {
216       point = [NSEvent mouseLocation];
217       _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
218     }
219   else
220     {
221       GdkWindowImplQuartz *impl;
222       NSWindow *nswindow;
223
224       impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
225       nswindow = impl->toplevel;
226
227       point = [nswindow mouseLocationOutsideOfEventStream];
228
229       x_tmp = point.x;
230       y_tmp = toplevel->height - point.y;
231
232       window = toplevel;
233     }
234
235   found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp,
236                                                 FALSE);
237
238   if (found_window == _gdk_root)
239     found_window = NULL;
240   else if (found_window)
241     translate_coords_to_child_coords (window, found_window,
242                                       &x_tmp, &y_tmp);
243
244   if (x)
245     *x = x_tmp;
246
247   if (y)
248     *y = y_tmp;
249
250   return found_window;
251 }
252
253 static gboolean
254 gdk_quartz_device_core_query_state (GdkDevice        *device,
255                                     GdkWindow        *window,
256                                     GdkWindow       **root_window,
257                                     GdkWindow       **child_window,
258                                     gint             *root_x,
259                                     gint             *root_y,
260                                     gint             *win_x,
261                                     gint             *win_y,
262                                     GdkModifierType  *mask)
263 {
264   GdkDisplay *display;
265   GdkWindow *found_window;
266   NSPoint point;
267   gint x_tmp, y_tmp;
268
269   found_window = gdk_quartz_device_core_query_state_helper (window, device,
270                                                             win_x, win_y,
271                                                             mask);
272   if (!found_window)
273     return FALSE;
274
275   display = gdk_window_get_display (window);
276
277   if (root_window)
278     *root_window = _gdk_root;
279
280   if (child_window)
281     *child_window = found_window;
282
283   point = [NSEvent mouseLocation];
284   _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
285
286   if (root_x)
287     *root_x = x_tmp;
288
289   if (root_y)
290     *root_y = y_tmp;
291
292   return TRUE;
293 }
294
295 static GdkGrabStatus
296 gdk_quartz_device_core_grab (GdkDevice    *device,
297                              GdkWindow    *window,
298                              gboolean      owner_events,
299                              GdkEventMask  event_mask,
300                              GdkWindow    *confine_to,
301                              GdkCursor    *cursor,
302                              guint32       time_)
303 {
304   /* Should remain empty */
305   return GDK_GRAB_SUCCESS;
306 }
307
308 static void
309 gdk_quartz_device_core_ungrab (GdkDevice *device,
310                                guint32    time_)
311 {
312   GdkDeviceGrabInfo *grab;
313
314   grab = _gdk_display_get_last_device_grab (_gdk_display, device);
315   if (grab)
316     grab->serial_end = 0;
317
318   _gdk_display_device_grab_update (_gdk_display, device, NULL, 0);
319 }
320
321 static GdkWindow *
322 gdk_quartz_device_core_window_at_position (GdkDevice       *device,
323                                            gint            *win_x,
324                                            gint            *win_y,
325                                            GdkModifierType *mask,
326                                            gboolean         get_toplevel)
327 {
328   GdkDisplay *display;
329   GdkScreen *screen;
330   GdkWindow *found_window;
331   NSPoint point;
332   gint x_tmp, y_tmp;
333
334   display = gdk_device_get_display (device);
335   screen = gdk_display_get_default_screen (display);
336
337   /* Get mouse coordinates, find window under the mouse pointer */
338   point = [NSEvent mouseLocation];
339   _gdk_quartz_window_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
340
341   found_window = _gdk_quartz_window_find_child (_gdk_root, x_tmp, y_tmp,
342                                                 get_toplevel);
343
344   if (found_window)
345     translate_coords_to_child_coords (_gdk_root, found_window,
346                                       &x_tmp, &y_tmp);
347
348   if (win_x)
349     *win_x = found_window ? x_tmp : -1;
350
351   if (win_y)
352     *win_y = found_window ? y_tmp : -1;
353
354   if (mask)
355     *mask = _gdk_quartz_events_get_current_event_mask ();
356
357   return found_window;
358 }
359
360 static void
361 gdk_quartz_device_core_select_window_events (GdkDevice    *device,
362                                              GdkWindow    *window,
363                                              GdkEventMask  event_mask)
364 {
365   /* The mask is set in the common code. */
366 }