1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998-2004 Tor Lillqvist
4 * Copyright (C) 2001-2011 Hans Breuer
5 * Copyright (C) 2007-2009 Cody Russell
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 of the License, or (at your option) any later version.
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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
25 * file for a list of people on the GTK+ Team. See the ChangeLog
26 * files for a list of changes. These files are distributed with
27 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
34 #include "gdkwindowimpl.h"
35 #include "gdkprivate-win32.h"
36 #include "gdkdeviceprivate.h"
37 #include "gdkdevicemanager-win32.h"
38 #include "gdkenumtypes.h"
40 #include "gdkdisplayprivate.h"
41 #include "gdkvisualprivate.h"
42 #include "gdkwin32window.h"
44 #include <cairo-win32.h>
46 static void gdk_window_impl_win32_init (GdkWindowImplWin32 *window);
47 static void gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass);
48 static void gdk_window_impl_win32_finalize (GObject *object);
50 static gpointer parent_class = NULL;
51 static GSList *modal_window_stack = NULL;
53 static const cairo_user_data_key_t gdk_win32_cairo_key;
54 typedef struct _FullscreenInfo FullscreenInfo;
56 struct _FullscreenInfo
63 static void update_style_bits (GdkWindow *window);
64 static gboolean _gdk_window_get_functions (GdkWindow *window,
65 GdkWMFunction *functions);
66 static HDC _gdk_win32_impl_acquire_dc (GdkWindowImplWin32 *impl);
67 static void _gdk_win32_impl_release_dc (GdkWindowImplWin32 *impl);
69 #define WINDOW_IS_TOPLEVEL(window) \
70 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
71 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
72 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
75 GDK_WINDOW_SCREEN (GObject *win)
80 struct _GdkWin32Window {
84 struct _GdkWin32WindowClass {
85 GdkWindowClass parent_class;
88 G_DEFINE_TYPE (GdkWin32Window, gdk_win32_window, GDK_TYPE_WINDOW)
91 gdk_win32_window_class_init (GdkWin32WindowClass *window_class)
96 gdk_win32_window_init (GdkWin32Window *window)
101 G_DEFINE_TYPE (GdkWindowImplWin32, gdk_window_impl_win32, GDK_TYPE_WINDOW_IMPL)
104 _gdk_window_impl_win32_get_type (void)
106 static GType object_type = 0;
110 const GTypeInfo object_info =
112 sizeof (GdkWindowImplWin32Class),
113 (GBaseInitFunc) NULL,
114 (GBaseFinalizeFunc) NULL,
115 (GClassInitFunc) gdk_window_impl_win32_class_init,
116 NULL, /* class_finalize */
117 NULL, /* class_data */
118 sizeof (GdkWindowImplWin32),
120 (GInstanceInitFunc) gdk_window_impl_win32_init,
123 object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL,
124 "GdkWindowImplWin32",
132 gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
134 impl->toplevel_window_type = -1;
135 impl->hcursor = NULL;
136 impl->hicon_big = NULL;
137 impl->hicon_small = NULL;
138 impl->hint_flags = 0;
139 impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
140 impl->extension_events_selected = FALSE;
141 impl->transient_owner = NULL;
142 impl->transient_children = NULL;
143 impl->num_transients = 0;
144 impl->changing_state = FALSE;
148 gdk_window_impl_win32_finalize (GObject *object)
151 GdkWindowImplWin32 *window_impl;
153 g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (object));
155 window_impl = GDK_WINDOW_IMPL_WIN32 (object);
157 wrapper = window_impl->wrapper;
159 if (!GDK_WINDOW_DESTROYED (wrapper))
161 gdk_win32_handle_table_remove (window_impl->handle);
164 if (window_impl->hcursor != NULL)
166 if (GetCursor () == window_impl->hcursor)
169 GDI_CALL (DestroyCursor, (window_impl->hcursor));
170 window_impl->hcursor = NULL;
173 if (window_impl->hicon_big != NULL)
175 GDI_CALL (DestroyIcon, (window_impl->hicon_big));
176 window_impl->hicon_big = NULL;
179 if (window_impl->hicon_small != NULL)
181 GDI_CALL (DestroyIcon, (window_impl->hicon_small));
182 window_impl->hicon_small = NULL;
185 G_OBJECT_CLASS (parent_class)->finalize (object);
189 _gdk_win32_adjust_client_rect (GdkWindow *window,
194 style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
195 exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
196 API_CALL (AdjustWindowRectEx, (rect, style, FALSE, exstyle));
200 _gdk_root_window_size_init (void)
206 window = GDK_WINDOW (_gdk_root);
207 rect = _gdk_monitors[0].rect;
208 for (i = 1; i < _gdk_num_monitors; i++)
209 gdk_rectangle_union (&rect, &_gdk_monitors[i].rect, &rect);
211 window->width = rect.width;
212 window->height = rect.height;
216 _gdk_windowing_window_init (GdkScreen *screen)
219 GdkWindowImplWin32 *impl_win32;
221 g_assert (_gdk_root == NULL);
223 _gdk_root = _gdk_display_create_window (_gdk_display);
225 window = (GdkWindow *)_gdk_root;
226 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
227 impl_win32 = GDK_WINDOW_IMPL_WIN32 (window->impl);
228 impl_win32->wrapper = window;
230 window->impl_window = window;
231 window->visual = gdk_screen_get_system_visual (screen);
233 window->window_type = GDK_WINDOW_ROOT;
234 window->depth = gdk_visual_get_system ()->depth;
236 _gdk_root_window_size_init ();
242 /* width and height already initialised in _gdk_root_window_size_init() */
243 window->viewable = TRUE;
245 gdk_win32_handle_table_insert ((HANDLE *) &impl_win32->handle, _gdk_root);
247 GDK_NOTE (MISC, g_print ("_gdk_root=%p\n", GDK_WINDOW_HWND (_gdk_root)));
251 get_default_title (void)
254 title = g_get_application_name ();
256 title = g_get_prgname ();
262 * is a wrapper function for RegisterWindowClassEx.
263 * It creates at least one unique class for every
264 * GdkWindowType. If support for single window-specific icons
265 * is ever needed (e.g Dialog specific), every such window should
269 RegisterGdkClass (GdkWindowType wtype, GdkWindowTypeHint wtype_hint)
271 static ATOM klassTOPLEVEL = 0;
272 static ATOM klassCHILD = 0;
273 static ATOM klassTEMP = 0;
274 static ATOM klassTEMPSHADOW = 0;
275 static HICON hAppIcon = NULL;
276 static HICON hAppIconSm = NULL;
277 static WNDCLASSEXW wcl;
280 wcl.cbSize = sizeof (WNDCLASSEX);
281 wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
282 * on WM_SIZE and WM_MOVE. Flicker, Performance!
284 wcl.lpfnWndProc = _gdk_win32_window_procedure;
287 wcl.hInstance = _gdk_app_hmodule;
291 /* initialize once! */
292 if (0 == hAppIcon && 0 == hAppIconSm)
294 gchar sLoc [MAX_PATH+1];
296 if (0 != GetModuleFileName (_gdk_app_hmodule, sLoc, MAX_PATH))
298 ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
300 if (0 == hAppIcon && 0 == hAppIconSm)
302 if (0 != GetModuleFileName (_gdk_dll_hinstance, sLoc, MAX_PATH))
304 ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
309 if (0 == hAppIcon && 0 == hAppIconSm)
311 hAppIcon = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
312 GetSystemMetrics (SM_CXICON),
313 GetSystemMetrics (SM_CYICON), 0);
314 hAppIconSm = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
315 GetSystemMetrics (SM_CXSMICON),
316 GetSystemMetrics (SM_CYSMICON), 0);
321 hAppIcon = hAppIconSm;
322 else if (0 == hAppIconSm)
323 hAppIconSm = hAppIcon;
325 wcl.lpszMenuName = NULL;
327 /* initialize once per class */
329 * HB: Setting the background brush leads to flicker, because we
330 * don't get asked how to clear the background. This is not what
331 * we want, at least not for input_only windows ...
333 #define ONCE_PER_CLASS() \
334 wcl.hIcon = CopyIcon (hAppIcon); \
335 wcl.hIconSm = CopyIcon (hAppIconSm); \
336 wcl.hbrBackground = NULL; \
337 wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
341 case GDK_WINDOW_TOPLEVEL:
342 if (0 == klassTOPLEVEL)
344 wcl.lpszClassName = L"gdkWindowToplevel";
347 klassTOPLEVEL = RegisterClassExW (&wcl);
349 klass = klassTOPLEVEL;
352 case GDK_WINDOW_CHILD:
355 wcl.lpszClassName = L"gdkWindowChild";
357 wcl.style |= CS_PARENTDC; /* MSDN: ... enhances system performance. */
359 klassCHILD = RegisterClassExW (&wcl);
364 case GDK_WINDOW_TEMP:
365 if ((wtype_hint == GDK_WINDOW_TYPE_HINT_MENU) ||
366 (wtype_hint == GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU) ||
367 (wtype_hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU) ||
368 (wtype_hint == GDK_WINDOW_TYPE_HINT_TOOLTIP))
370 if (klassTEMPSHADOW == 0)
372 wcl.lpszClassName = L"gdkWindowTempShadow";
373 wcl.style |= CS_SAVEBITS;
374 if (LOBYTE (g_win32_get_windows_version()) > 0x05 ||
375 LOWORD (g_win32_get_windows_version()) == 0x0105)
377 /* Windows XP (5.1) or above */
378 wcl.style |= 0x00020000; /* CS_DROPSHADOW */
381 klassTEMPSHADOW = RegisterClassExW (&wcl);
384 klass = klassTEMPSHADOW;
390 wcl.lpszClassName = L"gdkWindowTemp";
391 wcl.style |= CS_SAVEBITS;
393 klassTEMP = RegisterClassExW (&wcl);
401 g_assert_not_reached ();
407 WIN32_API_FAILED ("RegisterClassExW");
408 g_error ("That is a fatal error");
414 * Create native windows.
416 * With the default Gdk the created windows are mostly toplevel windows.
418 * Placement of the window is derived from the passed in window,
419 * except for toplevel window where OS/Window Manager placement
422 * The visual parameter, is based on GDK_WA_VISUAL if set already.
423 * From attributes the only things used is: colormap, title,
424 * wmclass and type_hint. [1]. We are checking redundant information
425 * and complain if that changes, which would break this implementation
428 * [1] http://mail.gnome.org/archives/gtk-devel-list/2010-August/msg00214.html
431 _gdk_win32_display_create_window_impl (GdkDisplay *display,
433 GdkWindow *real_parent,
435 GdkEventMask event_mask,
436 GdkWindowAttr *attributes,
437 gint attributes_mask)
442 DWORD dwStyle = 0, dwExStyle;
444 GdkWindowImplWin32 *impl;
447 gboolean override_redirect;
448 gint window_width, window_height;
449 gint offset_x = 0, offset_y = 0;
450 gint x, y, real_x = 0, real_y = 0;
451 /* check consistency of redundant information */
452 guint remaining_mask = attributes_mask;
455 g_print ("_gdk_window_impl_new: %s %s\n",
456 (window->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
457 (window->window_type == GDK_WINDOW_CHILD ? "CHILD" :
458 (window->window_type == GDK_WINDOW_TEMP ? "TEMP" :
460 (attributes->wclass == GDK_INPUT_OUTPUT ? "" : "input-only"))
463 /* to ensure to not miss important information some additional check against
464 * attributes which may silently work on X11 */
465 if ((attributes_mask & GDK_WA_X) != 0)
467 g_assert (attributes->x == window->x);
468 remaining_mask &= ~GDK_WA_X;
470 if ((attributes_mask & GDK_WA_Y) != 0)
472 g_assert (attributes->y == window->y);
473 remaining_mask &= ~GDK_WA_Y;
475 override_redirect = FALSE;
476 if ((attributes_mask & GDK_WA_NOREDIR) != 0)
478 override_redirect = !!attributes->override_redirect;
479 remaining_mask &= ~GDK_WA_NOREDIR;
482 if ((remaining_mask & ~(GDK_WA_WMCLASS|GDK_WA_VISUAL|GDK_WA_CURSOR|GDK_WA_TITLE|GDK_WA_TYPE_HINT)) != 0)
483 g_warning ("_gdk_window_impl_new: uexpected attribute 0x%X",
484 remaining_mask & ~(GDK_WA_WMCLASS|GDK_WA_VISUAL|GDK_WA_CURSOR|GDK_WA_TITLE|GDK_WA_TYPE_HINT));
486 hparent = GDK_WINDOW_HWND (real_parent);
488 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
489 impl->wrapper = GDK_WINDOW (window);
490 window->impl = GDK_WINDOW_IMPL (impl);
492 if (attributes_mask & GDK_WA_VISUAL)
493 g_assert (gdk_screen_get_system_visual (screen) == attributes->visual);
495 impl->extension_events_selected = FALSE;
496 impl->override_redirect = override_redirect;
498 /* wclass is not any longer set always, but if is ... */
499 if ((attributes_mask & GDK_WA_WMCLASS) == GDK_WA_WMCLASS)
500 g_assert ((attributes->wclass == GDK_INPUT_OUTPUT) == !window->input_only);
502 if (!window->input_only)
508 /* I very much doubt using WS_EX_TRANSPARENT actually
509 * corresponds to how X11 InputOnly windows work, but it appears
510 * to work well enough for the actual use cases in gtk.
512 dwExStyle = WS_EX_TRANSPARENT;
513 GDK_NOTE (MISC, g_print ("... GDK_INPUT_ONLY\n"));
516 switch (window->window_type)
518 case GDK_WINDOW_TOPLEVEL:
519 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
521 /* The common code warns for this case. */
522 hparent = GetDesktopWindow ();
524 /* Children of foreign windows aren't toplevel windows */
525 if (GDK_WINDOW_TYPE (real_parent) == GDK_WINDOW_FOREIGN)
527 dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN;
531 if (window->window_type == GDK_WINDOW_TOPLEVEL)
532 dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
534 dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
536 offset_x = _gdk_offset_x;
537 offset_y = _gdk_offset_y;
541 case GDK_WINDOW_CHILD:
542 dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
545 case GDK_WINDOW_TEMP:
546 /* A temp window is not necessarily a top level window */
547 dwStyle = (_gdk_root == real_parent ? WS_POPUP : WS_CHILDWINDOW);
548 dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
549 dwExStyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
550 offset_x = _gdk_offset_x;
551 offset_y = _gdk_offset_y;
555 g_assert_not_reached ();
558 if (window->window_type != GDK_WINDOW_CHILD)
560 rect.left = window->x;
561 rect.top = window->y;
562 rect.right = window->width;
563 rect.bottom = window->height;
565 AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
567 real_x = window->x - offset_x;
568 real_y = window->y - offset_y;
570 if (window->window_type == GDK_WINDOW_TOPLEVEL)
572 /* We initially place it at default so that we can get the
573 default window positioning if we want */
574 x = y = CW_USEDEFAULT;
578 /* TEMP, FOREIGN: Put these where requested */
583 window_width = rect.right - rect.left;
584 window_height = rect.bottom - rect.top;
588 /* adjust position relative to real_parent */
589 window_width = window->width;
590 window_height = window->height;
591 /* use given position for initial placement, native coordinates */
592 x = window->x + window->parent->abs_x - offset_x;
593 y = window->y + window->parent->abs_y - offset_y;
596 if (attributes_mask & GDK_WA_TITLE)
597 title = attributes->title;
599 title = get_default_title ();
600 if (!title || !*title)
603 impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask;
605 if (attributes_mask & GDK_WA_TYPE_HINT)
606 gdk_window_set_type_hint (window, attributes->type_hint);
608 if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
609 dwExStyle |= WS_EX_TOOLWINDOW;
611 klass = RegisterGdkClass (window->window_type, impl->type_hint);
613 wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
615 hwndNew = CreateWindowExW (dwExStyle,
616 MAKEINTRESOURCEW (klass),
621 window_width, window_height,
626 if (GDK_WINDOW_HWND (window) != hwndNew)
628 g_warning ("gdk_window_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
629 GDK_WINDOW_HWND (window),
632 /* HB: IHMO due to a race condition the handle was increased by
633 * one, which causes much trouble. Because I can't find the
634 * real bug, try to workaround it ...
635 * To reproduce: compile with MSVC 5, DEBUG=1
638 gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
639 GDK_WINDOW_HWND (window) = hwndNew;
640 gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
642 /* the old behaviour, but with warning */
643 impl->handle = hwndNew;
648 if (window->window_type != GDK_WINDOW_CHILD)
650 GetWindowRect (GDK_WINDOW_HWND (window), &rect);
651 impl->initial_x = rect.left;
652 impl->initial_y = rect.top;
654 /* Now we know the initial position, move to actually specified position */
655 if (real_x != x || real_y != y)
657 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
658 real_x, real_y, 0, 0,
659 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
663 g_object_ref (window);
664 gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
666 GDK_NOTE (MISC, g_print ("... \"%s\" %dx%d@%+d%+d %p = %p\n",
668 window_width, window_height,
669 window->x - offset_x,
670 window->y - offset_y,
672 GDK_WINDOW_HWND (window)));
674 /* Add window handle to title */
675 GDK_NOTE (MISC_OR_EVENTS, gdk_window_set_title (window, title));
679 if (impl->handle == NULL)
681 WIN32_API_FAILED ("CreateWindowExW");
682 g_object_unref (window);
686 // if (!from_set_skip_taskbar_hint && window->window_type == GDK_WINDOW_TEMP)
687 // gdk_window_set_skip_taskbar_hint (window, TRUE);
689 if (attributes_mask & GDK_WA_CURSOR)
690 gdk_window_set_cursor (window, attributes->cursor);
694 gdk_win32_window_foreign_new_for_display (GdkDisplay *display,
698 GdkWindowImplWin32 *impl;
704 g_return_val_if_fail (display == _gdk_display, NULL);
706 if ((window = gdk_win32_window_lookup_for_display (display, anid)) != NULL)
707 return g_object_ref (window);
709 window = _gdk_display_create_window (display);
710 window->visual = gdk_screen_get_system_visual (_gdk_screen);
711 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
712 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
713 impl->wrapper = window;
714 parent = GetParent (anid);
716 window->parent = gdk_win32_handle_table_lookup (parent);
717 if (!window->parent || GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_FOREIGN)
718 window->parent = _gdk_root;
720 window->parent->children = g_list_prepend (window->parent->children, window);
722 GetClientRect ((HWND) anid, &rect);
724 point.y = rect.right;
725 ClientToScreen ((HWND) anid, &point);
726 if (parent != GetDesktopWindow ())
727 ScreenToClient (parent, &point);
730 window->width = rect.right - rect.left;
731 window->height = rect.bottom - rect.top;
732 window->window_type = GDK_WINDOW_FOREIGN;
733 window->destroyed = FALSE;
734 window->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
735 if (IsWindowVisible ((HWND) anid))
736 window->state &= (~GDK_WINDOW_STATE_WITHDRAWN);
738 window->state |= GDK_WINDOW_STATE_WITHDRAWN;
739 if (GetWindowLong ((HWND)anid, GWL_EXSTYLE) & WS_EX_TOPMOST)
740 window->state |= GDK_WINDOW_STATE_ABOVE;
742 window->state &= (~GDK_WINDOW_STATE_ABOVE);
743 window->state &= (~GDK_WINDOW_STATE_BELOW);
744 window->viewable = TRUE;
746 window->depth = gdk_visual_get_system ()->depth;
748 g_object_ref (window);
749 gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
751 GDK_NOTE (MISC, g_print ("gdk_win32_window_foreign_new_for_display: %p: %s@%+d%+d\n",
753 _gdk_win32_window_description (window),
754 window->x, window->y));
760 gdk_win32_window_destroy (GdkWindow *window,
762 gboolean foreign_destroy)
764 GdkWindowImplWin32 *window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
767 g_return_if_fail (GDK_IS_WINDOW (window));
769 GDK_NOTE (MISC, g_print ("gdk_win32_window_destroy: %p\n",
770 GDK_WINDOW_HWND (window)));
772 /* Remove ourself from the modal stack */
773 _gdk_remove_modal_window (window);
775 /* Remove all our transient children */
776 tmp = window_impl->transient_children;
779 GdkWindow *child = tmp->data;
780 GdkWindowImplWin32 *child_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW (child)->impl);
782 child_impl->transient_owner = NULL;
783 tmp = g_slist_next (tmp);
785 g_slist_free (window_impl->transient_children);
786 window_impl->transient_children = NULL;
788 /* Remove ourself from our transient owner */
789 if (window_impl->transient_owner != NULL)
791 gdk_window_set_transient_for (window, NULL);
794 if (!recursing && !foreign_destroy)
796 window->destroyed = TRUE;
797 DestroyWindow (GDK_WINDOW_HWND (window));
801 static cairo_surface_t *
802 gdk_win32_window_resize_cairo_surface (GdkWindow *window,
803 cairo_surface_t *surface,
807 /* XXX: Make Cairo surface use DC clip */
808 cairo_surface_destroy (surface);
814 gdk_win32_window_destroy_foreign (GdkWindow *window)
816 /* It's somebody else's window, but in our hierarchy, so reparent it
817 * to the desktop, and then try to destroy it.
819 gdk_window_hide (window);
820 gdk_window_reparent (window, NULL, 0, 0);
822 PostMessage (GDK_WINDOW_HWND (window), WM_CLOSE, 0, 0);
825 /* This function is called when the window really gone.
828 gdk_win32_window_destroy_notify (GdkWindow *window)
830 g_return_if_fail (GDK_IS_WINDOW (window));
833 g_print ("gdk_window_destroy_notify: %p%s\n",
834 GDK_WINDOW_HWND (window),
835 (GDK_WINDOW_DESTROYED (window) ? " (destroyed)" : "")));
837 if (!GDK_WINDOW_DESTROYED (window))
839 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
840 g_warning ("window %p unexpectedly destroyed",
841 GDK_WINDOW_HWND (window));
843 _gdk_window_destroy (window, TRUE);
846 gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
847 g_object_unref (window);
851 get_outer_rect (GdkWindow *window,
856 rect->left = rect->top = 0;
858 rect->bottom = height;
860 _gdk_win32_adjust_client_rect (window, rect);
864 adjust_for_gravity_hints (GdkWindow *window,
869 GdkWindowImplWin32 *impl;
871 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
873 if (impl->hint_flags & GDK_HINT_WIN_GRAVITY)
875 #ifdef G_ENABLE_DEBUG
876 gint orig_x = *x, orig_y = *y;
879 switch (impl->hints.win_gravity)
881 case GDK_GRAVITY_NORTH:
882 case GDK_GRAVITY_CENTER:
883 case GDK_GRAVITY_SOUTH:
884 *x -= (outer_rect->right - outer_rect->left) / 2;
885 *x += window->width / 2;
888 case GDK_GRAVITY_SOUTH_EAST:
889 case GDK_GRAVITY_EAST:
890 case GDK_GRAVITY_NORTH_EAST:
891 *x -= outer_rect->right - outer_rect->left;
895 case GDK_GRAVITY_STATIC:
896 *x += outer_rect->left;
903 switch (impl->hints.win_gravity)
905 case GDK_GRAVITY_WEST:
906 case GDK_GRAVITY_CENTER:
907 case GDK_GRAVITY_EAST:
908 *y -= (outer_rect->bottom - outer_rect->top) / 2;
909 *y += window->height / 2;
912 case GDK_GRAVITY_SOUTH_WEST:
913 case GDK_GRAVITY_SOUTH:
914 case GDK_GRAVITY_SOUTH_EAST:
915 *y -= outer_rect->bottom - outer_rect->top;
916 *y += window->height;
919 case GDK_GRAVITY_STATIC:
920 *y += outer_rect->top;
927 (orig_x != *x || orig_y != *y) ?
928 g_print ("adjust_for_gravity_hints: x: %d->%d, y: %d->%d\n",
929 orig_x, *x, orig_y, *y)
935 show_window_internal (GdkWindow *window,
936 gboolean already_mapped,
939 GdkWindowImplWin32 *window_impl;
940 gboolean focus_on_map = FALSE;
943 if (window->destroyed)
946 GDK_NOTE (MISC, g_print ("show_window_internal: %p: %s%s\n",
947 GDK_WINDOW_HWND (window),
948 _gdk_win32_window_state_to_string (window->state),
949 (deiconify ? " deiconify" : "")));
951 /* If asked to show (not deiconify) an withdrawn and iconified
956 (window->state & GDK_WINDOW_STATE_ICONIFIED))
958 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMINNOACTIVE);
962 /* If asked to just show an iconified window, do nothing. */
963 if (!deiconify && (window->state & GDK_WINDOW_STATE_ICONIFIED))
966 /* If asked to deiconify an already noniconified window, do
967 * nothing. (Especially, don't cause the window to rise and
968 * activate. There are different calls for that.)
970 if (deiconify && !(window->state & GDK_WINDOW_STATE_ICONIFIED))
973 /* If asked to show (but not raise) a window that is already
974 * visible, do nothing.
976 if (!deiconify && !already_mapped && IsWindowVisible (GDK_WINDOW_HWND (window)))
982 focus_on_map = window->focus_on_map;
984 exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
986 /* Use SetWindowPos to show transparent windows so automatic redraws
987 * in other windows can be suppressed.
989 if (exstyle & WS_EX_TRANSPARENT)
991 UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
993 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
994 flags |= SWP_NOACTIVATE;
996 SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOP, 0, 0, 0, 0, flags);
1001 /* For initial map of "normal" windows we want to emulate WM window
1002 * positioning behaviour, which means:
1003 * + Use user specified position if GDK_HINT_POS or GDK_HINT_USER_POS
1005 * + default to the initial CW_USEDEFAULT placement,
1006 * no matter if the user moved the window before showing it.
1007 * + Certain window types and hints have more elaborate positioning
1010 window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1011 if (!already_mapped &&
1012 GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL &&
1013 (window_impl->hint_flags & (GDK_HINT_POS | GDK_HINT_USER_POS)) == 0 &&
1014 !window_impl->override_redirect)
1016 gboolean center = FALSE;
1017 RECT window_rect, center_on_rect;
1020 x = window_impl->initial_x;
1021 y = window_impl->initial_y;
1023 if (window_impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
1028 monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
1029 mi.cbSize = sizeof (mi);
1030 if (monitor && GetMonitorInfo (monitor, &mi))
1031 center_on_rect = mi.rcMonitor;
1034 center_on_rect.left = 0;
1035 center_on_rect.right = 0;
1036 center_on_rect.right = GetSystemMetrics (SM_CXSCREEN);
1037 center_on_rect.bottom = GetSystemMetrics (SM_CYSCREEN);
1041 else if (window_impl->transient_owner != NULL &&
1042 GDK_WINDOW_IS_MAPPED (window_impl->transient_owner))
1044 GdkWindow *owner = window_impl->transient_owner;
1045 /* Center on transient parent */
1046 center_on_rect.left = owner->x;
1047 center_on_rect.top = owner->y;
1048 center_on_rect.right = center_on_rect.left + owner->width;
1049 center_on_rect.bottom = center_on_rect.top + owner->height;
1050 _gdk_win32_adjust_client_rect (GDK_WINDOW (owner), ¢er_on_rect);
1056 window_rect.left = 0;
1057 window_rect.top = 0;
1058 window_rect.right = window->width;
1059 window_rect.bottom = window->height;
1060 _gdk_win32_adjust_client_rect (window, &window_rect);
1062 x = center_on_rect.left + ((center_on_rect.right - center_on_rect.left) - (window_rect.right - window_rect.left)) / 2;
1063 y = center_on_rect.top + ((center_on_rect.bottom - center_on_rect.top) - (window_rect.bottom - window_rect.top)) / 2;
1066 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1068 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
1071 if (!already_mapped &&
1072 GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL &&
1073 !window_impl->override_redirect)
1075 /* Ensure new windows are fully onscreen */
1081 GetWindowRect (GDK_WINDOW_HWND (window), &window_rect);
1083 monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
1084 mi.cbSize = sizeof (mi);
1085 if (monitor && GetMonitorInfo (monitor, &mi))
1087 x = window_rect.left;
1088 y = window_rect.top;
1090 if (window_rect.right > mi.rcWork.right)
1092 window_rect.left -= (window_rect.right - mi.rcWork.right);
1093 window_rect.right -= (window_rect.right - mi.rcWork.right);
1096 if (window_rect.bottom > mi.rcWork.bottom)
1098 window_rect.top -= (window_rect.bottom - mi.rcWork.bottom);
1099 window_rect.bottom -= (window_rect.bottom - mi.rcWork.bottom);
1102 if (window_rect.left < mi.rcWork.left)
1104 window_rect.right += (mi.rcWork.left - window_rect.left);
1105 window_rect.left += (mi.rcWork.left - window_rect.left);
1108 if (window_rect.top < mi.rcWork.top)
1110 window_rect.bottom += (mi.rcWork.top - window_rect.top);
1111 window_rect.top += (mi.rcWork.top - window_rect.top);
1114 if (x != window_rect.left || y != window_rect.top)
1115 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1116 window_rect.left, window_rect.top, 0, 0,
1117 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
1122 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1124 gdk_window_fullscreen (window);
1126 else if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1128 ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
1130 else if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1133 ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
1135 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
1137 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
1139 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
1143 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
1146 /* Sync STATE_ABOVE to TOPMOST */
1147 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_TEMP &&
1148 (((window->state & GDK_WINDOW_STATE_ABOVE) &&
1149 !(exstyle & WS_EX_TOPMOST)) ||
1150 (!(window->state & GDK_WINDOW_STATE_ABOVE) &&
1151 (exstyle & WS_EX_TOPMOST))))
1153 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
1154 (window->state & GDK_WINDOW_STATE_ABOVE)?HWND_TOPMOST:HWND_NOTOPMOST,
1156 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
1161 gdk_win32_window_show (GdkWindow *window,
1162 gboolean already_mapped)
1164 show_window_internal (window, FALSE, FALSE);
1168 gdk_win32_window_hide (GdkWindow *window)
1170 if (window->destroyed)
1173 GDK_NOTE (MISC, g_print ("gdk_win32_window_hide: %p: %s\n",
1174 GDK_WINDOW_HWND (window),
1175 _gdk_win32_window_state_to_string (window->state)));
1177 if (GDK_WINDOW_IS_MAPPED (window))
1178 gdk_synthesize_window_state (window,
1180 GDK_WINDOW_STATE_WITHDRAWN);
1182 _gdk_window_clear_update_area (window);
1184 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1185 ShowOwnedPopups (GDK_WINDOW_HWND (window), FALSE);
1187 if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
1189 SetWindowPos (GDK_WINDOW_HWND (window), HWND_BOTTOM,
1191 SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
1195 ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
1200 gdk_win32_window_withdraw (GdkWindow *window)
1202 if (window->destroyed)
1205 GDK_NOTE (MISC, g_print ("gdk_win32_window_withdraw: %p: %s\n",
1206 GDK_WINDOW_HWND (window),
1207 _gdk_win32_window_state_to_string (window->state)));
1209 gdk_window_hide (window); /* ??? */
1213 gdk_win32_window_move (GdkWindow *window,
1216 GdkWindowImplWin32 *impl;
1218 g_return_if_fail (GDK_IS_WINDOW (window));
1220 if (GDK_WINDOW_DESTROYED (window))
1223 GDK_NOTE (MISC, g_print ("gdk_win32_window_move: %p: %+d%+d\n",
1224 GDK_WINDOW_HWND (window), x, y));
1226 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1228 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1231 /* Don't check GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD.
1232 * Foreign windows (another app's windows) might be children of our
1233 * windows! Especially in the case of gtkplug/socket.
1235 if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1237 _gdk_window_move_resize_child (window, x, y, window->width, window->height);
1243 get_outer_rect (window, window->width, window->height, &outer_rect);
1245 adjust_for_gravity_hints (window, &outer_rect, &x, &y);
1247 GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,0,0,"
1248 "NOACTIVATE|NOSIZE|NOZORDER)\n",
1249 GDK_WINDOW_HWND (window),
1250 x - _gdk_offset_x, y - _gdk_offset_y));
1252 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1253 x - _gdk_offset_x, y - _gdk_offset_y, 0, 0,
1254 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
1259 gdk_win32_window_resize (GdkWindow *window,
1260 gint width, gint height)
1262 GdkWindowImplWin32 *impl;
1264 g_return_if_fail (GDK_IS_WINDOW (window));
1266 if (GDK_WINDOW_DESTROYED (window))
1274 GDK_NOTE (MISC, g_print ("gdk_win32_window_resize: %p: %dx%d\n",
1275 GDK_WINDOW_HWND (window), width, height));
1277 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1279 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1282 if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1284 _gdk_window_move_resize_child (window, window->x, window->y, width, height);
1290 get_outer_rect (window, width, height, &outer_rect);
1292 GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,0,0,%ld,%ld,"
1293 "NOACTIVATE|NOMOVE|NOZORDER)\n",
1294 GDK_WINDOW_HWND (window),
1295 outer_rect.right - outer_rect.left,
1296 outer_rect.bottom - outer_rect.top));
1298 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1300 outer_rect.right - outer_rect.left,
1301 outer_rect.bottom - outer_rect.top,
1302 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER));
1303 window->resize_count += 1;
1308 gdk_win32_window_move_resize_internal (GdkWindow *window,
1314 GdkWindowImplWin32 *impl;
1316 g_return_if_fail (GDK_IS_WINDOW (window));
1318 if (GDK_WINDOW_DESTROYED (window))
1326 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1328 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1331 GDK_NOTE (MISC, g_print ("gdk_win32_window_move_resize: %p: %dx%d@%+d%+d\n",
1332 GDK_WINDOW_HWND (window),
1333 width, height, x, y));
1335 if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1337 _gdk_window_move_resize_child (window, x, y, width, height);
1343 get_outer_rect (window, width, height, &outer_rect);
1345 adjust_for_gravity_hints (window, &outer_rect, &x, &y);
1347 GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%ld,%ld,"
1348 "NOACTIVATE|NOZORDER)\n",
1349 GDK_WINDOW_HWND (window),
1350 x - _gdk_offset_x, y - _gdk_offset_y,
1351 outer_rect.right - outer_rect.left,
1352 outer_rect.bottom - outer_rect.top));
1354 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1355 x - _gdk_offset_x, y - _gdk_offset_y,
1356 outer_rect.right - outer_rect.left,
1357 outer_rect.bottom - outer_rect.top,
1358 SWP_NOACTIVATE | SWP_NOZORDER));
1363 gdk_win32_window_move_resize (GdkWindow *window,
1370 GdkWindowImplWin32 *window_impl;
1372 window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1373 window_impl->inhibit_configure = TRUE;
1375 /* We ignore changes to the window being moved or resized by the
1376 user, as we don't want to fight the user */
1377 if (GDK_WINDOW_HWND (window) == _modal_move_resize_window)
1380 if (with_move && (width < 0 && height < 0))
1382 gdk_win32_window_move (window, x, y);
1388 gdk_win32_window_move_resize_internal (window, x, y, width, height);
1392 gdk_win32_window_resize (window, width, height);
1397 window_impl->inhibit_configure = FALSE;
1399 if (WINDOW_IS_TOPLEVEL (window))
1400 _gdk_win32_emit_configure_event (window);
1404 gdk_win32_window_reparent (GdkWindow *window,
1405 GdkWindow *new_parent,
1410 GdkWindow *old_parent;
1411 GdkWindowImplWin32 *impl;
1412 gboolean was_toplevel;
1416 new_parent = _gdk_root;
1418 old_parent = window->parent;
1419 parent = new_parent;
1420 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1422 GDK_NOTE (MISC, g_print ("gdk_win32_window_reparent: %p: %p\n",
1423 GDK_WINDOW_HWND (window),
1424 GDK_WINDOW_HWND (new_parent)));
1426 style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1428 was_toplevel = GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) == GetDesktopWindow ();
1429 if (was_toplevel && new_parent != _gdk_root)
1431 /* Reparenting from top-level (child of desktop). Clear out
1434 style &= ~(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
1436 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1438 else if (new_parent == _gdk_root)
1440 /* Reparenting to top-level. Add decorations. */
1441 style &= ~(WS_CHILD);
1442 style |= WS_OVERLAPPEDWINDOW;
1443 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1446 API_CALL (SetParent, (GDK_WINDOW_HWND (window),
1447 GDK_WINDOW_HWND (new_parent)));
1449 API_CALL (MoveWindow, (GDK_WINDOW_HWND (window),
1450 x, y, window->width, window->height, TRUE));
1452 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1455 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1456 new_parent = _gdk_root;
1458 window->parent = new_parent;
1460 /* Switch the window type as appropriate */
1462 switch (GDK_WINDOW_TYPE (new_parent))
1464 case GDK_WINDOW_ROOT:
1465 if (impl->toplevel_window_type != -1)
1466 GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
1467 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1468 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1471 case GDK_WINDOW_TOPLEVEL:
1472 case GDK_WINDOW_CHILD:
1473 case GDK_WINDOW_TEMP:
1474 if (WINDOW_IS_TOPLEVEL (window))
1476 /* Save the original window type so we can restore it if the
1477 * window is reparented back to be a toplevel.
1479 impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
1480 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1485 old_parent->children =
1486 g_list_remove (old_parent->children, window);
1488 parent->children = g_list_prepend (parent->children, window);
1494 gdk_win32_window_raise (GdkWindow *window)
1496 if (!GDK_WINDOW_DESTROYED (window))
1498 GDK_NOTE (MISC, g_print ("gdk_win32_window_raise: %p\n",
1499 GDK_WINDOW_HWND (window)));
1501 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
1502 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOPMOST,
1504 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1505 else if (window->accept_focus)
1506 /* Do not wrap this in an API_CALL macro as SetForegroundWindow might
1507 * fail when for example dragging a window belonging to a different
1508 * application at the time of a gtk_window_present() call due to focus
1509 * stealing prevention. */
1510 SetForegroundWindow (GDK_WINDOW_HWND (window));
1512 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
1514 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1519 gdk_win32_window_lower (GdkWindow *window)
1521 if (!GDK_WINDOW_DESTROYED (window))
1523 GDK_NOTE (MISC, g_print ("gdk_win32_window_lower: %p\n"
1524 "... SetWindowPos(%p,HWND_BOTTOM,0,0,0,0,"
1525 "NOACTIVATE|NOMOVE|NOSIZE)\n",
1526 GDK_WINDOW_HWND (window),
1527 GDK_WINDOW_HWND (window)));
1529 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_BOTTOM,
1531 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1536 gdk_win32_window_set_urgency_hint (GdkWindow *window,
1539 FLASHWINFO flashwinfo;
1540 typedef BOOL (*PFN_FlashWindowEx) (FLASHWINFO*);
1541 PFN_FlashWindowEx flashWindowEx = NULL;
1543 g_return_if_fail (GDK_IS_WINDOW (window));
1544 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1546 if (GDK_WINDOW_DESTROYED (window))
1549 flashWindowEx = (PFN_FlashWindowEx) GetProcAddress (GetModuleHandle ("user32.dll"), "FlashWindowEx");
1553 flashwinfo.cbSize = sizeof (flashwinfo);
1554 flashwinfo.hwnd = GDK_WINDOW_HWND (window);
1556 flashwinfo.dwFlags = FLASHW_ALL | FLASHW_TIMER;
1558 flashwinfo.dwFlags = FLASHW_STOP;
1559 flashwinfo.uCount = 0;
1560 flashwinfo.dwTimeout = 0;
1562 flashWindowEx (&flashwinfo);
1566 FlashWindow (GDK_WINDOW_HWND (window), urgent);
1571 get_effective_window_decorations (GdkWindow *window,
1572 GdkWMDecoration *decoration)
1574 GdkWindowImplWin32 *impl;
1576 impl = (GdkWindowImplWin32 *)window->impl;
1578 if (gdk_window_get_decorations (window, decoration))
1581 if (window->window_type != GDK_WINDOW_TOPLEVEL)
1586 if ((impl->hint_flags & GDK_HINT_MIN_SIZE) &&
1587 (impl->hint_flags & GDK_HINT_MAX_SIZE) &&
1588 impl->hints.min_width == impl->hints.max_width &&
1589 impl->hints.min_height == impl->hints.max_height)
1591 *decoration = GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MAXIMIZE;
1593 if (impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
1594 impl->type_hint == GDK_WINDOW_TYPE_HINT_MENU ||
1595 impl->type_hint == GDK_WINDOW_TYPE_HINT_TOOLBAR)
1597 *decoration |= GDK_DECOR_MINIMIZE;
1599 else if (impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
1601 *decoration |= GDK_DECOR_MENU | GDK_DECOR_MINIMIZE;
1606 else if (impl->hint_flags & GDK_HINT_MAX_SIZE)
1608 *decoration = GDK_DECOR_ALL | GDK_DECOR_MAXIMIZE;
1609 if (impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
1610 impl->type_hint == GDK_WINDOW_TYPE_HINT_MENU ||
1611 impl->type_hint == GDK_WINDOW_TYPE_HINT_TOOLBAR)
1613 *decoration |= GDK_DECOR_MINIMIZE;
1620 switch (impl->type_hint)
1622 case GDK_WINDOW_TYPE_HINT_DIALOG:
1623 *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1626 case GDK_WINDOW_TYPE_HINT_MENU:
1627 *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1630 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
1631 case GDK_WINDOW_TYPE_HINT_UTILITY:
1632 gdk_window_set_skip_taskbar_hint (window, TRUE);
1633 gdk_window_set_skip_pager_hint (window, TRUE);
1634 *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1637 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
1638 *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MENU |
1639 GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1642 case GDK_WINDOW_TYPE_HINT_DOCK:
1645 case GDK_WINDOW_TYPE_HINT_DESKTOP:
1650 case GDK_WINDOW_TYPE_HINT_NORMAL:
1651 *decoration = GDK_DECOR_ALL;
1660 gdk_win32_window_set_geometry_hints (GdkWindow *window,
1661 const GdkGeometry *geometry,
1662 GdkWindowHints geom_mask)
1664 GdkWindowImplWin32 *impl;
1667 g_return_if_fail (GDK_IS_WINDOW (window));
1669 if (GDK_WINDOW_DESTROYED (window))
1672 GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints: %p\n",
1673 GDK_WINDOW_HWND (window)));
1675 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1677 fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
1679 fi->hint_flags = geom_mask;
1681 impl->hint_flags = geom_mask;
1682 impl->hints = *geometry;
1684 if (geom_mask & GDK_HINT_POS)
1685 ; /* even the X11 mplementation doesn't care */
1687 if (geom_mask & GDK_HINT_MIN_SIZE)
1689 GDK_NOTE (MISC, g_print ("... MIN_SIZE: %dx%d\n",
1690 geometry->min_width, geometry->min_height));
1693 if (geom_mask & GDK_HINT_MAX_SIZE)
1695 GDK_NOTE (MISC, g_print ("... MAX_SIZE: %dx%d\n",
1696 geometry->max_width, geometry->max_height));
1699 if (geom_mask & GDK_HINT_BASE_SIZE)
1701 GDK_NOTE (MISC, g_print ("... BASE_SIZE: %dx%d\n",
1702 geometry->base_width, geometry->base_height));
1705 if (geom_mask & GDK_HINT_RESIZE_INC)
1707 GDK_NOTE (MISC, g_print ("... RESIZE_INC: (%d,%d)\n",
1708 geometry->width_inc, geometry->height_inc));
1711 if (geom_mask & GDK_HINT_ASPECT)
1713 GDK_NOTE (MISC, g_print ("... ASPECT: %g--%g\n",
1714 geometry->min_aspect, geometry->max_aspect));
1717 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1719 GDK_NOTE (MISC, g_print ("... GRAVITY: %d\n", geometry->win_gravity));
1722 update_style_bits (window);
1726 gdk_win32_window_set_title (GdkWindow *window,
1731 g_return_if_fail (GDK_IS_WINDOW (window));
1732 g_return_if_fail (title != NULL);
1734 if (GDK_WINDOW_DESTROYED (window))
1737 /* Empty window titles not allowed, so set it to just a period. */
1741 GDK_NOTE (MISC, g_print ("gdk_window_set_title: %p: %s\n",
1742 GDK_WINDOW_HWND (window), title));
1744 GDK_NOTE (MISC_OR_EVENTS, title = g_strdup_printf ("%p %s", GDK_WINDOW_HWND (window), title));
1746 wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
1747 API_CALL (SetWindowTextW, (GDK_WINDOW_HWND (window), wtitle));
1750 GDK_NOTE (MISC_OR_EVENTS, g_free ((char *) title));
1754 gdk_win32_window_set_role (GdkWindow *window,
1757 g_return_if_fail (GDK_IS_WINDOW (window));
1759 GDK_NOTE (MISC, g_print ("gdk_window_set_role: %p: %s\n",
1760 GDK_WINDOW_HWND (window),
1761 (role ? role : "NULL")));
1766 gdk_win32_window_set_transient_for (GdkWindow *window,
1769 HWND window_id, parent_id;
1770 GdkWindowImplWin32 *window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1771 GdkWindowImplWin32 *parent_impl = NULL;
1774 g_return_if_fail (GDK_IS_WINDOW (window));
1776 window_id = GDK_WINDOW_HWND (window);
1777 parent_id = parent != NULL ? GDK_WINDOW_HWND (parent) : NULL;
1779 GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %p: %p\n", window_id, parent_id));
1781 if (GDK_WINDOW_DESTROYED (window) || (parent && GDK_WINDOW_DESTROYED (parent)))
1783 if (GDK_WINDOW_DESTROYED (window))
1784 GDK_NOTE (MISC, g_print ("... destroyed!\n"));
1786 GDK_NOTE (MISC, g_print ("... owner destroyed!\n"));
1791 if (window->window_type == GDK_WINDOW_CHILD)
1793 GDK_NOTE (MISC, g_print ("... a child window!\n"));
1799 GdkWindowImplWin32 *trans_impl = GDK_WINDOW_IMPL_WIN32 (window_impl->transient_owner->impl);
1800 if (trans_impl->transient_children != NULL)
1802 item = g_slist_find (trans_impl->transient_children, window);
1804 trans_impl->transient_children = g_slist_delete_link (trans_impl->transient_children, item);
1805 trans_impl->num_transients--;
1807 if (!trans_impl->num_transients)
1809 trans_impl->transient_children = NULL;
1812 g_object_unref (G_OBJECT (window_impl->transient_owner));
1813 g_object_unref (G_OBJECT (window));
1815 window_impl->transient_owner = NULL;
1819 parent_impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
1821 parent_impl->transient_children = g_slist_append (parent_impl->transient_children, window);
1822 g_object_ref (G_OBJECT (window));
1823 parent_impl->num_transients++;
1824 window_impl->transient_owner = parent;
1825 g_object_ref (G_OBJECT (parent));
1828 /* This changes the *owner* of the window, despite the misleading
1829 * name. (Owner and parent are unrelated concepts.) At least that's
1830 * what people who seem to know what they talk about say on
1831 * USENET. Search on Google.
1834 if (SetWindowLongPtr (window_id, GWLP_HWNDPARENT, (LONG_PTR) parent_id) == 0 &&
1835 GetLastError () != 0)
1836 WIN32_API_FAILED ("SetWindowLongPtr");
1840 _gdk_push_modal_window (GdkWindow *window)
1842 modal_window_stack = g_slist_prepend (modal_window_stack,
1847 _gdk_remove_modal_window (GdkWindow *window)
1851 g_return_if_fail (window != NULL);
1853 /* It's possible to be NULL here if someone sets the modal hint of the window
1854 * to FALSE before a modal window stack has ever been created. */
1855 if (modal_window_stack == NULL)
1858 /* Find the requested window in the stack and remove it. Yeah, I realize this
1859 * means we're not a 'real stack', strictly speaking. Sue me. :) */
1860 tmp = g_slist_find (modal_window_stack, window);
1863 modal_window_stack = g_slist_delete_link (modal_window_stack, tmp);
1868 _gdk_modal_blocked (GdkWindow *window)
1871 gboolean found_any = FALSE;
1873 for (l = modal_window_stack; l != NULL; l = l->next)
1875 GdkWindow *modal = l->data;
1877 if (modal == window)
1880 if (GDK_WINDOW_IS_MAPPED (modal))
1888 _gdk_modal_current (void)
1892 for (l = modal_window_stack; l != NULL; l = l->next)
1894 GdkWindow *modal = l->data;
1896 if (GDK_WINDOW_IS_MAPPED (modal))
1904 gdk_win32_window_set_background (GdkWindow *window,
1905 cairo_pattern_t *pattern)
1910 gdk_win32_window_set_device_cursor (GdkWindow *window,
1914 GdkWindowImplWin32 *impl;
1915 GdkWin32Cursor *cursor_private;
1917 HCURSOR hprevcursor;
1919 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1920 cursor_private = (GdkWin32Cursor*) cursor;
1922 if (GDK_WINDOW_DESTROYED (window))
1928 hcursor = cursor_private->hcursor;
1930 GDK_NOTE (MISC, g_print ("gdk_win32_window_set_cursor: %p: %p\n",
1931 GDK_WINDOW_HWND (window),
1934 /* First get the old cursor, if any (we wait to free the old one
1935 * since it may be the current cursor set in the Win32 API right
1938 hprevcursor = impl->hcursor;
1940 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
1942 if (hcursor == NULL)
1943 impl->hcursor = NULL;
1946 /* We must copy the cursor as it is OK to destroy the GdkCursor
1947 * while still in use for some window. See for instance
1948 * gimp_change_win_cursor() which calls gdk_window_set_cursor
1949 * (win, cursor), and immediately afterwards gdk_cursor_destroy
1952 if ((impl->hcursor = CopyCursor (hcursor)) == NULL)
1953 WIN32_API_FAILED ("CopyCursor");
1954 GDK_NOTE (MISC, g_print ("... CopyCursor (%p) = %p\n",
1955 hcursor, impl->hcursor));
1958 /* Destroy the previous cursor */
1959 if (hprevcursor != NULL)
1961 GDK_NOTE (MISC, g_print ("... DestroyCursor (%p)\n", hprevcursor));
1962 API_CALL (DestroyCursor, (hprevcursor));
1967 gdk_win32_window_get_geometry (GdkWindow *window,
1976 if (!GDK_WINDOW_DESTROYED (window))
1980 API_CALL (GetClientRect, (GDK_WINDOW_HWND (window), &rect));
1982 if (window != _gdk_root)
1985 GdkWindow *parent = gdk_window_get_parent (window);
1989 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1990 ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
1996 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1997 ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
2001 if (parent == _gdk_root)
2003 rect.left += _gdk_offset_x;
2004 rect.top += _gdk_offset_y;
2005 rect.right += _gdk_offset_x;
2006 rect.bottom += _gdk_offset_y;
2015 *width = rect.right - rect.left;
2017 *height = rect.bottom - rect.top;
2019 GDK_NOTE (MISC, g_print ("gdk_win32_window_get_geometry: %p: %ldx%ldx%d@%+ld%+ld\n",
2020 GDK_WINDOW_HWND (window),
2021 rect.right - rect.left, rect.bottom - rect.top,
2022 gdk_window_get_visual (window)->depth,
2023 rect.left, rect.top));
2028 gdk_win32_window_get_root_coords (GdkWindow *window,
2040 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
2045 *root_x = tx + _gdk_offset_x;
2047 *root_y = ty + _gdk_offset_y;
2049 GDK_NOTE (MISC, g_print ("gdk_win32_window_get_root_coords: %p: %+d%+d %+d%+d\n",
2050 GDK_WINDOW_HWND (window),
2052 tx + _gdk_offset_x, ty + _gdk_offset_y));
2057 gdk_win32_window_restack_under (GdkWindow *window,
2058 GList *native_siblings)
2064 gdk_win32_window_restack_toplevel (GdkWindow *window,
2072 gdk_win32_window_get_root_origin (GdkWindow *window,
2078 g_return_if_fail (GDK_IS_WINDOW (window));
2080 gdk_window_get_frame_extents (window, &rect);
2088 GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %p: %+d%+d\n",
2089 GDK_WINDOW_HWND (window), rect.x, rect.y));
2093 gdk_win32_window_get_frame_extents (GdkWindow *window,
2099 g_return_if_fail (GDK_IS_WINDOW (window));
2100 g_return_if_fail (rect != NULL);
2107 if (GDK_WINDOW_DESTROYED (window))
2110 /* FIXME: window is documented to be a toplevel GdkWindow, so is it really
2111 * necessary to walk its parent chain?
2113 while (window->parent && window->parent->parent)
2114 window = window->parent;
2116 hwnd = GDK_WINDOW_HWND (window);
2117 API_CALL (GetWindowRect, (hwnd, &r));
2119 rect->x = r.left + _gdk_offset_x;
2120 rect->y = r.top + _gdk_offset_y;
2121 rect->width = r.right - r.left;
2122 rect->height = r.bottom - r.top;
2124 GDK_NOTE (MISC, g_print ("gdk_window_get_frame_extents: %p: %ldx%ld@%+ld%+ld\n",
2125 GDK_WINDOW_HWND (window),
2126 r.right - r.left, r.bottom - r.top,
2131 gdk_window_win32_get_device_state (GdkWindow *window,
2135 GdkModifierType *mask)
2139 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
2141 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
2145 return (child != NULL);
2149 _gdk_windowing_get_device_state (GdkDisplay *display,
2154 GdkModifierType *mask)
2156 g_return_if_fail (display == _gdk_display);
2159 *screen = _gdk_screen;
2161 GDK_DEVICE_GET_CLASS (device)->query_state (device,
2162 gdk_screen_get_root_window (_gdk_screen),
2170 gdk_display_warp_device (GdkDisplay *display,
2176 g_return_if_fail (display == _gdk_display);
2177 g_return_if_fail (screen == _gdk_screen);
2178 g_return_if_fail (GDK_IS_DEVICE (device));
2179 g_return_if_fail (display == gdk_device_get_display (device));
2181 GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
2185 _gdk_windowing_window_at_device_position (GdkDisplay *display,
2189 GdkModifierType *mask,
2190 gboolean get_toplevel)
2192 return GDK_DEVICE_GET_CLASS (device)->window_at_position (device, win_x, win_y, mask, get_toplevel);
2196 gdk_win32_window_get_events (GdkWindow *window)
2198 GdkWindowImplWin32 *impl;
2200 if (GDK_WINDOW_DESTROYED (window))
2203 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2205 return impl->native_event_mask;
2209 gdk_win32_window_set_events (GdkWindow *window,
2210 GdkEventMask event_mask)
2212 GdkWindowImplWin32 *impl;
2214 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2216 /* gdk_window_new() always sets the GDK_STRUCTURE_MASK, so better
2217 * set it here, too. Not that I know or remember why it is
2218 * necessary, will have to test some day.
2220 impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask;
2224 do_shape_combine_region (GdkWindow *window,
2230 GetClientRect (GDK_WINDOW_HWND (window), &rect);
2231 _gdk_win32_adjust_client_rect (window, &rect);
2233 OffsetRgn (hrgn, -rect.left, -rect.top);
2234 OffsetRgn (hrgn, x, y);
2236 /* If this is a top-level window, add the title bar to the region */
2237 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
2239 HRGN tmp = CreateRectRgn (0, 0, rect.right - rect.left, -rect.top);
2240 CombineRgn (hrgn, hrgn, tmp, RGN_OR);
2244 SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
2248 gdk_win32_window_set_override_redirect (GdkWindow *window,
2249 gboolean override_redirect)
2251 GdkWindowImplWin32 *window_impl;
2253 g_return_if_fail (GDK_IS_WINDOW (window));
2255 window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2257 window_impl->override_redirect = !!override_redirect;
2261 gdk_win32_window_set_accept_focus (GdkWindow *window,
2262 gboolean accept_focus)
2264 g_return_if_fail (GDK_IS_WINDOW (window));
2266 accept_focus = accept_focus != FALSE;
2268 if (window->accept_focus != accept_focus)
2269 window->accept_focus = accept_focus;
2273 gdk_win32_window_set_focus_on_map (GdkWindow *window,
2274 gboolean focus_on_map)
2276 g_return_if_fail (GDK_IS_WINDOW (window));
2278 focus_on_map = focus_on_map != FALSE;
2280 if (window->focus_on_map != focus_on_map)
2281 window->focus_on_map = focus_on_map;
2285 gdk_win32_window_set_icon_list (GdkWindow *window,
2288 GdkPixbuf *pixbuf, *big_pixbuf, *small_pixbuf;
2289 gint big_diff, small_diff;
2290 gint big_w, big_h, small_w, small_h;
2293 HICON small_hicon, big_hicon;
2294 GdkWindowImplWin32 *impl;
2295 gint i, big_i, small_i;
2297 g_return_if_fail (GDK_IS_WINDOW (window));
2299 if (GDK_WINDOW_DESTROYED (window))
2302 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2304 /* ideal sizes for small and large icons */
2305 big_w = GetSystemMetrics (SM_CXICON);
2306 big_h = GetSystemMetrics (SM_CYICON);
2307 small_w = GetSystemMetrics (SM_CXSMICON);
2308 small_h = GetSystemMetrics (SM_CYSMICON);
2310 /* find closest sized icons in the list */
2312 small_pixbuf = NULL;
2318 pixbuf = (GdkPixbuf*) pixbufs->data;
2319 w = gdk_pixbuf_get_width (pixbuf);
2320 h = gdk_pixbuf_get_height (pixbuf);
2322 dw = ABS (w - big_w);
2323 dh = ABS (h - big_h);
2324 diff = dw*dw + dh*dh;
2325 if (big_pixbuf == NULL || diff < big_diff)
2327 big_pixbuf = pixbuf;
2332 dw = ABS (w - small_w);
2333 dh = ABS (h - small_h);
2334 diff = dw*dw + dh*dh;
2335 if (small_pixbuf == NULL || diff < small_diff)
2337 small_pixbuf = pixbuf;
2342 pixbufs = g_list_next (pixbufs);
2346 /* Create the icons */
2347 big_hicon = _gdk_win32_pixbuf_to_hicon (big_pixbuf);
2348 small_hicon = _gdk_win32_pixbuf_to_hicon (small_pixbuf);
2351 SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_BIG,
2353 SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_SMALL,
2354 (LPARAM)small_hicon);
2356 /* Store the icons, destroying any previous icons */
2357 if (impl->hicon_big)
2358 GDI_CALL (DestroyIcon, (impl->hicon_big));
2359 impl->hicon_big = big_hicon;
2360 if (impl->hicon_small)
2361 GDI_CALL (DestroyIcon, (impl->hicon_small));
2362 impl->hicon_small = small_hicon;
2366 gdk_win32_window_set_icon_name (GdkWindow *window,
2369 /* In case I manage to confuse this again (or somebody else does):
2370 * Please note that "icon name" here really *does* mean the name or
2371 * title of an window minimized as an icon on the desktop, or in the
2372 * taskbar. It has nothing to do with the freedesktop.org icon
2376 g_return_if_fail (GDK_IS_WINDOW (window));
2378 if (GDK_WINDOW_DESTROYED (window))
2382 /* This is not the correct thing to do. We should keep both the
2383 * "normal" window title, and the icon name. When the window is
2384 * minimized, call SetWindowText() with the icon name, and when the
2385 * window is restored, with the normal window title. Also, the name
2386 * is in UTF-8, so we should do the normal conversion to either wide
2387 * chars or system codepage, and use either the W or A version of
2388 * SetWindowText(), depending on Windows version.
2390 API_CALL (SetWindowText, (GDK_WINDOW_HWND (window), name));
2395 gdk_win32_window_get_group (GdkWindow *window)
2397 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2398 g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
2400 if (GDK_WINDOW_DESTROYED (window))
2403 g_warning ("gdk_window_get_group not yet implemented");
2409 gdk_win32_window_set_group (GdkWindow *window,
2412 g_return_if_fail (GDK_IS_WINDOW (window));
2413 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2414 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
2416 if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
2419 g_warning ("gdk_window_set_group not implemented");
2423 update_single_bit (LONG *style,
2428 /* all controls the interpretation of gdk_bit -- if all is TRUE,
2429 * gdk_bit indicates whether style_bit is off; if all is FALSE, gdk
2430 * bit indicate whether style_bit is on
2432 if ((!all && gdk_bit) || (all && !gdk_bit))
2433 *style |= style_bit;
2435 *style &= ~style_bit;
2439 update_style_bits (GdkWindow *window)
2441 GdkWindowImplWin32 *impl = (GdkWindowImplWin32 *)window->impl;
2442 GdkWMDecoration decorations;
2443 LONG old_style, new_style, old_exstyle, new_exstyle;
2445 RECT rect, before, after;
2447 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
2450 old_style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2451 old_exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
2453 GetClientRect (GDK_WINDOW_HWND (window), &before);
2455 AdjustWindowRectEx (&before, old_style, FALSE, old_exstyle);
2457 new_style = old_style;
2458 new_exstyle = old_exstyle;
2460 if (window->window_type == GDK_WINDOW_TEMP)
2461 new_exstyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
2462 else if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
2463 new_exstyle |= WS_EX_TOOLWINDOW ;
2465 new_exstyle &= ~WS_EX_TOOLWINDOW;
2467 if (get_effective_window_decorations (window, &decorations))
2469 all = (decorations & GDK_DECOR_ALL);
2470 update_single_bit (&new_style, all, decorations & GDK_DECOR_BORDER, WS_BORDER);
2471 update_single_bit (&new_style, all, decorations & GDK_DECOR_RESIZEH, WS_THICKFRAME);
2472 update_single_bit (&new_style, all, decorations & GDK_DECOR_TITLE, WS_CAPTION);
2473 update_single_bit (&new_style, all, decorations & GDK_DECOR_MENU, WS_SYSMENU);
2474 update_single_bit (&new_style, all, decorations & GDK_DECOR_MINIMIZE, WS_MINIMIZEBOX);
2475 update_single_bit (&new_style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
2478 if (old_style == new_style && old_exstyle == new_exstyle )
2480 GDK_NOTE (MISC, g_print ("update_style_bits: %p: no change\n",
2481 GDK_WINDOW_HWND (window)));
2485 if (old_style != new_style)
2487 GDK_NOTE (MISC, g_print ("update_style_bits: %p: STYLE: %s => %s\n",
2488 GDK_WINDOW_HWND (window),
2489 _gdk_win32_window_style_to_string (old_style),
2490 _gdk_win32_window_style_to_string (new_style)));
2492 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, new_style);
2495 if (old_exstyle != new_exstyle)
2497 GDK_NOTE (MISC, g_print ("update_style_bits: %p: EXSTYLE: %s => %s\n",
2498 GDK_WINDOW_HWND (window),
2499 _gdk_win32_window_exstyle_to_string (old_exstyle),
2500 _gdk_win32_window_exstyle_to_string (new_exstyle)));
2502 SetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE, new_exstyle);
2505 AdjustWindowRectEx (&after, new_style, FALSE, new_exstyle);
2507 GetWindowRect (GDK_WINDOW_HWND (window), &rect);
2508 rect.left += after.left - before.left;
2509 rect.top += after.top - before.top;
2510 rect.right += after.right - before.right;
2511 rect.bottom += after.bottom - before.bottom;
2513 SetWindowPos (GDK_WINDOW_HWND (window), NULL,
2514 rect.left, rect.top,
2515 rect.right - rect.left, rect.bottom - rect.top,
2516 SWP_FRAMECHANGED | SWP_NOACTIVATE |
2517 SWP_NOREPOSITION | SWP_NOZORDER);
2522 update_single_system_menu_entry (HMENU hmenu,
2527 /* all controls the interpretation of gdk_bit -- if all is TRUE,
2528 * gdk_bit indicates whether menu entry is disabled; if all is
2529 * FALSE, gdk bit indicate whether menu entry is enabled
2531 if ((!all && gdk_bit) || (all && !gdk_bit))
2532 EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_ENABLED);
2534 EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_GRAYED);
2538 update_system_menu (GdkWindow *window)
2540 GdkWMFunction functions;
2543 if (_gdk_window_get_functions (window, &functions))
2545 HMENU hmenu = GetSystemMenu (GDK_WINDOW_HWND (window), FALSE);
2547 all = (functions & GDK_FUNC_ALL);
2548 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_RESIZE, SC_SIZE);
2549 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MOVE, SC_MOVE);
2550 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MINIMIZE, SC_MINIMIZE);
2551 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MAXIMIZE, SC_MAXIMIZE);
2552 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_CLOSE, SC_CLOSE);
2557 get_decorations_quark ()
2559 static GQuark quark = 0;
2562 quark = g_quark_from_static_string ("gdk-window-decorations");
2568 gdk_win32_window_set_decorations (GdkWindow *window,
2569 GdkWMDecoration decorations)
2571 GdkWMDecoration* decorations_copy;
2573 g_return_if_fail (GDK_IS_WINDOW (window));
2575 GDK_NOTE (MISC, g_print ("gdk_window_set_decorations: %p: %s %s%s%s%s%s%s\n",
2576 GDK_WINDOW_HWND (window),
2577 (decorations & GDK_DECOR_ALL ? "clearing" : "setting"),
2578 (decorations & GDK_DECOR_BORDER ? "BORDER " : ""),
2579 (decorations & GDK_DECOR_RESIZEH ? "RESIZEH " : ""),
2580 (decorations & GDK_DECOR_TITLE ? "TITLE " : ""),
2581 (decorations & GDK_DECOR_MENU ? "MENU " : ""),
2582 (decorations & GDK_DECOR_MINIMIZE ? "MINIMIZE " : ""),
2583 (decorations & GDK_DECOR_MAXIMIZE ? "MAXIMIZE " : "")));
2585 decorations_copy = g_malloc (sizeof (GdkWMDecoration));
2586 *decorations_copy = decorations;
2587 g_object_set_qdata_full (G_OBJECT (window), get_decorations_quark (), decorations_copy, g_free);
2589 update_style_bits (window);
2593 gdk_win32_window_get_decorations (GdkWindow *window,
2594 GdkWMDecoration *decorations)
2596 GdkWMDecoration* decorations_set;
2598 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2600 decorations_set = g_object_get_qdata (G_OBJECT (window), get_decorations_quark ());
2601 if (decorations_set)
2602 *decorations = *decorations_set;
2604 return (decorations_set != NULL);
2608 get_functions_quark ()
2610 static GQuark quark = 0;
2613 quark = g_quark_from_static_string ("gdk-window-functions");
2619 gdk_win32_window_set_functions (GdkWindow *window,
2620 GdkWMFunction functions)
2622 GdkWMFunction* functions_copy;
2624 g_return_if_fail (GDK_IS_WINDOW (window));
2626 GDK_NOTE (MISC, g_print ("gdk_window_set_functions: %p: %s %s%s%s%s%s\n",
2627 GDK_WINDOW_HWND (window),
2628 (functions & GDK_FUNC_ALL ? "clearing" : "setting"),
2629 (functions & GDK_FUNC_RESIZE ? "RESIZE " : ""),
2630 (functions & GDK_FUNC_MOVE ? "MOVE " : ""),
2631 (functions & GDK_FUNC_MINIMIZE ? "MINIMIZE " : ""),
2632 (functions & GDK_FUNC_MAXIMIZE ? "MAXIMIZE " : ""),
2633 (functions & GDK_FUNC_CLOSE ? "CLOSE " : "")));
2635 functions_copy = g_malloc (sizeof (GdkWMFunction));
2636 *functions_copy = functions;
2637 g_object_set_qdata_full (G_OBJECT (window), get_functions_quark (), functions_copy, g_free);
2639 update_system_menu (window);
2643 _gdk_window_get_functions (GdkWindow *window,
2644 GdkWMFunction *functions)
2646 GdkWMFunction* functions_set;
2648 functions_set = g_object_get_qdata (G_OBJECT (window), get_functions_quark ());
2650 *functions = *functions_set;
2652 return (functions_set != NULL);
2656 gdk_win32_window_set_static_gravities (GdkWindow *window,
2657 gboolean use_static)
2659 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2665 gdk_win32_window_begin_resize_drag (GdkWindow *window,
2675 g_return_if_fail (GDK_IS_WINDOW (window));
2677 if (GDK_WINDOW_DESTROYED (window))
2680 /* Tell Windows to start interactively resizing the window by pretending that
2681 * the left pointer button was clicked in the suitable edge or corner. This
2682 * will only work if the button is down when this function is called, and
2683 * will only work with button 1 (left), since Windows only allows window
2684 * dragging using the left mouse button.
2689 /* Must break the automatic grab that occured when the button was
2690 * pressed, otherwise it won't work.
2692 gdk_display_pointer_ungrab (_gdk_display, 0);
2696 case GDK_WINDOW_EDGE_NORTH_WEST:
2697 winedge = HTTOPLEFT;
2700 case GDK_WINDOW_EDGE_NORTH:
2704 case GDK_WINDOW_EDGE_NORTH_EAST:
2705 winedge = HTTOPRIGHT;
2708 case GDK_WINDOW_EDGE_WEST:
2712 case GDK_WINDOW_EDGE_EAST:
2716 case GDK_WINDOW_EDGE_SOUTH_WEST:
2717 winedge = HTBOTTOMLEFT;
2720 case GDK_WINDOW_EDGE_SOUTH:
2724 case GDK_WINDOW_EDGE_SOUTH_EAST:
2726 winedge = HTBOTTOMRIGHT;
2730 DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, winedge,
2731 MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2735 gdk_win32_window_begin_move_drag (GdkWindow *window,
2742 g_return_if_fail (GDK_IS_WINDOW (window));
2744 if (GDK_WINDOW_DESTROYED (window))
2747 /* Tell Windows to start interactively moving the window by pretending that
2748 * the left pointer button was clicked in the titlebar. This will only work
2749 * if the button is down when this function is called, and will only work
2750 * with button 1 (left), since Windows only allows window dragging using the
2751 * left mouse button.
2756 /* Must break the automatic grab that occured when the button was pressed,
2757 * otherwise it won't work.
2759 gdk_display_pointer_ungrab (_gdk_display, 0);
2761 DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, HTCAPTION,
2762 MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2767 * Setting window states
2770 gdk_win32_window_iconify (GdkWindow *window)
2772 HWND old_active_window;
2774 g_return_if_fail (GDK_IS_WINDOW (window));
2776 if (GDK_WINDOW_DESTROYED (window))
2779 GDK_NOTE (MISC, g_print ("gdk_window_iconify: %p: %s\n",
2780 GDK_WINDOW_HWND (window),
2781 _gdk_win32_window_state_to_string (window->state)));
2783 if (GDK_WINDOW_IS_MAPPED (window))
2785 old_active_window = GetActiveWindow ();
2786 ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
2787 if (old_active_window != GDK_WINDOW_HWND (window))
2788 SetActiveWindow (old_active_window);
2792 gdk_synthesize_window_state (window,
2794 GDK_WINDOW_STATE_ICONIFIED);
2799 gdk_win32_window_deiconify (GdkWindow *window)
2801 g_return_if_fail (GDK_IS_WINDOW (window));
2803 if (GDK_WINDOW_DESTROYED (window))
2806 GDK_NOTE (MISC, g_print ("gdk_window_deiconify: %p: %s\n",
2807 GDK_WINDOW_HWND (window),
2808 _gdk_win32_window_state_to_string (window->state)));
2810 if (GDK_WINDOW_IS_MAPPED (window))
2812 show_window_internal (window, GDK_WINDOW_IS_MAPPED (window), TRUE);
2816 gdk_synthesize_window_state (window,
2817 GDK_WINDOW_STATE_ICONIFIED,
2823 gdk_win32_window_stick (GdkWindow *window)
2825 g_return_if_fail (GDK_IS_WINDOW (window));
2827 if (GDK_WINDOW_DESTROYED (window))
2830 /* FIXME: Do something? */
2834 gdk_win32_window_unstick (GdkWindow *window)
2836 g_return_if_fail (GDK_IS_WINDOW (window));
2838 if (GDK_WINDOW_DESTROYED (window))
2841 /* FIXME: Do something? */
2845 gdk_win32_window_maximize (GdkWindow *window)
2847 g_return_if_fail (GDK_IS_WINDOW (window));
2849 if (GDK_WINDOW_DESTROYED (window))
2852 GDK_NOTE (MISC, g_print ("gdk_window_maximize: %p: %s\n",
2853 GDK_WINDOW_HWND (window),
2854 _gdk_win32_window_state_to_string (window->state)));
2856 if (GDK_WINDOW_IS_MAPPED (window))
2857 ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
2859 gdk_synthesize_window_state (window,
2861 GDK_WINDOW_STATE_MAXIMIZED);
2865 gdk_win32_window_unmaximize (GdkWindow *window)
2867 g_return_if_fail (GDK_IS_WINDOW (window));
2869 if (GDK_WINDOW_DESTROYED (window))
2872 GDK_NOTE (MISC, g_print ("gdk_window_unmaximize: %p: %s\n",
2873 GDK_WINDOW_HWND (window),
2874 _gdk_win32_window_state_to_string (window->state)));
2876 if (GDK_WINDOW_IS_MAPPED (window))
2877 ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
2879 gdk_synthesize_window_state (window,
2880 GDK_WINDOW_STATE_MAXIMIZED,
2885 gdk_win32_window_fullscreen (GdkWindow *window)
2887 gint x, y, width, height;
2892 g_return_if_fail (GDK_IS_WINDOW (window));
2894 fi = g_new (FullscreenInfo, 1);
2896 if (!GetWindowRect (GDK_WINDOW_HWND (window), &(fi->r)))
2900 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2902 monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
2903 mi.cbSize = sizeof (mi);
2904 if (monitor && GetMonitorInfo (monitor, &mi))
2906 x = mi.rcMonitor.left;
2907 y = mi.rcMonitor.top;
2908 width = mi.rcMonitor.right - x;
2909 height = mi.rcMonitor.bottom - y;
2914 width = GetSystemMetrics (SM_CXSCREEN);
2915 height = GetSystemMetrics (SM_CYSCREEN);
2918 /* remember for restoring */
2919 fi->hint_flags = impl->hint_flags;
2920 impl->hint_flags &= ~GDK_HINT_MAX_SIZE;
2921 g_object_set_data (G_OBJECT (window), "fullscreen-info", fi);
2922 fi->style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2924 /* Send state change before configure event */
2925 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2927 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
2928 (fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP);
2930 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
2931 x, y, width, height,
2932 SWP_NOCOPYBITS | SWP_SHOWWINDOW));
2937 gdk_win32_window_unfullscreen (GdkWindow *window)
2941 g_return_if_fail (GDK_IS_WINDOW (window));
2943 fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
2946 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2948 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
2950 impl->hint_flags = fi->hint_flags;
2951 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, fi->style);
2952 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_NOTOPMOST,
2953 fi->r.left, fi->r.top,
2954 fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
2955 SWP_NOCOPYBITS | SWP_SHOWWINDOW));
2957 g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
2959 update_style_bits (window);
2964 gdk_win32_window_set_keep_above (GdkWindow *window,
2967 g_return_if_fail (GDK_IS_WINDOW (window));
2969 if (GDK_WINDOW_DESTROYED (window))
2972 GDK_NOTE (MISC, g_print ("gdk_window_set_keep_above: %p: %s\n",
2973 GDK_WINDOW_HWND (window),
2974 setting ? "YES" : "NO"));
2976 if (GDK_WINDOW_IS_MAPPED (window))
2978 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
2979 setting ? HWND_TOPMOST : HWND_NOTOPMOST,
2981 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
2984 gdk_synthesize_window_state (window,
2985 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
2986 setting ? GDK_WINDOW_STATE_ABOVE : 0);
2990 gdk_win32_window_set_keep_below (GdkWindow *window,
2993 g_return_if_fail (GDK_IS_WINDOW (window));
2995 if (GDK_WINDOW_DESTROYED (window))
2998 GDK_NOTE (MISC, g_print ("gdk_window_set_keep_below: %p: %s\n",
2999 GDK_WINDOW_HWND (window),
3000 setting ? "YES" : "NO"));
3002 if (GDK_WINDOW_IS_MAPPED (window))
3004 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
3005 setting ? HWND_BOTTOM : HWND_NOTOPMOST,
3007 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
3010 gdk_synthesize_window_state (window,
3011 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
3012 setting ? GDK_WINDOW_STATE_BELOW : 0);
3016 gdk_win32_window_focus (GdkWindow *window,
3019 g_return_if_fail (GDK_IS_WINDOW (window));
3021 if (GDK_WINDOW_DESTROYED (window))
3024 GDK_NOTE (MISC, g_print ("gdk_window_focus: %p: %s\n",
3025 GDK_WINDOW_HWND (window),
3026 _gdk_win32_window_state_to_string (window->state)));
3028 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
3029 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMAXIMIZED);
3031 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
3032 SetFocus (GDK_WINDOW_HWND (window));
3036 gdk_win32_window_set_modal_hint (GdkWindow *window,
3039 g_return_if_fail (GDK_IS_WINDOW (window));
3041 if (GDK_WINDOW_DESTROYED (window))
3044 GDK_NOTE (MISC, g_print ("gdk_window_set_modal_hint: %p: %s\n",
3045 GDK_WINDOW_HWND (window),
3046 modal ? "YES" : "NO"));
3048 if (modal == window->modal_hint)
3051 window->modal_hint = modal;
3054 /* Not sure about this one.. -- Cody */
3055 if (GDK_WINDOW_IS_MAPPED (window))
3056 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
3057 modal ? HWND_TOPMOST : HWND_NOTOPMOST,
3059 SWP_NOMOVE | SWP_NOSIZE));
3064 _gdk_push_modal_window (window);
3065 gdk_window_raise (window);
3069 _gdk_remove_modal_window (window);
3076 gdk_win32_window_set_skip_taskbar_hint (GdkWindow *window,
3077 gboolean skips_taskbar)
3079 static GdkWindow *owner = NULL;
3082 g_return_if_fail (GDK_IS_WINDOW (window));
3084 GDK_NOTE (MISC, g_print ("gdk_window_set_skip_taskbar_hint: %p: %s, doing nothing\n",
3085 GDK_WINDOW_HWND (window),
3086 skips_taskbar ? "YES" : "NO"));
3088 // ### TODO: Need to figure out what to do here.
3096 wa.window_type = GDK_WINDOW_TEMP;
3097 wa.wclass = GDK_INPUT_OUTPUT;
3098 wa.width = wa.height = 1;
3100 owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
3104 SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_WINDOW_HWND (owner));
3106 #if 0 /* Should we also turn off the minimize and maximize buttons? */
3107 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
3108 GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE) & ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU));
3110 SetWindowPos (GDK_WINDOW_HWND (window), NULL,
3112 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
3113 SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
3118 SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, 0);
3123 gdk_win32_window_set_skip_pager_hint (GdkWindow *window,
3124 gboolean skips_pager)
3126 g_return_if_fail (GDK_IS_WINDOW (window));
3128 GDK_NOTE (MISC, g_print ("gdk_window_set_skip_pager_hint: %p: %s, doing nothing\n",
3129 GDK_WINDOW_HWND (window),
3130 skips_pager ? "YES" : "NO"));
3134 gdk_win32_window_set_type_hint (GdkWindow *window,
3135 GdkWindowTypeHint hint)
3137 g_return_if_fail (GDK_IS_WINDOW (window));
3139 if (GDK_WINDOW_DESTROYED (window))
3144 static GEnumClass *class = NULL;
3146 class = g_type_class_ref (GDK_TYPE_WINDOW_TYPE_HINT);
3147 g_print ("gdk_window_set_type_hint: %p: %s\n",
3148 GDK_WINDOW_HWND (window),
3149 g_enum_get_value (class, hint)->value_name);
3152 ((GdkWindowImplWin32 *)window->impl)->type_hint = hint;
3154 update_style_bits (window);
3157 static GdkWindowTypeHint
3158 gdk_win32_window_get_type_hint (GdkWindow *window)
3160 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
3162 if (GDK_WINDOW_DESTROYED (window))
3163 return GDK_WINDOW_TYPE_HINT_NORMAL;
3165 return GDK_WINDOW_IMPL_WIN32 (window->impl)->type_hint;
3169 cairo_region_to_hrgn (const cairo_region_t *region,
3176 cairo_rectangle_int_t r;
3177 const int nrects = cairo_region_num_rectangles (region);
3179 sizeof (RGNDATAHEADER) + (sizeof (RECT) * nrects);
3182 rgndata = g_malloc (nbytes);
3183 rgndata->rdh.dwSize = sizeof (RGNDATAHEADER);
3184 rgndata->rdh.iType = RDH_RECTANGLES;
3185 rgndata->rdh.nCount = rgndata->rdh.nRgnSize = 0;
3186 SetRect (&rgndata->rdh.rcBound,
3187 G_MAXLONG, G_MAXLONG, G_MINLONG, G_MINLONG);
3189 for (i = 0; i < nrects; i++)
3191 rect = ((RECT *) rgndata->Buffer) + rgndata->rdh.nCount++;
3193 cairo_region_get_rectangle (region, i, &r);
3194 rect->left = r.x + x_origin;
3195 rect->right = rect->left + r.width;
3196 rect->top = r.y + y_origin;
3197 rect->bottom = rect->top + r.height;
3199 if (rect->left < rgndata->rdh.rcBound.left)
3200 rgndata->rdh.rcBound.left = rect->left;
3201 if (rect->right > rgndata->rdh.rcBound.right)
3202 rgndata->rdh.rcBound.right = rect->right;
3203 if (rect->top < rgndata->rdh.rcBound.top)
3204 rgndata->rdh.rcBound.top = rect->top;
3205 if (rect->bottom > rgndata->rdh.rcBound.bottom)
3206 rgndata->rdh.rcBound.bottom = rect->bottom;
3208 if ((hrgn = ExtCreateRegion (NULL, nbytes, rgndata)) == NULL)
3209 WIN32_API_FAILED ("ExtCreateRegion");
3217 gdk_win32_window_shape_combine_region (GdkWindow *window,
3218 const cairo_region_t *shape_region,
3222 if (GDK_WINDOW_DESTROYED (window))
3227 GDK_NOTE (MISC, g_print ("gdk_win32_window_shape_combine_region: %p: none\n",
3228 GDK_WINDOW_HWND (window)));
3229 SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
3235 hrgn = cairo_region_to_hrgn (shape_region, 0, 0);
3237 GDK_NOTE (MISC, g_print ("gdk_win32_window_shape_combine_region: %p: %p\n",
3238 GDK_WINDOW_HWND (window),
3241 do_shape_combine_region (window, hrgn, offset_x, offset_y);
3246 gdk_win32_window_lookup_for_display (GdkDisplay *display,
3249 g_return_val_if_fail (display == _gdk_display, NULL);
3251 return (GdkWindow*) gdk_win32_handle_table_lookup (anid);
3255 gdk_win32_window_enable_synchronized_configure (GdkWindow *window)
3257 /* nothing - no window manager to cooperate with */
3261 gdk_win32_window_configure_finished (GdkWindow *window)
3263 /* nothing - no window manager to cooperate with */
3267 gdk_win32_window_set_opacity (GdkWindow *window,
3271 typedef BOOL (*PFN_SetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
3272 PFN_SetLayeredWindowAttributes setLayeredWindowAttributes = NULL;
3274 g_return_if_fail (GDK_IS_WINDOW (window));
3275 g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
3277 if (GDK_WINDOW_DESTROYED (window))
3282 else if (opacity > 1)
3285 exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
3287 if (!(exstyle & WS_EX_LAYERED))
3288 SetWindowLong (GDK_WINDOW_HWND (window),
3290 exstyle | WS_EX_LAYERED);
3292 setLayeredWindowAttributes =
3293 (PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes");
3295 if (setLayeredWindowAttributes)
3297 API_CALL (setLayeredWindowAttributes, (GDK_WINDOW_HWND (window),
3304 static cairo_region_t *
3305 gdk_win32_window_get_shape (GdkWindow *window)
3307 HRGN hrgn = CreateRectRgn (0, 0, 0, 0);
3308 int type = GetWindowRgn (GDK_WINDOW_HWND (window), hrgn);
3310 if (type == SIMPLEREGION || type == COMPLEXREGION)
3312 cairo_region_t *region = _gdk_win32_hrgn_to_region (hrgn);
3314 DeleteObject (hrgn);
3322 _gdk_win32_window_queue_antiexpose (GdkWindow *window,
3323 cairo_region_t *area)
3325 HRGN hrgn = cairo_region_to_hrgn (area, 0, 0);
3327 GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
3328 GDK_WINDOW_HWND (window),
3329 _gdk_win32_cairo_region_to_string (area)));
3331 ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
3333 DeleteObject (hrgn);
3338 /* Gets called from gdwindow.c(do_move_region_bits_on_impl)
3339 * and got tested with testgtk::big_window. Given the previous,
3340 * untested implementation this one looks much too simple ;)
3343 _gdk_win32_window_translate (GdkWindow *window,
3344 cairo_region_t *area, /* In impl window coords */
3348 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
3349 GdkRectangle extents;
3351 HRGN hrgn, area_hrgn;
3355 /* Note: This is the destination area, not the source, and
3356 it has been moved by dx, dy from the source area */
3357 area_hrgn = cairo_region_to_hrgn (area, 0, 0);
3359 /* First we copy any outstanding invalid areas in the
3360 source area to the new position in the destination area */
3361 hrgn = CreateRectRgn (0, 0, 0, 0);
3362 ret = GetUpdateRgn (GDK_WINDOW_HWND (window), hrgn, FALSE);
3364 WIN32_API_FAILED ("GetUpdateRgn");
3365 else if (ret != NULLREGION)
3367 /* Convert the source invalid region as it would be copied */
3368 OffsetRgn (hrgn, dx, dy);
3369 /* Keep what intersects the copy destination area */
3370 ret = CombineRgn (hrgn, hrgn, area_hrgn, RGN_AND);
3371 /* And invalidate it */
3373 WIN32_API_FAILED ("CombineRgn");
3374 else if (ret != NULLREGION)
3375 API_CALL (InvalidateRgn, (GDK_WINDOW_HWND (window), hrgn, TRUE));
3378 /* Then we copy the bits, invalidating whatever is copied from
3379 otherwise invisible areas */
3381 hdc = _gdk_win32_impl_acquire_dc (impl);
3383 /* Clip hdc to target region */
3384 API_CALL (SelectClipRgn, (hdc, area_hrgn));
3386 cairo_region_get_extents (area, &extents);
3388 rect.left = MIN (extents.x, extents.x - dx);
3389 rect.top = MIN (extents.y, extents.y - dy);
3390 rect.right = MAX (extents.x + extents.width, extents.x - dx + extents.width);
3391 rect.bottom = MAX (extents.y + extents.height, extents.y - dy + extents.height);
3393 SetRectRgn (hrgn, 0, 0, 0, 0);
3395 if (!ScrollDC (hdc, dx, dy, &rect, NULL, hrgn, NULL))
3396 WIN32_GDI_FAILED ("ScrollDC");
3397 else if (!InvalidateRgn (GDK_WINDOW_HWND (window), hrgn, FALSE))
3398 WIN32_GDI_FAILED ("InvalidateRgn");
3400 /* Unset hdc clip region */
3401 API_CALL (SelectClipRgn, (hdc, NULL));
3403 _gdk_win32_impl_release_dc (impl);
3405 if (!DeleteObject (hrgn))
3406 WIN32_GDI_FAILED ("DeleteObject");
3408 if (!DeleteObject (area_hrgn))
3409 WIN32_GDI_FAILED ("DeleteObject");
3413 gdk_win32_input_shape_combine_region (GdkWindow *window,
3414 const cairo_region_t *shape_region,
3418 if (GDK_WINDOW_DESTROYED (window))
3420 /* CHECK: are these really supposed to be the same? */
3421 gdk_win32_window_shape_combine_region (window, shape_region, offset_x, offset_y);
3425 gdk_win32_window_process_updates_recurse (GdkWindow *window,
3426 cairo_region_t *region)
3428 _gdk_window_process_updates_recurse (window, region);
3432 gdk_win32_window_is_win32 (GdkWindow *window)
3434 return GDK_WINDOW_IS_WIN32 (window);
3438 * _gdk_win32_acquire_dc
3439 * @impl: a Win32 #GdkWindowImplWin32 implementation
3441 * Gets a DC with the given drawable selected into it.
3443 * Return value: The DC, on success. Otherwise
3444 * %NULL. If this function succeeded
3445 * _gdk_win32_impl_release_dc() must be called
3446 * release the DC when you are done using it.
3449 _gdk_win32_impl_acquire_dc (GdkWindowImplWin32 *impl)
3451 if (GDK_IS_WINDOW_IMPL_WIN32 (impl) &&
3452 GDK_WINDOW_DESTROYED (impl->wrapper))
3457 impl->hdc = GetDC (impl->handle);
3459 WIN32_GDI_FAILED ("GetDC");
3474 * _gdk_win32_impl_release_dc
3475 * @impl: a Win32 #GdkWindowImplWin32 implementation
3477 * Releases the reference count for the DC
3478 * from _gdk_win32_impl_acquire_dc()
3481 _gdk_win32_impl_release_dc (GdkWindowImplWin32 *impl)
3483 g_return_if_fail (impl->hdc_count > 0);
3486 if (impl->hdc_count == 0)
3488 if (impl->saved_dc_bitmap)
3490 GDI_CALL (SelectObject, (impl->hdc, impl->saved_dc_bitmap));
3491 impl->saved_dc_bitmap = NULL;
3496 GDI_CALL (ReleaseDC, (impl->handle, impl->hdc));
3503 gdk_win32_window_get_impl_hwnd (GdkWindow *window)
3505 if (GDK_WINDOW_IS_WIN32 (window))
3506 return GDK_WINDOW_HWND (window);
3511 gdk_win32_cairo_surface_destroy (void *data)
3513 GdkWindowImplWin32 *impl = data;
3515 _gdk_win32_impl_release_dc (impl);
3516 impl->cairo_surface = NULL;
3519 static cairo_surface_t *
3520 gdk_win32_ref_cairo_surface (GdkWindow *window)
3522 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
3524 if (GDK_IS_WINDOW_IMPL_WIN32 (impl) &&
3525 GDK_WINDOW_DESTROYED (impl->wrapper))
3528 if (!impl->cairo_surface)
3530 HDC hdc = _gdk_win32_impl_acquire_dc (impl);
3534 impl->cairo_surface = cairo_win32_surface_create (hdc);
3536 cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
3537 impl, gdk_win32_cairo_surface_destroy);
3540 cairo_surface_reference (impl->cairo_surface);
3542 return impl->cairo_surface;
3546 gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
3548 GObjectClass *object_class = G_OBJECT_CLASS (klass);
3549 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
3551 parent_class = g_type_class_peek_parent (klass);
3553 object_class->finalize = gdk_window_impl_win32_finalize;
3555 impl_class->ref_cairo_surface = gdk_win32_ref_cairo_surface;
3557 impl_class->show = gdk_win32_window_show;
3558 impl_class->hide = gdk_win32_window_hide;
3559 impl_class->withdraw = gdk_win32_window_withdraw;
3560 impl_class->set_events = gdk_win32_window_set_events;
3561 impl_class->get_events = gdk_win32_window_get_events;
3562 impl_class->raise = gdk_win32_window_raise;
3563 impl_class->lower = gdk_win32_window_lower;
3564 impl_class->restack_under = gdk_win32_window_restack_under;
3565 impl_class->restack_toplevel = gdk_win32_window_restack_toplevel;
3566 impl_class->move_resize = gdk_win32_window_move_resize;
3567 impl_class->set_background = gdk_win32_window_set_background;
3568 impl_class->reparent = gdk_win32_window_reparent;
3569 impl_class->set_device_cursor = gdk_win32_window_set_device_cursor;
3570 impl_class->get_geometry = gdk_win32_window_get_geometry;
3571 impl_class->get_device_state = gdk_window_win32_get_device_state;
3572 impl_class->get_root_coords = gdk_win32_window_get_root_coords;
3574 impl_class->shape_combine_region = gdk_win32_window_shape_combine_region;
3575 impl_class->input_shape_combine_region = gdk_win32_input_shape_combine_region;
3576 impl_class->set_static_gravities = gdk_win32_window_set_static_gravities;
3577 impl_class->queue_antiexpose = _gdk_win32_window_queue_antiexpose;
3578 impl_class->translate = _gdk_win32_window_translate;
3579 impl_class->destroy = gdk_win32_window_destroy;
3580 impl_class->destroy_foreign = gdk_win32_window_destroy_foreign;
3581 impl_class->resize_cairo_surface = gdk_win32_window_resize_cairo_surface;
3582 impl_class->get_shape = gdk_win32_window_get_shape;
3583 //FIXME?: impl_class->get_input_shape = gdk_win32_window_get_input_shape;
3585 //impl_class->beep = gdk_x11_window_beep;
3587 impl_class->focus = gdk_win32_window_focus;
3588 impl_class->set_type_hint = gdk_win32_window_set_type_hint;
3589 impl_class->get_type_hint = gdk_win32_window_get_type_hint;
3590 impl_class->set_modal_hint = gdk_win32_window_set_modal_hint;
3591 impl_class->set_skip_taskbar_hint = gdk_win32_window_set_skip_taskbar_hint;
3592 impl_class->set_skip_pager_hint = gdk_win32_window_set_skip_pager_hint;
3593 impl_class->set_urgency_hint = gdk_win32_window_set_urgency_hint;
3594 impl_class->set_geometry_hints = gdk_win32_window_set_geometry_hints;
3595 impl_class->set_title = gdk_win32_window_set_title;
3596 impl_class->set_role = gdk_win32_window_set_role;
3597 //impl_class->set_startup_id = gdk_x11_window_set_startup_id;
3598 impl_class->set_transient_for = gdk_win32_window_set_transient_for;
3599 impl_class->get_root_origin = gdk_win32_window_get_root_origin;
3600 impl_class->get_frame_extents = gdk_win32_window_get_frame_extents;
3601 impl_class->set_override_redirect = gdk_win32_window_set_override_redirect;
3602 impl_class->set_accept_focus = gdk_win32_window_set_accept_focus;
3603 impl_class->set_focus_on_map = gdk_win32_window_set_focus_on_map;
3604 impl_class->set_icon_list = gdk_win32_window_set_icon_list;
3605 impl_class->set_icon_name = gdk_win32_window_set_icon_name;
3606 impl_class->iconify = gdk_win32_window_iconify;
3607 impl_class->deiconify = gdk_win32_window_deiconify;
3608 impl_class->stick = gdk_win32_window_stick;
3609 impl_class->unstick = gdk_win32_window_unstick;
3610 impl_class->maximize = gdk_win32_window_maximize;
3611 impl_class->unmaximize = gdk_win32_window_unmaximize;
3612 impl_class->fullscreen = gdk_win32_window_fullscreen;
3613 impl_class->unfullscreen = gdk_win32_window_unfullscreen;
3614 impl_class->set_keep_above = gdk_win32_window_set_keep_above;
3615 impl_class->set_keep_below = gdk_win32_window_set_keep_below;
3616 impl_class->get_group = gdk_win32_window_get_group;
3617 impl_class->set_group = gdk_win32_window_set_group;
3618 impl_class->set_decorations = gdk_win32_window_set_decorations;
3619 impl_class->get_decorations = gdk_win32_window_get_decorations;
3620 impl_class->set_functions = gdk_win32_window_set_functions;
3622 impl_class->begin_resize_drag = gdk_win32_window_begin_resize_drag;
3623 impl_class->begin_move_drag = gdk_win32_window_begin_move_drag;
3624 impl_class->enable_synchronized_configure = gdk_win32_window_enable_synchronized_configure;
3625 impl_class->configure_finished = gdk_win32_window_configure_finished;
3626 impl_class->set_opacity = gdk_win32_window_set_opacity;
3627 //impl_class->set_composited = gdk_win32_window_set_composited;
3628 impl_class->destroy_notify = gdk_win32_window_destroy_notify;
3629 impl_class->get_drag_protocol = _gdk_win32_window_get_drag_protocol;
3630 impl_class->register_dnd = _gdk_win32_window_register_dnd;
3631 impl_class->drag_begin = _gdk_win32_window_drag_begin;
3632 impl_class->process_updates_recurse = gdk_win32_window_process_updates_recurse;
3633 //? impl_class->sync_rendering = _gdk_win32_window_sync_rendering;
3634 impl_class->simulate_key = _gdk_win32_window_simulate_key;
3635 impl_class->simulate_button = _gdk_win32_window_simulate_button;
3636 impl_class->get_property = _gdk_win32_window_get_property;
3637 impl_class->change_property = _gdk_win32_window_change_property;
3638 impl_class->delete_property = _gdk_win32_window_delete_property;
3642 gdk_win32_window_get_handle (GdkWindow *window)
3644 /* Try to ensure the window has a native window */
3645 if (!_gdk_window_has_impl (window))
3646 gdk_window_ensure_native (window);
3648 if (!GDK_WINDOW_IS_WIN32 (window))
3650 g_warning (G_STRLOC " window is not a native Win32 window");
3654 return GDK_WINDOW_HWND (window);