]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkdevice-win32.c
win32: no more GdkNativeWindow and related changes
[~andy/gtk] / gdk / win32 / gdkdevice-win32.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 <gdk/gdkwindow.h>
23
24 #include <windowsx.h>
25 #include <objbase.h>
26
27 #include "gdkdisplayprivate.h"
28 #include "gdkdevice-win32.h"
29 #include "gdkwin32.h"
30
31 static gboolean gdk_device_win32_get_history (GdkDevice      *device,
32                                               GdkWindow      *window,
33                                               guint32         start,
34                                               guint32         stop,
35                                               GdkTimeCoord ***events,
36                                               gint           *n_events);
37 static void gdk_device_win32_get_state (GdkDevice       *device,
38                                         GdkWindow       *window,
39                                         gdouble         *axes,
40                                         GdkModifierType *mask);
41 static void gdk_device_win32_set_window_cursor (GdkDevice *device,
42                                                 GdkWindow *window,
43                                                 GdkCursor *cursor);
44 static void gdk_device_win32_warp (GdkDevice *device,
45                                    GdkScreen *screen,
46                                    gint       x,
47                                    gint       y);
48 static gboolean gdk_device_win32_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_device_win32_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_device_win32_ungrab (GdkDevice     *device,
65                                               guint32        time_);
66 static GdkWindow * gdk_device_win32_window_at_position (GdkDevice       *device,
67                                                         gint            *win_x,
68                                                         gint            *win_y,
69                                                         GdkModifierType *mask,
70                                                         gboolean         get_toplevel);
71 static void      gdk_device_win32_select_window_events (GdkDevice       *device,
72                                                         GdkWindow       *window,
73                                                         GdkEventMask     event_mask);
74
75
76 G_DEFINE_TYPE (GdkDeviceWin32, gdk_device_win32, GDK_TYPE_DEVICE)
77
78 static void
79 gdk_device_win32_class_init (GdkDeviceWin32Class *klass)
80 {
81   GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
82
83   device_class->get_history = gdk_device_win32_get_history;
84   device_class->get_state = gdk_device_win32_get_state;
85   device_class->set_window_cursor = gdk_device_win32_set_window_cursor;
86   device_class->warp = gdk_device_win32_warp;
87   device_class->query_state = gdk_device_win32_query_state;
88   device_class->grab = gdk_device_win32_grab;
89   device_class->ungrab = gdk_device_win32_ungrab;
90   device_class->window_at_position = gdk_device_win32_window_at_position;
91   device_class->select_window_events = gdk_device_win32_select_window_events;
92 }
93
94 static void
95 gdk_device_win32_init (GdkDeviceWin32 *device_win32)
96 {
97   GdkDevice *device;
98
99   device = GDK_DEVICE (device_win32);
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_device_win32_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_device_win32_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 gdk_device_win32_set_window_cursor (GdkDevice *device,
135                                     GdkWindow *window,
136                                     GdkCursor *cursor)
137 {
138   GdkWin32Cursor *cursor_private;
139   GdkWindow *parent_window;
140   GdkWindowImplWin32 *impl;
141   HCURSOR hcursor;
142   HCURSOR hprevcursor;
143
144   impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
145   cursor_private = (GdkWin32Cursor*) cursor;
146
147   hprevcursor = impl->hcursor;
148
149   if (!cursor)
150     hcursor = NULL;
151   else
152     hcursor = cursor_private->hcursor;
153
154   if (hcursor != NULL)
155     {
156       /* If the pointer is over our window, set new cursor */
157       GdkWindow *curr_window = gdk_window_get_pointer (window, NULL, NULL, NULL);
158
159       if (curr_window == window ||
160           (curr_window && window == gdk_window_get_toplevel (curr_window)))
161         SetCursor (hcursor);
162       else
163         {
164           /* Climb up the tree and find whether our window is the
165            * first ancestor that has cursor defined, and if so, set
166            * new cursor.
167            */
168           while (curr_window && curr_window->impl &&
169                  !GDK_WINDOW_IMPL_WIN32 (curr_window->impl)->hcursor)
170             {
171               curr_window = curr_window->parent;
172               if (curr_window == GDK_WINDOW (window))
173                 {
174                   SetCursor (hcursor);
175                   break;
176                 }
177             }
178         }
179     }
180
181   /* Unset the previous cursor: Need to make sure it's no longer in
182    * use before we destroy it, in case we're not over our window but
183    * the cursor is still set to our old one.
184    */
185   if (hprevcursor != NULL &&
186       GetCursor () == hprevcursor)
187     {
188       /* Look for a suitable cursor to use instead */
189       hcursor = NULL;
190       parent_window = GDK_WINDOW (window)->parent;
191
192       while (hcursor == NULL)
193         {
194           if (parent_window)
195             {
196               impl = GDK_WINDOW_IMPL_WIN32 (parent_window->impl);
197               hcursor = impl->hcursor;
198               parent_window = parent_window->parent;
199             }
200           else
201             hcursor = LoadCursor (NULL, IDC_ARROW);
202         }
203
204       SetCursor (hcursor);
205     }
206 }
207
208 static void
209 gdk_device_win32_warp (GdkDevice *device,
210                        GdkScreen *screen,
211                        gint       x,
212                        gint       y)
213 {
214   SetCursorPos (x - _gdk_offset_x, y - _gdk_offset_y);
215 }
216
217 static GdkModifierType
218 get_current_mask (void)
219 {
220   GdkModifierType mask;
221   BYTE kbd[256];
222
223   GetKeyboardState (kbd);
224   mask = 0;
225   if (kbd[VK_SHIFT] & 0x80)
226     mask |= GDK_SHIFT_MASK;
227   if (kbd[VK_CAPITAL] & 0x80)
228     mask |= GDK_LOCK_MASK;
229   if (kbd[VK_CONTROL] & 0x80)
230     mask |= GDK_CONTROL_MASK;
231   if (kbd[VK_MENU] & 0x80)
232     mask |= GDK_MOD1_MASK;
233   if (kbd[VK_LBUTTON] & 0x80)
234     mask |= GDK_BUTTON1_MASK;
235   if (kbd[VK_MBUTTON] & 0x80)
236     mask |= GDK_BUTTON2_MASK;
237   if (kbd[VK_RBUTTON] & 0x80)
238     mask |= GDK_BUTTON3_MASK;
239
240   return mask;
241 }
242
243 static gboolean
244 gdk_device_win32_query_state (GdkDevice        *device,
245                               GdkWindow        *window,
246                               GdkWindow       **root_window,
247                               GdkWindow       **child_window,
248                               gint             *root_x,
249                               gint             *root_y,
250                               gint             *win_x,
251                               gint             *win_y,
252                               GdkModifierType  *mask)
253 {
254   gboolean return_val;
255   POINT point;
256   HWND hwnd, hwndc;
257
258   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
259   
260   return_val = TRUE;
261
262   hwnd = GDK_WINDOW_HWND (window);
263   GetCursorPos (&point);
264
265   if (root_x)
266     *root_x = point.x;
267
268   if (root_y)
269     *root_y = point.y;
270
271   ScreenToClient (hwnd, &point);
272
273   if (win_x)
274     *win_x = point.x;
275
276   if (win_y)
277     *win_y = point.y;
278
279   if (window == _gdk_root)
280     {
281       if (win_x)
282         *win_x += _gdk_offset_x;
283
284       if (win_y)
285         *win_y += _gdk_offset_y;
286     }
287
288   if (child_window)
289     {
290       hwndc = ChildWindowFromPoint (hwnd, point);
291
292       if (hwndc && hwndc != hwnd)
293         *child_window = gdk_win32_handle_table_lookup (hwndc);
294       else
295         *child_window = NULL; /* Direct child unknown to gdk */
296     }
297
298   if (root_window)
299     {
300       GdkScreen *screen;
301
302       screen = gdk_window_get_screen (window);
303       *root_window = gdk_screen_get_root_window (screen);
304     }
305
306   if (mask)
307     *mask = get_current_mask ();
308
309   return TRUE;
310 }
311
312 static GdkGrabStatus
313 gdk_device_win32_grab (GdkDevice    *device,
314                        GdkWindow    *window,
315                        gboolean      owner_events,
316                        GdkEventMask  event_mask,
317                        GdkWindow    *confine_to,
318                        GdkCursor    *cursor,
319                        guint32       time_)
320 {
321   if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
322     SetCapture (GDK_WINDOW_HWND (window));
323
324   return GDK_GRAB_SUCCESS;
325 }
326
327 static void
328 gdk_device_win32_ungrab (GdkDevice *device,
329                          guint32    time_)
330 {
331   GdkDeviceGrabInfo *info;
332   GdkDisplay *display;
333
334   display = gdk_device_get_display (device);
335   info = _gdk_display_get_last_device_grab (display, device);
336
337   if (info)
338     info->serial_end = 0;
339
340   if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
341     ReleaseCapture ();
342
343   _gdk_display_device_grab_update (display, device, NULL, 0);
344 }
345
346 static GdkWindow *
347 gdk_device_win32_window_at_position (GdkDevice       *device,
348                                      gint            *win_x,
349                                      gint            *win_y,
350                                      GdkModifierType *mask,
351                                      gboolean         get_toplevel)
352 {
353   GdkWindow *window;
354   POINT point, pointc;
355   HWND hwnd, hwndc;
356   RECT rect;
357
358   GetCursorPos (&pointc);
359   point = pointc;
360   hwnd = WindowFromPoint (point);
361
362   if (hwnd == NULL)
363     {
364       window = _gdk_root;
365       *win_x = pointc.x + _gdk_offset_x;
366       *win_y = pointc.y + _gdk_offset_y;
367       return window;
368     }
369
370   ScreenToClient (hwnd, &point);
371
372   do
373     {
374       if (get_toplevel &&
375           (window = gdk_win32_handle_table_lookup (hwnd)) != NULL &&
376           GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
377         break;
378
379       hwndc = ChildWindowFromPoint (hwnd, point);
380       ClientToScreen (hwnd, &point);
381       ScreenToClient (hwndc, &point);
382     }
383   while (hwndc != hwnd && (hwnd = hwndc, 1));
384
385   window = gdk_win32_handle_table_lookup (hwnd);
386
387   if (window && (win_x || win_y))
388     {
389       GetClientRect (hwnd, &rect);
390       *win_x = point.x - rect.left;
391       *win_y = point.y - rect.top;
392     }
393
394   return window;
395 }
396
397 static void
398 gdk_device_win32_select_window_events (GdkDevice    *device,
399                                        GdkWindow    *window,
400                                        GdkEventMask  event_mask)
401 {
402 }