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;
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 (((window->state & GDK_WINDOW_STATE_ABOVE) &&
1148 !(exstyle & WS_EX_TOPMOST)) ||
1149 (!(window->state & GDK_WINDOW_STATE_ABOVE) &&
1150 (exstyle & WS_EX_TOPMOST)))
1152 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
1153 (window->state & GDK_WINDOW_STATE_ABOVE)?HWND_TOPMOST:HWND_NOTOPMOST,
1155 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
1160 gdk_win32_window_show (GdkWindow *window,
1161 gboolean already_mapped)
1163 show_window_internal (window, FALSE, FALSE);
1167 gdk_win32_window_hide (GdkWindow *window)
1169 if (window->destroyed)
1172 GDK_NOTE (MISC, g_print ("gdk_win32_window_hide: %p: %s\n",
1173 GDK_WINDOW_HWND (window),
1174 _gdk_win32_window_state_to_string (window->state)));
1176 if (GDK_WINDOW_IS_MAPPED (window))
1177 gdk_synthesize_window_state (window,
1179 GDK_WINDOW_STATE_WITHDRAWN);
1181 _gdk_window_clear_update_area (window);
1183 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1184 ShowOwnedPopups (GDK_WINDOW_HWND (window), FALSE);
1186 if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
1188 SetWindowPos (GDK_WINDOW_HWND (window), HWND_BOTTOM,
1190 SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
1194 ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
1199 gdk_win32_window_withdraw (GdkWindow *window)
1201 if (window->destroyed)
1204 GDK_NOTE (MISC, g_print ("gdk_win32_window_withdraw: %p: %s\n",
1205 GDK_WINDOW_HWND (window),
1206 _gdk_win32_window_state_to_string (window->state)));
1208 gdk_window_hide (window); /* ??? */
1212 gdk_win32_window_move (GdkWindow *window,
1215 GdkWindowImplWin32 *impl;
1217 g_return_if_fail (GDK_IS_WINDOW (window));
1219 if (GDK_WINDOW_DESTROYED (window))
1222 GDK_NOTE (MISC, g_print ("gdk_win32_window_move: %p: %+d%+d\n",
1223 GDK_WINDOW_HWND (window), x, y));
1225 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1227 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1230 /* Don't check GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD.
1231 * Foreign windows (another app's windows) might be children of our
1232 * windows! Especially in the case of gtkplug/socket.
1234 if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1236 _gdk_window_move_resize_child (window, x, y, window->width, window->height);
1242 get_outer_rect (window, window->width, window->height, &outer_rect);
1244 adjust_for_gravity_hints (window, &outer_rect, &x, &y);
1246 GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,0,0,"
1247 "NOACTIVATE|NOSIZE|NOZORDER)\n",
1248 GDK_WINDOW_HWND (window),
1249 x - _gdk_offset_x, y - _gdk_offset_y));
1251 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1252 x - _gdk_offset_x, y - _gdk_offset_y, 0, 0,
1253 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
1258 gdk_win32_window_resize (GdkWindow *window,
1259 gint width, gint height)
1261 GdkWindowImplWin32 *impl;
1263 g_return_if_fail (GDK_IS_WINDOW (window));
1265 if (GDK_WINDOW_DESTROYED (window))
1273 GDK_NOTE (MISC, g_print ("gdk_win32_window_resize: %p: %dx%d\n",
1274 GDK_WINDOW_HWND (window), width, height));
1276 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1278 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1281 if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1283 _gdk_window_move_resize_child (window, window->x, window->y, width, height);
1289 get_outer_rect (window, width, height, &outer_rect);
1291 GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,0,0,%ld,%ld,"
1292 "NOACTIVATE|NOMOVE|NOZORDER)\n",
1293 GDK_WINDOW_HWND (window),
1294 outer_rect.right - outer_rect.left,
1295 outer_rect.bottom - outer_rect.top));
1297 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1299 outer_rect.right - outer_rect.left,
1300 outer_rect.bottom - outer_rect.top,
1301 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER));
1302 window->resize_count += 1;
1307 gdk_win32_window_move_resize_internal (GdkWindow *window,
1313 GdkWindowImplWin32 *impl;
1315 g_return_if_fail (GDK_IS_WINDOW (window));
1317 if (GDK_WINDOW_DESTROYED (window))
1325 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1327 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1330 GDK_NOTE (MISC, g_print ("gdk_win32_window_move_resize: %p: %dx%d@%+d%+d\n",
1331 GDK_WINDOW_HWND (window),
1332 width, height, x, y));
1334 if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1336 _gdk_window_move_resize_child (window, x, y, width, height);
1342 get_outer_rect (window, width, height, &outer_rect);
1344 adjust_for_gravity_hints (window, &outer_rect, &x, &y);
1346 GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%ld,%ld,"
1347 "NOACTIVATE|NOZORDER)\n",
1348 GDK_WINDOW_HWND (window),
1349 x - _gdk_offset_x, y - _gdk_offset_y,
1350 outer_rect.right - outer_rect.left,
1351 outer_rect.bottom - outer_rect.top));
1353 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1354 x - _gdk_offset_x, y - _gdk_offset_y,
1355 outer_rect.right - outer_rect.left,
1356 outer_rect.bottom - outer_rect.top,
1357 SWP_NOACTIVATE | SWP_NOZORDER));
1362 gdk_win32_window_move_resize (GdkWindow *window,
1369 GdkWindowImplWin32 *window_impl;
1371 window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1372 window_impl->inhibit_configure = TRUE;
1374 /* We ignore changes to the window being moved or resized by the
1375 user, as we don't want to fight the user */
1376 if (GDK_WINDOW_HWND (window) == _modal_move_resize_window)
1379 if (with_move && (width < 0 && height < 0))
1381 gdk_win32_window_move (window, x, y);
1387 gdk_win32_window_move_resize_internal (window, x, y, width, height);
1391 gdk_win32_window_resize (window, width, height);
1396 window_impl->inhibit_configure = FALSE;
1398 if (WINDOW_IS_TOPLEVEL (window))
1399 _gdk_win32_emit_configure_event (window);
1403 gdk_win32_window_reparent (GdkWindow *window,
1404 GdkWindow *new_parent,
1409 GdkWindow *old_parent;
1410 GdkWindowImplWin32 *impl;
1411 gboolean was_toplevel;
1415 new_parent = _gdk_root;
1417 old_parent = window->parent;
1418 parent = new_parent;
1419 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1421 GDK_NOTE (MISC, g_print ("gdk_win32_window_reparent: %p: %p\n",
1422 GDK_WINDOW_HWND (window),
1423 GDK_WINDOW_HWND (new_parent)));
1425 style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1427 was_toplevel = GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) == GetDesktopWindow ();
1428 if (was_toplevel && new_parent != _gdk_root)
1430 /* Reparenting from top-level (child of desktop). Clear out
1433 style &= ~(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
1435 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1437 else if (new_parent == _gdk_root)
1439 /* Reparenting to top-level. Add decorations. */
1440 style &= ~(WS_CHILD);
1441 style |= WS_OVERLAPPEDWINDOW;
1442 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1445 API_CALL (SetParent, (GDK_WINDOW_HWND (window),
1446 GDK_WINDOW_HWND (new_parent)));
1448 API_CALL (MoveWindow, (GDK_WINDOW_HWND (window),
1449 x, y, window->width, window->height, TRUE));
1451 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1454 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1455 new_parent = _gdk_root;
1457 window->parent = new_parent;
1459 /* Switch the window type as appropriate */
1461 switch (GDK_WINDOW_TYPE (new_parent))
1463 case GDK_WINDOW_ROOT:
1464 if (impl->toplevel_window_type != -1)
1465 GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
1466 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1467 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1470 case GDK_WINDOW_TOPLEVEL:
1471 case GDK_WINDOW_CHILD:
1472 case GDK_WINDOW_TEMP:
1473 if (WINDOW_IS_TOPLEVEL (window))
1475 /* Save the original window type so we can restore it if the
1476 * window is reparented back to be a toplevel.
1478 impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
1479 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1484 old_parent->children =
1485 g_list_remove (old_parent->children, window);
1487 parent->children = g_list_prepend (parent->children, window);
1493 gdk_win32_window_raise (GdkWindow *window)
1495 if (!GDK_WINDOW_DESTROYED (window))
1497 GDK_NOTE (MISC, g_print ("gdk_win32_window_raise: %p\n",
1498 GDK_WINDOW_HWND (window)));
1500 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
1501 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOPMOST,
1503 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1504 else if (window->accept_focus)
1505 API_CALL (BringWindowToTop, (GDK_WINDOW_HWND (window)));
1507 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
1509 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1514 gdk_win32_window_lower (GdkWindow *window)
1516 if (!GDK_WINDOW_DESTROYED (window))
1518 GDK_NOTE (MISC, g_print ("gdk_win32_window_lower: %p\n"
1519 "... SetWindowPos(%p,HWND_BOTTOM,0,0,0,0,"
1520 "NOACTIVATE|NOMOVE|NOSIZE)\n",
1521 GDK_WINDOW_HWND (window),
1522 GDK_WINDOW_HWND (window)));
1524 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_BOTTOM,
1526 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1531 gdk_win32_window_set_urgency_hint (GdkWindow *window,
1534 FLASHWINFO flashwinfo;
1535 typedef BOOL (*PFN_FlashWindowEx) (FLASHWINFO*);
1536 PFN_FlashWindowEx flashWindowEx = NULL;
1538 g_return_if_fail (GDK_IS_WINDOW (window));
1539 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1541 if (GDK_WINDOW_DESTROYED (window))
1544 flashWindowEx = (PFN_FlashWindowEx) GetProcAddress (GetModuleHandle ("user32.dll"), "FlashWindowEx");
1548 flashwinfo.cbSize = sizeof (flashwinfo);
1549 flashwinfo.hwnd = GDK_WINDOW_HWND (window);
1551 flashwinfo.dwFlags = FLASHW_ALL | FLASHW_TIMER;
1553 flashwinfo.dwFlags = FLASHW_STOP;
1554 flashwinfo.uCount = 0;
1555 flashwinfo.dwTimeout = 0;
1557 flashWindowEx (&flashwinfo);
1561 FlashWindow (GDK_WINDOW_HWND (window), urgent);
1566 get_effective_window_decorations (GdkWindow *window,
1567 GdkWMDecoration *decoration)
1569 GdkWindowImplWin32 *impl;
1571 impl = (GdkWindowImplWin32 *)window->impl;
1573 if (gdk_window_get_decorations (window, decoration))
1576 if (window->window_type != GDK_WINDOW_TOPLEVEL)
1581 if ((impl->hint_flags & GDK_HINT_MIN_SIZE) &&
1582 (impl->hint_flags & GDK_HINT_MAX_SIZE) &&
1583 impl->hints.min_width == impl->hints.max_width &&
1584 impl->hints.min_height == impl->hints.max_height)
1586 *decoration = GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MAXIMIZE;
1588 if (impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
1589 impl->type_hint == GDK_WINDOW_TYPE_HINT_MENU ||
1590 impl->type_hint == GDK_WINDOW_TYPE_HINT_TOOLBAR)
1592 *decoration |= GDK_DECOR_MINIMIZE;
1594 else if (impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
1596 *decoration |= GDK_DECOR_MENU | GDK_DECOR_MINIMIZE;
1601 else if (impl->hint_flags & GDK_HINT_MAX_SIZE)
1603 *decoration = GDK_DECOR_ALL | GDK_DECOR_MAXIMIZE;
1604 if (impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
1605 impl->type_hint == GDK_WINDOW_TYPE_HINT_MENU ||
1606 impl->type_hint == GDK_WINDOW_TYPE_HINT_TOOLBAR)
1608 *decoration |= GDK_DECOR_MINIMIZE;
1615 switch (impl->type_hint)
1617 case GDK_WINDOW_TYPE_HINT_DIALOG:
1618 *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1621 case GDK_WINDOW_TYPE_HINT_MENU:
1622 *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1625 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
1626 case GDK_WINDOW_TYPE_HINT_UTILITY:
1627 gdk_window_set_skip_taskbar_hint (window, TRUE);
1628 gdk_window_set_skip_pager_hint (window, TRUE);
1629 *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1632 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
1633 *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MENU |
1634 GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1637 case GDK_WINDOW_TYPE_HINT_DOCK:
1640 case GDK_WINDOW_TYPE_HINT_DESKTOP:
1645 case GDK_WINDOW_TYPE_HINT_NORMAL:
1646 *decoration = GDK_DECOR_ALL;
1655 gdk_win32_window_set_geometry_hints (GdkWindow *window,
1656 const GdkGeometry *geometry,
1657 GdkWindowHints geom_mask)
1659 GdkWindowImplWin32 *impl;
1662 g_return_if_fail (GDK_IS_WINDOW (window));
1664 if (GDK_WINDOW_DESTROYED (window))
1667 GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints: %p\n",
1668 GDK_WINDOW_HWND (window)));
1670 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1672 fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
1674 fi->hint_flags = geom_mask;
1676 impl->hint_flags = geom_mask;
1677 impl->hints = *geometry;
1679 if (geom_mask & GDK_HINT_POS)
1680 ; /* even the X11 mplementation doesn't care */
1682 if (geom_mask & GDK_HINT_MIN_SIZE)
1684 GDK_NOTE (MISC, g_print ("... MIN_SIZE: %dx%d\n",
1685 geometry->min_width, geometry->min_height));
1688 if (geom_mask & GDK_HINT_MAX_SIZE)
1690 GDK_NOTE (MISC, g_print ("... MAX_SIZE: %dx%d\n",
1691 geometry->max_width, geometry->max_height));
1694 if (geom_mask & GDK_HINT_BASE_SIZE)
1696 GDK_NOTE (MISC, g_print ("... BASE_SIZE: %dx%d\n",
1697 geometry->base_width, geometry->base_height));
1700 if (geom_mask & GDK_HINT_RESIZE_INC)
1702 GDK_NOTE (MISC, g_print ("... RESIZE_INC: (%d,%d)\n",
1703 geometry->width_inc, geometry->height_inc));
1706 if (geom_mask & GDK_HINT_ASPECT)
1708 GDK_NOTE (MISC, g_print ("... ASPECT: %g--%g\n",
1709 geometry->min_aspect, geometry->max_aspect));
1712 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1714 GDK_NOTE (MISC, g_print ("... GRAVITY: %d\n", geometry->win_gravity));
1717 update_style_bits (window);
1721 gdk_win32_window_set_title (GdkWindow *window,
1726 g_return_if_fail (GDK_IS_WINDOW (window));
1727 g_return_if_fail (title != NULL);
1729 if (GDK_WINDOW_DESTROYED (window))
1732 /* Empty window titles not allowed, so set it to just a period. */
1736 GDK_NOTE (MISC, g_print ("gdk_window_set_title: %p: %s\n",
1737 GDK_WINDOW_HWND (window), title));
1739 GDK_NOTE (MISC_OR_EVENTS, title = g_strdup_printf ("%p %s", GDK_WINDOW_HWND (window), title));
1741 wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
1742 API_CALL (SetWindowTextW, (GDK_WINDOW_HWND (window), wtitle));
1745 GDK_NOTE (MISC_OR_EVENTS, g_free ((char *) title));
1749 gdk_win32_window_set_role (GdkWindow *window,
1752 g_return_if_fail (GDK_IS_WINDOW (window));
1754 GDK_NOTE (MISC, g_print ("gdk_window_set_role: %p: %s\n",
1755 GDK_WINDOW_HWND (window),
1756 (role ? role : "NULL")));
1761 gdk_win32_window_set_transient_for (GdkWindow *window,
1764 HWND window_id, parent_id;
1765 GdkWindowImplWin32 *window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1766 GdkWindowImplWin32 *parent_impl = NULL;
1769 g_return_if_fail (GDK_IS_WINDOW (window));
1771 window_id = GDK_WINDOW_HWND (window);
1772 parent_id = parent != NULL ? GDK_WINDOW_HWND (parent) : NULL;
1774 GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %p: %p\n", window_id, parent_id));
1776 if (GDK_WINDOW_DESTROYED (window) || (parent && GDK_WINDOW_DESTROYED (parent)))
1778 if (GDK_WINDOW_DESTROYED (window))
1779 GDK_NOTE (MISC, g_print ("... destroyed!\n"));
1781 GDK_NOTE (MISC, g_print ("... owner destroyed!\n"));
1786 if (window->window_type == GDK_WINDOW_CHILD)
1788 GDK_NOTE (MISC, g_print ("... a child window!\n"));
1794 GdkWindowImplWin32 *trans_impl = GDK_WINDOW_IMPL_WIN32 (window_impl->transient_owner->impl);
1795 if (trans_impl->transient_children != NULL)
1797 item = g_slist_find (trans_impl->transient_children, window);
1799 trans_impl->transient_children = g_slist_delete_link (trans_impl->transient_children, item);
1800 trans_impl->num_transients--;
1802 if (!trans_impl->num_transients)
1804 trans_impl->transient_children = NULL;
1807 g_object_unref (G_OBJECT (window_impl->transient_owner));
1808 g_object_unref (G_OBJECT (window));
1810 window_impl->transient_owner = NULL;
1814 parent_impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
1816 parent_impl->transient_children = g_slist_append (parent_impl->transient_children, window);
1817 g_object_ref (G_OBJECT (window));
1818 parent_impl->num_transients++;
1819 window_impl->transient_owner = parent;
1820 g_object_ref (G_OBJECT (parent));
1823 /* This changes the *owner* of the window, despite the misleading
1824 * name. (Owner and parent are unrelated concepts.) At least that's
1825 * what people who seem to know what they talk about say on
1826 * USENET. Search on Google.
1829 if (SetWindowLongPtr (window_id, GWLP_HWNDPARENT, (LONG_PTR) parent_id) == 0 &&
1830 GetLastError () != 0)
1831 WIN32_API_FAILED ("SetWindowLongPtr");
1835 _gdk_push_modal_window (GdkWindow *window)
1837 modal_window_stack = g_slist_prepend (modal_window_stack,
1842 _gdk_remove_modal_window (GdkWindow *window)
1846 g_return_if_fail (window != NULL);
1848 /* It's possible to be NULL here if someone sets the modal hint of the window
1849 * to FALSE before a modal window stack has ever been created. */
1850 if (modal_window_stack == NULL)
1853 /* Find the requested window in the stack and remove it. Yeah, I realize this
1854 * means we're not a 'real stack', strictly speaking. Sue me. :) */
1855 tmp = g_slist_find (modal_window_stack, window);
1858 modal_window_stack = g_slist_delete_link (modal_window_stack, tmp);
1863 _gdk_modal_blocked (GdkWindow *window)
1866 gboolean found_any = FALSE;
1868 for (l = modal_window_stack; l != NULL; l = l->next)
1870 GdkWindow *modal = l->data;
1872 if (modal == window)
1875 if (GDK_WINDOW_IS_MAPPED (modal))
1883 _gdk_modal_current (void)
1887 for (l = modal_window_stack; l != NULL; l = l->next)
1889 GdkWindow *modal = l->data;
1891 if (GDK_WINDOW_IS_MAPPED (modal))
1899 gdk_win32_window_set_background (GdkWindow *window,
1900 cairo_pattern_t *pattern)
1905 gdk_win32_window_set_device_cursor (GdkWindow *window,
1909 GdkWindowImplWin32 *impl;
1910 GdkWin32Cursor *cursor_private;
1912 HCURSOR hprevcursor;
1914 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1915 cursor_private = (GdkWin32Cursor*) cursor;
1917 if (GDK_WINDOW_DESTROYED (window))
1923 hcursor = cursor_private->hcursor;
1925 GDK_NOTE (MISC, g_print ("gdk_win32_window_set_cursor: %p: %p\n",
1926 GDK_WINDOW_HWND (window),
1929 /* First get the old cursor, if any (we wait to free the old one
1930 * since it may be the current cursor set in the Win32 API right
1933 hprevcursor = impl->hcursor;
1935 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
1937 if (hcursor == NULL)
1938 impl->hcursor = NULL;
1941 /* We must copy the cursor as it is OK to destroy the GdkCursor
1942 * while still in use for some window. See for instance
1943 * gimp_change_win_cursor() which calls gdk_window_set_cursor
1944 * (win, cursor), and immediately afterwards gdk_cursor_destroy
1947 if ((impl->hcursor = CopyCursor (hcursor)) == NULL)
1948 WIN32_API_FAILED ("CopyCursor");
1949 GDK_NOTE (MISC, g_print ("... CopyCursor (%p) = %p\n",
1950 hcursor, impl->hcursor));
1953 /* Destroy the previous cursor */
1954 if (hprevcursor != NULL)
1956 GDK_NOTE (MISC, g_print ("... DestroyCursor (%p)\n", hprevcursor));
1957 API_CALL (DestroyCursor, (hprevcursor));
1962 gdk_win32_window_get_geometry (GdkWindow *window,
1971 if (!GDK_WINDOW_DESTROYED (window))
1975 API_CALL (GetClientRect, (GDK_WINDOW_HWND (window), &rect));
1977 if (window != _gdk_root)
1980 GdkWindow *parent = gdk_window_get_parent (window);
1984 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1985 ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
1991 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1992 ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
1996 if (parent == _gdk_root)
1998 rect.left += _gdk_offset_x;
1999 rect.top += _gdk_offset_y;
2000 rect.right += _gdk_offset_x;
2001 rect.bottom += _gdk_offset_y;
2010 *width = rect.right - rect.left;
2012 *height = rect.bottom - rect.top;
2014 GDK_NOTE (MISC, g_print ("gdk_win32_window_get_geometry: %p: %ldx%ldx%d@%+ld%+ld\n",
2015 GDK_WINDOW_HWND (window),
2016 rect.right - rect.left, rect.bottom - rect.top,
2017 gdk_window_get_visual (window)->depth,
2018 rect.left, rect.top));
2023 gdk_win32_window_get_root_coords (GdkWindow *window,
2035 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
2040 *root_x = tx + _gdk_offset_x;
2042 *root_y = ty + _gdk_offset_y;
2044 GDK_NOTE (MISC, g_print ("gdk_win32_window_get_root_coords: %p: %+d%+d %+d%+d\n",
2045 GDK_WINDOW_HWND (window),
2047 tx + _gdk_offset_x, ty + _gdk_offset_y));
2052 gdk_win32_window_restack_under (GdkWindow *window,
2053 GList *native_siblings)
2059 gdk_win32_window_restack_toplevel (GdkWindow *window,
2067 gdk_win32_window_get_root_origin (GdkWindow *window,
2073 g_return_if_fail (GDK_IS_WINDOW (window));
2075 gdk_window_get_frame_extents (window, &rect);
2083 GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %p: %+d%+d\n",
2084 GDK_WINDOW_HWND (window), rect.x, rect.y));
2088 gdk_win32_window_get_frame_extents (GdkWindow *window,
2094 g_return_if_fail (GDK_IS_WINDOW (window));
2095 g_return_if_fail (rect != NULL);
2102 if (GDK_WINDOW_DESTROYED (window))
2105 /* FIXME: window is documented to be a toplevel GdkWindow, so is it really
2106 * necessary to walk its parent chain?
2108 while (window->parent && window->parent->parent)
2109 window = window->parent;
2111 hwnd = GDK_WINDOW_HWND (window);
2112 API_CALL (GetWindowRect, (hwnd, &r));
2114 rect->x = r.left + _gdk_offset_x;
2115 rect->y = r.top + _gdk_offset_y;
2116 rect->width = r.right - r.left;
2117 rect->height = r.bottom - r.top;
2119 GDK_NOTE (MISC, g_print ("gdk_window_get_frame_extents: %p: %ldx%ld@%+ld%+ld\n",
2120 GDK_WINDOW_HWND (window),
2121 r.right - r.left, r.bottom - r.top,
2126 gdk_window_win32_get_device_state (GdkWindow *window,
2130 GdkModifierType *mask)
2134 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
2136 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
2140 return (child != NULL);
2144 _gdk_windowing_get_device_state (GdkDisplay *display,
2149 GdkModifierType *mask)
2151 g_return_if_fail (display == _gdk_display);
2154 *screen = _gdk_screen;
2156 GDK_DEVICE_GET_CLASS (device)->query_state (device,
2157 gdk_screen_get_root_window (_gdk_screen),
2165 gdk_display_warp_device (GdkDisplay *display,
2171 g_return_if_fail (display == _gdk_display);
2172 g_return_if_fail (screen == _gdk_screen);
2173 g_return_if_fail (GDK_IS_DEVICE (device));
2174 g_return_if_fail (display == gdk_device_get_display (device));
2176 GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
2180 _gdk_windowing_window_at_device_position (GdkDisplay *display,
2184 GdkModifierType *mask,
2185 gboolean get_toplevel)
2187 return GDK_DEVICE_GET_CLASS (device)->window_at_position (device, win_x, win_y, mask, get_toplevel);
2191 gdk_win32_window_get_events (GdkWindow *window)
2193 GdkWindowImplWin32 *impl;
2195 if (GDK_WINDOW_DESTROYED (window))
2198 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2200 return impl->native_event_mask;
2204 gdk_win32_window_set_events (GdkWindow *window,
2205 GdkEventMask event_mask)
2207 GdkWindowImplWin32 *impl;
2209 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2211 /* gdk_window_new() always sets the GDK_STRUCTURE_MASK, so better
2212 * set it here, too. Not that I know or remember why it is
2213 * necessary, will have to test some day.
2215 impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask;
2219 do_shape_combine_region (GdkWindow *window,
2225 GetClientRect (GDK_WINDOW_HWND (window), &rect);
2226 _gdk_win32_adjust_client_rect (window, &rect);
2228 OffsetRgn (hrgn, -rect.left, -rect.top);
2229 OffsetRgn (hrgn, x, y);
2231 /* If this is a top-level window, add the title bar to the region */
2232 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
2234 HRGN tmp = CreateRectRgn (0, 0, rect.right - rect.left, -rect.top);
2235 CombineRgn (hrgn, hrgn, tmp, RGN_OR);
2239 SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
2243 gdk_win32_window_set_override_redirect (GdkWindow *window,
2244 gboolean override_redirect)
2246 GdkWindowImplWin32 *window_impl;
2248 g_return_if_fail (GDK_IS_WINDOW (window));
2250 window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2252 window_impl->override_redirect = !!override_redirect;
2256 gdk_win32_window_set_accept_focus (GdkWindow *window,
2257 gboolean accept_focus)
2259 g_return_if_fail (GDK_IS_WINDOW (window));
2261 accept_focus = accept_focus != FALSE;
2263 if (window->accept_focus != accept_focus)
2264 window->accept_focus = accept_focus;
2268 gdk_win32_window_set_focus_on_map (GdkWindow *window,
2269 gboolean focus_on_map)
2271 g_return_if_fail (GDK_IS_WINDOW (window));
2273 focus_on_map = focus_on_map != FALSE;
2275 if (window->focus_on_map != focus_on_map)
2276 window->focus_on_map = focus_on_map;
2280 gdk_win32_window_set_icon_list (GdkWindow *window,
2283 GdkPixbuf *pixbuf, *big_pixbuf, *small_pixbuf;
2284 gint big_diff, small_diff;
2285 gint big_w, big_h, small_w, small_h;
2288 HICON small_hicon, big_hicon;
2289 GdkWindowImplWin32 *impl;
2290 gint i, big_i, small_i;
2292 g_return_if_fail (GDK_IS_WINDOW (window));
2294 if (GDK_WINDOW_DESTROYED (window))
2297 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2299 /* ideal sizes for small and large icons */
2300 big_w = GetSystemMetrics (SM_CXICON);
2301 big_h = GetSystemMetrics (SM_CYICON);
2302 small_w = GetSystemMetrics (SM_CXSMICON);
2303 small_h = GetSystemMetrics (SM_CYSMICON);
2305 /* find closest sized icons in the list */
2307 small_pixbuf = NULL;
2313 pixbuf = (GdkPixbuf*) pixbufs->data;
2314 w = gdk_pixbuf_get_width (pixbuf);
2315 h = gdk_pixbuf_get_height (pixbuf);
2317 dw = ABS (w - big_w);
2318 dh = ABS (h - big_h);
2319 diff = dw*dw + dh*dh;
2320 if (big_pixbuf == NULL || diff < big_diff)
2322 big_pixbuf = pixbuf;
2327 dw = ABS (w - small_w);
2328 dh = ABS (h - small_h);
2329 diff = dw*dw + dh*dh;
2330 if (small_pixbuf == NULL || diff < small_diff)
2332 small_pixbuf = pixbuf;
2337 pixbufs = g_list_next (pixbufs);
2341 /* Create the icons */
2342 big_hicon = _gdk_win32_pixbuf_to_hicon (big_pixbuf);
2343 small_hicon = _gdk_win32_pixbuf_to_hicon (small_pixbuf);
2346 SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_BIG,
2348 SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_SMALL,
2349 (LPARAM)small_hicon);
2351 /* Store the icons, destroying any previous icons */
2352 if (impl->hicon_big)
2353 GDI_CALL (DestroyIcon, (impl->hicon_big));
2354 impl->hicon_big = big_hicon;
2355 if (impl->hicon_small)
2356 GDI_CALL (DestroyIcon, (impl->hicon_small));
2357 impl->hicon_small = small_hicon;
2361 gdk_win32_window_set_icon_name (GdkWindow *window,
2364 /* In case I manage to confuse this again (or somebody else does):
2365 * Please note that "icon name" here really *does* mean the name or
2366 * title of an window minimized as an icon on the desktop, or in the
2367 * taskbar. It has nothing to do with the freedesktop.org icon
2371 g_return_if_fail (GDK_IS_WINDOW (window));
2373 if (GDK_WINDOW_DESTROYED (window))
2377 /* This is not the correct thing to do. We should keep both the
2378 * "normal" window title, and the icon name. When the window is
2379 * minimized, call SetWindowText() with the icon name, and when the
2380 * window is restored, with the normal window title. Also, the name
2381 * is in UTF-8, so we should do the normal conversion to either wide
2382 * chars or system codepage, and use either the W or A version of
2383 * SetWindowText(), depending on Windows version.
2385 API_CALL (SetWindowText, (GDK_WINDOW_HWND (window), name));
2390 gdk_win32_window_get_group (GdkWindow *window)
2392 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2393 g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
2395 if (GDK_WINDOW_DESTROYED (window))
2398 g_warning ("gdk_window_get_group not yet implemented");
2404 gdk_win32_window_set_group (GdkWindow *window,
2407 g_return_if_fail (GDK_IS_WINDOW (window));
2408 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2409 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
2411 if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
2414 g_warning ("gdk_window_set_group not implemented");
2418 update_single_bit (LONG *style,
2423 /* all controls the interpretation of gdk_bit -- if all is TRUE,
2424 * gdk_bit indicates whether style_bit is off; if all is FALSE, gdk
2425 * bit indicate whether style_bit is on
2427 if ((!all && gdk_bit) || (all && !gdk_bit))
2428 *style |= style_bit;
2430 *style &= ~style_bit;
2434 update_style_bits (GdkWindow *window)
2436 GdkWindowImplWin32 *impl = (GdkWindowImplWin32 *)window->impl;
2437 GdkWMDecoration decorations;
2438 LONG old_style, new_style, old_exstyle, new_exstyle;
2440 RECT rect, before, after;
2442 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
2445 old_style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2446 old_exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
2448 GetClientRect (GDK_WINDOW_HWND (window), &before);
2450 AdjustWindowRectEx (&before, old_style, FALSE, old_exstyle);
2452 new_style = old_style;
2453 new_exstyle = old_exstyle;
2455 if (window->window_type == GDK_WINDOW_TEMP ||
2456 impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
2457 new_exstyle |= WS_EX_TOOLWINDOW;
2459 new_exstyle &= ~WS_EX_TOOLWINDOW;
2461 if (get_effective_window_decorations (window, &decorations))
2463 all = (decorations & GDK_DECOR_ALL);
2464 update_single_bit (&new_style, all, decorations & GDK_DECOR_BORDER, WS_BORDER);
2465 update_single_bit (&new_style, all, decorations & GDK_DECOR_RESIZEH, WS_THICKFRAME);
2466 update_single_bit (&new_style, all, decorations & GDK_DECOR_TITLE, WS_CAPTION);
2467 update_single_bit (&new_style, all, decorations & GDK_DECOR_MENU, WS_SYSMENU);
2468 update_single_bit (&new_style, all, decorations & GDK_DECOR_MINIMIZE, WS_MINIMIZEBOX);
2469 update_single_bit (&new_style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
2472 if (old_style == new_style && old_exstyle == new_exstyle )
2474 GDK_NOTE (MISC, g_print ("update_style_bits: %p: no change\n",
2475 GDK_WINDOW_HWND (window)));
2479 if (old_style != new_style)
2481 GDK_NOTE (MISC, g_print ("update_style_bits: %p: STYLE: %s => %s\n",
2482 GDK_WINDOW_HWND (window),
2483 _gdk_win32_window_style_to_string (old_style),
2484 _gdk_win32_window_style_to_string (new_style)));
2486 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, new_style);
2489 if (old_exstyle != new_exstyle)
2491 GDK_NOTE (MISC, g_print ("update_style_bits: %p: EXSTYLE: %s => %s\n",
2492 GDK_WINDOW_HWND (window),
2493 _gdk_win32_window_exstyle_to_string (old_exstyle),
2494 _gdk_win32_window_exstyle_to_string (new_exstyle)));
2496 SetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE, new_exstyle);
2499 AdjustWindowRectEx (&after, new_style, FALSE, new_exstyle);
2501 GetWindowRect (GDK_WINDOW_HWND (window), &rect);
2502 rect.left += after.left - before.left;
2503 rect.top += after.top - before.top;
2504 rect.right += after.right - before.right;
2505 rect.bottom += after.bottom - before.bottom;
2507 SetWindowPos (GDK_WINDOW_HWND (window), NULL,
2508 rect.left, rect.top,
2509 rect.right - rect.left, rect.bottom - rect.top,
2510 SWP_FRAMECHANGED | SWP_NOACTIVATE |
2511 SWP_NOREPOSITION | SWP_NOZORDER);
2516 update_single_system_menu_entry (HMENU hmenu,
2521 /* all controls the interpretation of gdk_bit -- if all is TRUE,
2522 * gdk_bit indicates whether menu entry is disabled; if all is
2523 * FALSE, gdk bit indicate whether menu entry is enabled
2525 if ((!all && gdk_bit) || (all && !gdk_bit))
2526 EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_ENABLED);
2528 EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_GRAYED);
2532 update_system_menu (GdkWindow *window)
2534 GdkWMFunction functions;
2537 if (_gdk_window_get_functions (window, &functions))
2539 HMENU hmenu = GetSystemMenu (GDK_WINDOW_HWND (window), FALSE);
2541 all = (functions & GDK_FUNC_ALL);
2542 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_RESIZE, SC_SIZE);
2543 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MOVE, SC_MOVE);
2544 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MINIMIZE, SC_MINIMIZE);
2545 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MAXIMIZE, SC_MAXIMIZE);
2546 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_CLOSE, SC_CLOSE);
2551 get_decorations_quark ()
2553 static GQuark quark = 0;
2556 quark = g_quark_from_static_string ("gdk-window-decorations");
2562 gdk_win32_window_set_decorations (GdkWindow *window,
2563 GdkWMDecoration decorations)
2565 GdkWMDecoration* decorations_copy;
2567 g_return_if_fail (GDK_IS_WINDOW (window));
2569 GDK_NOTE (MISC, g_print ("gdk_window_set_decorations: %p: %s %s%s%s%s%s%s\n",
2570 GDK_WINDOW_HWND (window),
2571 (decorations & GDK_DECOR_ALL ? "clearing" : "setting"),
2572 (decorations & GDK_DECOR_BORDER ? "BORDER " : ""),
2573 (decorations & GDK_DECOR_RESIZEH ? "RESIZEH " : ""),
2574 (decorations & GDK_DECOR_TITLE ? "TITLE " : ""),
2575 (decorations & GDK_DECOR_MENU ? "MENU " : ""),
2576 (decorations & GDK_DECOR_MINIMIZE ? "MINIMIZE " : ""),
2577 (decorations & GDK_DECOR_MAXIMIZE ? "MAXIMIZE " : "")));
2579 decorations_copy = g_malloc (sizeof (GdkWMDecoration));
2580 *decorations_copy = decorations;
2581 g_object_set_qdata_full (G_OBJECT (window), get_decorations_quark (), decorations_copy, g_free);
2583 update_style_bits (window);
2587 gdk_win32_window_get_decorations (GdkWindow *window,
2588 GdkWMDecoration *decorations)
2590 GdkWMDecoration* decorations_set;
2592 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2594 decorations_set = g_object_get_qdata (G_OBJECT (window), get_decorations_quark ());
2595 if (decorations_set)
2596 *decorations = *decorations_set;
2598 return (decorations_set != NULL);
2602 get_functions_quark ()
2604 static GQuark quark = 0;
2607 quark = g_quark_from_static_string ("gdk-window-functions");
2613 gdk_win32_window_set_functions (GdkWindow *window,
2614 GdkWMFunction functions)
2616 GdkWMFunction* functions_copy;
2618 g_return_if_fail (GDK_IS_WINDOW (window));
2620 GDK_NOTE (MISC, g_print ("gdk_window_set_functions: %p: %s %s%s%s%s%s\n",
2621 GDK_WINDOW_HWND (window),
2622 (functions & GDK_FUNC_ALL ? "clearing" : "setting"),
2623 (functions & GDK_FUNC_RESIZE ? "RESIZE " : ""),
2624 (functions & GDK_FUNC_MOVE ? "MOVE " : ""),
2625 (functions & GDK_FUNC_MINIMIZE ? "MINIMIZE " : ""),
2626 (functions & GDK_FUNC_MAXIMIZE ? "MAXIMIZE " : ""),
2627 (functions & GDK_FUNC_CLOSE ? "CLOSE " : "")));
2629 functions_copy = g_malloc (sizeof (GdkWMFunction));
2630 *functions_copy = functions;
2631 g_object_set_qdata_full (G_OBJECT (window), get_functions_quark (), functions_copy, g_free);
2633 update_system_menu (window);
2637 _gdk_window_get_functions (GdkWindow *window,
2638 GdkWMFunction *functions)
2640 GdkWMFunction* functions_set;
2642 functions_set = g_object_get_qdata (G_OBJECT (window), get_functions_quark ());
2644 *functions = *functions_set;
2646 return (functions_set != NULL);
2650 gdk_win32_window_set_static_gravities (GdkWindow *window,
2651 gboolean use_static)
2653 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2659 gdk_win32_window_begin_resize_drag (GdkWindow *window,
2669 g_return_if_fail (GDK_IS_WINDOW (window));
2671 if (GDK_WINDOW_DESTROYED (window))
2674 /* Tell Windows to start interactively resizing the window by pretending that
2675 * the left pointer button was clicked in the suitable edge or corner. This
2676 * will only work if the button is down when this function is called, and
2677 * will only work with button 1 (left), since Windows only allows window
2678 * dragging using the left mouse button.
2683 /* Must break the automatic grab that occured when the button was
2684 * pressed, otherwise it won't work.
2686 gdk_display_pointer_ungrab (_gdk_display, 0);
2690 case GDK_WINDOW_EDGE_NORTH_WEST:
2691 winedge = HTTOPLEFT;
2694 case GDK_WINDOW_EDGE_NORTH:
2698 case GDK_WINDOW_EDGE_NORTH_EAST:
2699 winedge = HTTOPRIGHT;
2702 case GDK_WINDOW_EDGE_WEST:
2706 case GDK_WINDOW_EDGE_EAST:
2710 case GDK_WINDOW_EDGE_SOUTH_WEST:
2711 winedge = HTBOTTOMLEFT;
2714 case GDK_WINDOW_EDGE_SOUTH:
2718 case GDK_WINDOW_EDGE_SOUTH_EAST:
2720 winedge = HTBOTTOMRIGHT;
2724 DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, winedge,
2725 MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2729 gdk_win32_window_begin_move_drag (GdkWindow *window,
2736 g_return_if_fail (GDK_IS_WINDOW (window));
2738 if (GDK_WINDOW_DESTROYED (window))
2741 /* Tell Windows to start interactively moving the window by pretending that
2742 * the left pointer button was clicked in the titlebar. This will only work
2743 * if the button is down when this function is called, and will only work
2744 * with button 1 (left), since Windows only allows window dragging using the
2745 * left mouse button.
2750 /* Must break the automatic grab that occured when the button was pressed,
2751 * otherwise it won't work.
2753 gdk_display_pointer_ungrab (_gdk_display, 0);
2755 DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, HTCAPTION,
2756 MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2761 * Setting window states
2764 gdk_win32_window_iconify (GdkWindow *window)
2766 HWND old_active_window;
2768 g_return_if_fail (GDK_IS_WINDOW (window));
2770 if (GDK_WINDOW_DESTROYED (window))
2773 GDK_NOTE (MISC, g_print ("gdk_window_iconify: %p: %s\n",
2774 GDK_WINDOW_HWND (window),
2775 _gdk_win32_window_state_to_string (window->state)));
2777 if (GDK_WINDOW_IS_MAPPED (window))
2779 old_active_window = GetActiveWindow ();
2780 ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
2781 if (old_active_window != GDK_WINDOW_HWND (window))
2782 SetActiveWindow (old_active_window);
2786 gdk_synthesize_window_state (window,
2788 GDK_WINDOW_STATE_ICONIFIED);
2793 gdk_win32_window_deiconify (GdkWindow *window)
2795 g_return_if_fail (GDK_IS_WINDOW (window));
2797 if (GDK_WINDOW_DESTROYED (window))
2800 GDK_NOTE (MISC, g_print ("gdk_window_deiconify: %p: %s\n",
2801 GDK_WINDOW_HWND (window),
2802 _gdk_win32_window_state_to_string (window->state)));
2804 if (GDK_WINDOW_IS_MAPPED (window))
2806 show_window_internal (window, GDK_WINDOW_IS_MAPPED (window), TRUE);
2810 gdk_synthesize_window_state (window,
2811 GDK_WINDOW_STATE_ICONIFIED,
2817 gdk_win32_window_stick (GdkWindow *window)
2819 g_return_if_fail (GDK_IS_WINDOW (window));
2821 if (GDK_WINDOW_DESTROYED (window))
2824 /* FIXME: Do something? */
2828 gdk_win32_window_unstick (GdkWindow *window)
2830 g_return_if_fail (GDK_IS_WINDOW (window));
2832 if (GDK_WINDOW_DESTROYED (window))
2835 /* FIXME: Do something? */
2839 gdk_win32_window_maximize (GdkWindow *window)
2841 g_return_if_fail (GDK_IS_WINDOW (window));
2843 if (GDK_WINDOW_DESTROYED (window))
2846 GDK_NOTE (MISC, g_print ("gdk_window_maximize: %p: %s\n",
2847 GDK_WINDOW_HWND (window),
2848 _gdk_win32_window_state_to_string (window->state)));
2850 if (GDK_WINDOW_IS_MAPPED (window))
2851 ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
2853 gdk_synthesize_window_state (window,
2855 GDK_WINDOW_STATE_MAXIMIZED);
2859 gdk_win32_window_unmaximize (GdkWindow *window)
2861 g_return_if_fail (GDK_IS_WINDOW (window));
2863 if (GDK_WINDOW_DESTROYED (window))
2866 GDK_NOTE (MISC, g_print ("gdk_window_unmaximize: %p: %s\n",
2867 GDK_WINDOW_HWND (window),
2868 _gdk_win32_window_state_to_string (window->state)));
2870 if (GDK_WINDOW_IS_MAPPED (window))
2871 ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
2873 gdk_synthesize_window_state (window,
2874 GDK_WINDOW_STATE_MAXIMIZED,
2879 gdk_win32_window_fullscreen (GdkWindow *window)
2881 gint x, y, width, height;
2886 g_return_if_fail (GDK_IS_WINDOW (window));
2888 fi = g_new (FullscreenInfo, 1);
2890 if (!GetWindowRect (GDK_WINDOW_HWND (window), &(fi->r)))
2894 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2896 monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
2897 mi.cbSize = sizeof (mi);
2898 if (monitor && GetMonitorInfo (monitor, &mi))
2900 x = mi.rcMonitor.left;
2901 y = mi.rcMonitor.top;
2902 width = mi.rcMonitor.right - x;
2903 height = mi.rcMonitor.bottom - y;
2908 width = GetSystemMetrics (SM_CXSCREEN);
2909 height = GetSystemMetrics (SM_CYSCREEN);
2912 /* remember for restoring */
2913 fi->hint_flags = impl->hint_flags;
2914 impl->hint_flags &= ~GDK_HINT_MAX_SIZE;
2915 g_object_set_data (G_OBJECT (window), "fullscreen-info", fi);
2916 fi->style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2918 /* Send state change before configure event */
2919 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2921 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
2922 (fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP);
2924 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
2925 x, y, width, height,
2926 SWP_NOCOPYBITS | SWP_SHOWWINDOW));
2931 gdk_win32_window_unfullscreen (GdkWindow *window)
2935 g_return_if_fail (GDK_IS_WINDOW (window));
2937 fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
2940 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2942 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
2944 impl->hint_flags = fi->hint_flags;
2945 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, fi->style);
2946 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_NOTOPMOST,
2947 fi->r.left, fi->r.top,
2948 fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
2949 SWP_NOCOPYBITS | SWP_SHOWWINDOW));
2951 g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
2953 update_style_bits (window);
2958 gdk_win32_window_set_keep_above (GdkWindow *window,
2961 g_return_if_fail (GDK_IS_WINDOW (window));
2963 if (GDK_WINDOW_DESTROYED (window))
2966 GDK_NOTE (MISC, g_print ("gdk_window_set_keep_above: %p: %s\n",
2967 GDK_WINDOW_HWND (window),
2968 setting ? "YES" : "NO"));
2970 if (GDK_WINDOW_IS_MAPPED (window))
2972 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
2973 setting ? HWND_TOPMOST : HWND_NOTOPMOST,
2975 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
2978 gdk_synthesize_window_state (window,
2979 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
2980 setting ? GDK_WINDOW_STATE_ABOVE : 0);
2984 gdk_win32_window_set_keep_below (GdkWindow *window,
2987 g_return_if_fail (GDK_IS_WINDOW (window));
2989 if (GDK_WINDOW_DESTROYED (window))
2992 GDK_NOTE (MISC, g_print ("gdk_window_set_keep_below: %p: %s\n",
2993 GDK_WINDOW_HWND (window),
2994 setting ? "YES" : "NO"));
2996 if (GDK_WINDOW_IS_MAPPED (window))
2998 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
2999 setting ? HWND_BOTTOM : HWND_NOTOPMOST,
3001 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
3004 gdk_synthesize_window_state (window,
3005 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
3006 setting ? GDK_WINDOW_STATE_BELOW : 0);
3010 gdk_win32_window_focus (GdkWindow *window,
3013 g_return_if_fail (GDK_IS_WINDOW (window));
3015 if (GDK_WINDOW_DESTROYED (window))
3018 GDK_NOTE (MISC, g_print ("gdk_window_focus: %p: %s\n",
3019 GDK_WINDOW_HWND (window),
3020 _gdk_win32_window_state_to_string (window->state)));
3022 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
3023 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMAXIMIZED);
3025 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
3026 SetFocus (GDK_WINDOW_HWND (window));
3030 gdk_win32_window_set_modal_hint (GdkWindow *window,
3033 g_return_if_fail (GDK_IS_WINDOW (window));
3035 if (GDK_WINDOW_DESTROYED (window))
3038 GDK_NOTE (MISC, g_print ("gdk_window_set_modal_hint: %p: %s\n",
3039 GDK_WINDOW_HWND (window),
3040 modal ? "YES" : "NO"));
3042 if (modal == window->modal_hint)
3045 window->modal_hint = modal;
3048 /* Not sure about this one.. -- Cody */
3049 if (GDK_WINDOW_IS_MAPPED (window))
3050 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
3051 modal ? HWND_TOPMOST : HWND_NOTOPMOST,
3053 SWP_NOMOVE | SWP_NOSIZE));
3058 _gdk_push_modal_window (window);
3059 gdk_window_raise (window);
3063 _gdk_remove_modal_window (window);
3070 gdk_win32_window_set_skip_taskbar_hint (GdkWindow *window,
3071 gboolean skips_taskbar)
3073 static GdkWindow *owner = NULL;
3076 g_return_if_fail (GDK_IS_WINDOW (window));
3078 GDK_NOTE (MISC, g_print ("gdk_window_set_skip_taskbar_hint: %p: %s, doing nothing\n",
3079 GDK_WINDOW_HWND (window),
3080 skips_taskbar ? "YES" : "NO"));
3082 // ### TODO: Need to figure out what to do here.
3090 wa.window_type = GDK_WINDOW_TEMP;
3091 wa.wclass = GDK_INPUT_OUTPUT;
3092 wa.width = wa.height = 1;
3094 owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
3098 SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_WINDOW_HWND (owner));
3100 #if 0 /* Should we also turn off the minimize and maximize buttons? */
3101 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
3102 GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE) & ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU));
3104 SetWindowPos (GDK_WINDOW_HWND (window), NULL,
3106 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
3107 SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
3112 SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, 0);
3117 gdk_win32_window_set_skip_pager_hint (GdkWindow *window,
3118 gboolean skips_pager)
3120 g_return_if_fail (GDK_IS_WINDOW (window));
3122 GDK_NOTE (MISC, g_print ("gdk_window_set_skip_pager_hint: %p: %s, doing nothing\n",
3123 GDK_WINDOW_HWND (window),
3124 skips_pager ? "YES" : "NO"));
3128 gdk_win32_window_set_type_hint (GdkWindow *window,
3129 GdkWindowTypeHint hint)
3131 g_return_if_fail (GDK_IS_WINDOW (window));
3133 if (GDK_WINDOW_DESTROYED (window))
3138 static GEnumClass *class = NULL;
3140 class = g_type_class_ref (GDK_TYPE_WINDOW_TYPE_HINT);
3141 g_print ("gdk_window_set_type_hint: %p: %s\n",
3142 GDK_WINDOW_HWND (window),
3143 g_enum_get_value (class, hint)->value_name);
3146 ((GdkWindowImplWin32 *)window->impl)->type_hint = hint;
3148 update_style_bits (window);
3151 static GdkWindowTypeHint
3152 gdk_win32_window_get_type_hint (GdkWindow *window)
3154 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
3156 if (GDK_WINDOW_DESTROYED (window))
3157 return GDK_WINDOW_TYPE_HINT_NORMAL;
3159 return GDK_WINDOW_IMPL_WIN32 (window->impl)->type_hint;
3163 cairo_region_to_hrgn (const cairo_region_t *region,
3170 cairo_rectangle_int_t r;
3171 const int nrects = cairo_region_num_rectangles (region);
3173 sizeof (RGNDATAHEADER) + (sizeof (RECT) * nrects);
3176 rgndata = g_malloc (nbytes);
3177 rgndata->rdh.dwSize = sizeof (RGNDATAHEADER);
3178 rgndata->rdh.iType = RDH_RECTANGLES;
3179 rgndata->rdh.nCount = rgndata->rdh.nRgnSize = 0;
3180 SetRect (&rgndata->rdh.rcBound,
3181 G_MAXLONG, G_MAXLONG, G_MINLONG, G_MINLONG);
3183 for (i = 0; i < nrects; i++)
3185 rect = ((RECT *) rgndata->Buffer) + rgndata->rdh.nCount++;
3187 cairo_region_get_rectangle (region, i, &r);
3188 rect->left = r.x + x_origin;
3189 rect->right = rect->left + r.width;
3190 rect->top = r.y + y_origin;
3191 rect->bottom = rect->top + r.height;
3193 if (rect->left < rgndata->rdh.rcBound.left)
3194 rgndata->rdh.rcBound.left = rect->left;
3195 if (rect->right > rgndata->rdh.rcBound.right)
3196 rgndata->rdh.rcBound.right = rect->right;
3197 if (rect->top < rgndata->rdh.rcBound.top)
3198 rgndata->rdh.rcBound.top = rect->top;
3199 if (rect->bottom > rgndata->rdh.rcBound.bottom)
3200 rgndata->rdh.rcBound.bottom = rect->bottom;
3202 if ((hrgn = ExtCreateRegion (NULL, nbytes, rgndata)) == NULL)
3203 WIN32_API_FAILED ("ExtCreateRegion");
3211 gdk_win32_window_shape_combine_region (GdkWindow *window,
3212 const cairo_region_t *shape_region,
3216 if (GDK_WINDOW_DESTROYED (window))
3221 GDK_NOTE (MISC, g_print ("gdk_win32_window_shape_combine_region: %p: none\n",
3222 GDK_WINDOW_HWND (window)));
3223 SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
3229 hrgn = cairo_region_to_hrgn (shape_region, 0, 0);
3231 GDK_NOTE (MISC, g_print ("gdk_win32_window_shape_combine_region: %p: %p\n",
3232 GDK_WINDOW_HWND (window),
3235 do_shape_combine_region (window, hrgn, offset_x, offset_y);
3240 gdk_win32_window_lookup_for_display (GdkDisplay *display,
3243 g_return_val_if_fail (display == _gdk_display, NULL);
3245 return (GdkWindow*) gdk_win32_handle_table_lookup (anid);
3249 gdk_win32_window_enable_synchronized_configure (GdkWindow *window)
3251 /* nothing - no window manager to cooperate with */
3255 gdk_win32_window_configure_finished (GdkWindow *window)
3257 /* nothing - no window manager to cooperate with */
3261 gdk_win32_window_set_opacity (GdkWindow *window,
3265 typedef BOOL (*PFN_SetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
3266 PFN_SetLayeredWindowAttributes setLayeredWindowAttributes = NULL;
3268 g_return_if_fail (GDK_IS_WINDOW (window));
3269 g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
3271 if (GDK_WINDOW_DESTROYED (window))
3276 else if (opacity > 1)
3279 exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
3281 if (!(exstyle & WS_EX_LAYERED))
3282 SetWindowLong (GDK_WINDOW_HWND (window),
3284 exstyle | WS_EX_LAYERED);
3286 setLayeredWindowAttributes =
3287 (PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes");
3289 if (setLayeredWindowAttributes)
3291 API_CALL (setLayeredWindowAttributes, (GDK_WINDOW_HWND (window),
3298 static cairo_region_t *
3299 gdk_win32_window_get_shape (GdkWindow *window)
3301 HRGN hrgn = CreateRectRgn (0, 0, 0, 0);
3302 int type = GetWindowRgn (GDK_WINDOW_HWND (window), hrgn);
3304 if (type == SIMPLEREGION || type == COMPLEXREGION)
3306 cairo_region_t *region = _gdk_win32_hrgn_to_region (hrgn);
3308 DeleteObject (hrgn);
3316 _gdk_win32_window_queue_antiexpose (GdkWindow *window,
3317 cairo_region_t *area)
3319 HRGN hrgn = cairo_region_to_hrgn (area, 0, 0);
3321 GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
3322 GDK_WINDOW_HWND (window),
3323 _gdk_win32_cairo_region_to_string (area)));
3325 ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
3327 DeleteObject (hrgn);
3332 /* Gets called from gdwindow.c(do_move_region_bits_on_impl)
3333 * and got tested with testgtk::big_window. Given the previous,
3334 * untested implementation this one looks much too simple ;)
3337 _gdk_win32_window_translate (GdkWindow *window,
3338 cairo_region_t *area, /* In impl window coords */
3342 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
3343 GdkRectangle extents;
3345 HRGN hrgn, area_hrgn;
3349 /* Note: This is the destination area, not the source, and
3350 it has been moved by dx, dy from the source area */
3351 area_hrgn = cairo_region_to_hrgn (area, 0, 0);
3353 /* First we copy any outstanding invalid areas in the
3354 source area to the new position in the destination area */
3355 hrgn = CreateRectRgn (0, 0, 0, 0);
3356 ret = GetUpdateRgn (GDK_WINDOW_HWND (window), hrgn, FALSE);
3358 WIN32_API_FAILED ("GetUpdateRgn");
3359 else if (ret != NULLREGION)
3361 /* Convert the source invalid region as it would be copied */
3362 OffsetRgn (hrgn, dx, dy);
3363 /* Keep what intersects the copy destination area */
3364 ret = CombineRgn (hrgn, hrgn, area_hrgn, RGN_AND);
3365 /* And invalidate it */
3367 WIN32_API_FAILED ("CombineRgn");
3368 else if (ret != NULLREGION)
3369 API_CALL (InvalidateRgn, (GDK_WINDOW_HWND (window), hrgn, TRUE));
3372 /* Then we copy the bits, invalidating whatever is copied from
3373 otherwise invisible areas */
3375 hdc = _gdk_win32_impl_acquire_dc (impl);
3377 /* Clip hdc to target region */
3378 API_CALL (SelectClipRgn, (hdc, area_hrgn));
3380 cairo_region_get_extents (area, &extents);
3382 rect.left = MIN (extents.x, extents.x - dx);
3383 rect.top = MIN (extents.y, extents.y - dy);
3384 rect.right = MAX (extents.x + extents.width, extents.x - dx + extents.width);
3385 rect.bottom = MAX (extents.y + extents.height, extents.y - dy + extents.height);
3387 SetRectRgn (hrgn, 0, 0, 0, 0);
3389 if (!ScrollDC (hdc, dx, dy, &rect, NULL, hrgn, NULL))
3390 WIN32_GDI_FAILED ("ScrollDC");
3391 else if (!InvalidateRgn (GDK_WINDOW_HWND (window), hrgn, FALSE))
3392 WIN32_GDI_FAILED ("InvalidateRgn");
3394 /* Unset hdc clip region */
3395 API_CALL (SelectClipRgn, (hdc, NULL));
3397 _gdk_win32_impl_release_dc (impl);
3399 if (!DeleteObject (hrgn))
3400 WIN32_GDI_FAILED ("DeleteObject");
3402 if (!DeleteObject (area_hrgn))
3403 WIN32_GDI_FAILED ("DeleteObject");
3407 gdk_win32_input_shape_combine_region (GdkWindow *window,
3408 const cairo_region_t *shape_region,
3412 if (GDK_WINDOW_DESTROYED (window))
3414 /* CHECK: are these really supposed to be the same? */
3415 gdk_win32_window_shape_combine_region (window, shape_region, offset_x, offset_y);
3419 gdk_win32_window_process_updates_recurse (GdkWindow *window,
3420 cairo_region_t *region)
3422 _gdk_window_process_updates_recurse (window, region);
3426 gdk_win32_window_is_win32 (GdkWindow *window)
3428 return GDK_WINDOW_IS_WIN32 (window);
3432 * _gdk_win32_acquire_dc
3433 * @impl: a Win32 #GdkWindowImplWin32 implementation
3435 * Gets a DC with the given drawable selected into it.
3437 * Return value: The DC, on success. Otherwise
3438 * %NULL. If this function succeeded
3439 * _gdk_win32_impl_release_dc() must be called
3440 * release the DC when you are done using it.
3443 _gdk_win32_impl_acquire_dc (GdkWindowImplWin32 *impl)
3445 if (GDK_IS_WINDOW_IMPL_WIN32 (impl) &&
3446 GDK_WINDOW_DESTROYED (impl->wrapper))
3451 impl->hdc = GetDC (impl->handle);
3453 WIN32_GDI_FAILED ("GetDC");
3468 * _gdk_win32_impl_release_dc
3469 * @impl: a Win32 #GdkWindowImplWin32 implementation
3471 * Releases the reference count for the DC
3472 * from _gdk_win32_impl_acquire_dc()
3475 _gdk_win32_impl_release_dc (GdkWindowImplWin32 *impl)
3477 g_return_if_fail (impl->hdc_count > 0);
3480 if (impl->hdc_count == 0)
3482 if (impl->saved_dc_bitmap)
3484 GDI_CALL (SelectObject, (impl->hdc, impl->saved_dc_bitmap));
3485 impl->saved_dc_bitmap = NULL;
3490 GDI_CALL (ReleaseDC, (impl->handle, impl->hdc));
3497 gdk_win32_window_get_impl_hwnd (GdkWindow *window)
3499 if (GDK_WINDOW_IS_WIN32 (window))
3500 return GDK_WINDOW_HWND (window);
3505 gdk_win32_cairo_surface_destroy (void *data)
3507 GdkWindowImplWin32 *impl = data;
3509 _gdk_win32_impl_release_dc (impl);
3510 impl->cairo_surface = NULL;
3513 static cairo_surface_t *
3514 gdk_win32_ref_cairo_surface (GdkWindow *window)
3516 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
3518 if (GDK_IS_WINDOW_IMPL_WIN32 (impl) &&
3519 GDK_WINDOW_DESTROYED (impl->wrapper))
3522 if (!impl->cairo_surface)
3524 HDC hdc = _gdk_win32_impl_acquire_dc (impl);
3528 impl->cairo_surface = cairo_win32_surface_create (hdc);
3530 cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
3531 impl, gdk_win32_cairo_surface_destroy);
3534 cairo_surface_reference (impl->cairo_surface);
3536 return impl->cairo_surface;
3540 gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
3542 GObjectClass *object_class = G_OBJECT_CLASS (klass);
3543 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
3545 parent_class = g_type_class_peek_parent (klass);
3547 object_class->finalize = gdk_window_impl_win32_finalize;
3549 impl_class->ref_cairo_surface = gdk_win32_ref_cairo_surface;
3551 impl_class->show = gdk_win32_window_show;
3552 impl_class->hide = gdk_win32_window_hide;
3553 impl_class->withdraw = gdk_win32_window_withdraw;
3554 impl_class->set_events = gdk_win32_window_set_events;
3555 impl_class->get_events = gdk_win32_window_get_events;
3556 impl_class->raise = gdk_win32_window_raise;
3557 impl_class->lower = gdk_win32_window_lower;
3558 impl_class->restack_under = gdk_win32_window_restack_under;
3559 impl_class->restack_toplevel = gdk_win32_window_restack_toplevel;
3560 impl_class->move_resize = gdk_win32_window_move_resize;
3561 impl_class->set_background = gdk_win32_window_set_background;
3562 impl_class->reparent = gdk_win32_window_reparent;
3563 impl_class->set_device_cursor = gdk_win32_window_set_device_cursor;
3564 impl_class->get_geometry = gdk_win32_window_get_geometry;
3565 impl_class->get_device_state = gdk_window_win32_get_device_state;
3566 impl_class->get_root_coords = gdk_win32_window_get_root_coords;
3568 impl_class->shape_combine_region = gdk_win32_window_shape_combine_region;
3569 impl_class->input_shape_combine_region = gdk_win32_input_shape_combine_region;
3570 impl_class->set_static_gravities = gdk_win32_window_set_static_gravities;
3571 impl_class->queue_antiexpose = _gdk_win32_window_queue_antiexpose;
3572 impl_class->translate = _gdk_win32_window_translate;
3573 impl_class->destroy = gdk_win32_window_destroy;
3574 impl_class->destroy_foreign = gdk_win32_window_destroy_foreign;
3575 impl_class->resize_cairo_surface = gdk_win32_window_resize_cairo_surface;
3576 impl_class->get_shape = gdk_win32_window_get_shape;
3577 //FIXME?: impl_class->get_input_shape = gdk_win32_window_get_input_shape;
3579 //impl_class->beep = gdk_x11_window_beep;
3581 impl_class->focus = gdk_win32_window_focus;
3582 impl_class->set_type_hint = gdk_win32_window_set_type_hint;
3583 impl_class->get_type_hint = gdk_win32_window_get_type_hint;
3584 impl_class->set_modal_hint = gdk_win32_window_set_modal_hint;
3585 impl_class->set_skip_taskbar_hint = gdk_win32_window_set_skip_taskbar_hint;
3586 impl_class->set_skip_pager_hint = gdk_win32_window_set_skip_pager_hint;
3587 impl_class->set_urgency_hint = gdk_win32_window_set_urgency_hint;
3588 impl_class->set_geometry_hints = gdk_win32_window_set_geometry_hints;
3589 impl_class->set_title = gdk_win32_window_set_title;
3590 impl_class->set_role = gdk_win32_window_set_role;
3591 //impl_class->set_startup_id = gdk_x11_window_set_startup_id;
3592 impl_class->set_transient_for = gdk_win32_window_set_transient_for;
3593 impl_class->get_root_origin = gdk_win32_window_get_root_origin;
3594 impl_class->get_frame_extents = gdk_win32_window_get_frame_extents;
3595 impl_class->set_override_redirect = gdk_win32_window_set_override_redirect;
3596 impl_class->set_accept_focus = gdk_win32_window_set_accept_focus;
3597 impl_class->set_focus_on_map = gdk_win32_window_set_focus_on_map;
3598 impl_class->set_icon_list = gdk_win32_window_set_icon_list;
3599 impl_class->set_icon_name = gdk_win32_window_set_icon_name;
3600 impl_class->iconify = gdk_win32_window_iconify;
3601 impl_class->deiconify = gdk_win32_window_deiconify;
3602 impl_class->stick = gdk_win32_window_stick;
3603 impl_class->unstick = gdk_win32_window_unstick;
3604 impl_class->maximize = gdk_win32_window_maximize;
3605 impl_class->unmaximize = gdk_win32_window_unmaximize;
3606 impl_class->fullscreen = gdk_win32_window_fullscreen;
3607 impl_class->unfullscreen = gdk_win32_window_unfullscreen;
3608 impl_class->set_keep_above = gdk_win32_window_set_keep_above;
3609 impl_class->set_keep_below = gdk_win32_window_set_keep_below;
3610 impl_class->get_group = gdk_win32_window_get_group;
3611 impl_class->set_group = gdk_win32_window_set_group;
3612 impl_class->set_decorations = gdk_win32_window_set_decorations;
3613 impl_class->get_decorations = gdk_win32_window_get_decorations;
3614 impl_class->set_functions = gdk_win32_window_set_functions;
3616 impl_class->begin_resize_drag = gdk_win32_window_begin_resize_drag;
3617 impl_class->begin_move_drag = gdk_win32_window_begin_move_drag;
3618 impl_class->enable_synchronized_configure = gdk_win32_window_enable_synchronized_configure;
3619 impl_class->configure_finished = gdk_win32_window_configure_finished;
3620 impl_class->set_opacity = gdk_win32_window_set_opacity;
3621 //impl_class->set_composited = gdk_win32_window_set_composited;
3622 impl_class->destroy_notify = gdk_win32_window_destroy_notify;
3623 impl_class->get_drag_protocol = _gdk_win32_window_get_drag_protocol;
3624 impl_class->register_dnd = _gdk_win32_window_register_dnd;
3625 impl_class->drag_begin = _gdk_win32_window_drag_begin;
3626 impl_class->process_updates_recurse = gdk_win32_window_process_updates_recurse;
3627 //? impl_class->sync_rendering = _gdk_win32_window_sync_rendering;
3628 impl_class->simulate_key = _gdk_win32_window_simulate_key;
3629 impl_class->simulate_button = _gdk_win32_window_simulate_button;
3630 impl_class->get_property = _gdk_win32_window_get_property;
3631 impl_class->change_property = _gdk_win32_window_change_property;
3632 impl_class->delete_property = _gdk_win32_window_delete_property;
3636 gdk_win32_window_get_handle (GdkWindow *window)
3638 /* Try to ensure the window has a native window */
3639 if (!_gdk_window_has_impl (window))
3640 gdk_window_ensure_native (window);
3642 if (!GDK_WINDOW_IS_WIN32 (window))
3644 g_warning (G_STRLOC " window is not a native Win32 window");
3648 return GDK_WINDOW_HWND (window);