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, see <http://www.gnu.org/licenses/>.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
32 #include "gdkwindowimpl.h"
33 #include "gdkprivate-win32.h"
34 #include "gdkdeviceprivate.h"
35 #include "gdkdevicemanager-win32.h"
36 #include "gdkenumtypes.h"
38 #include "gdkdisplayprivate.h"
39 #include "gdkvisualprivate.h"
40 #include "gdkwin32window.h"
42 #include <cairo-win32.h>
44 static void gdk_window_impl_win32_init (GdkWindowImplWin32 *window);
45 static void gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass);
46 static void gdk_window_impl_win32_finalize (GObject *object);
48 static gpointer parent_class = NULL;
49 static GSList *modal_window_stack = NULL;
51 static const cairo_user_data_key_t gdk_win32_cairo_key;
52 typedef struct _FullscreenInfo FullscreenInfo;
54 struct _FullscreenInfo
61 static void update_style_bits (GdkWindow *window);
62 static gboolean _gdk_window_get_functions (GdkWindow *window,
63 GdkWMFunction *functions);
64 static HDC _gdk_win32_impl_acquire_dc (GdkWindowImplWin32 *impl);
65 static void _gdk_win32_impl_release_dc (GdkWindowImplWin32 *impl);
67 #define WINDOW_IS_TOPLEVEL(window) \
68 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
69 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
70 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
73 GDK_WINDOW_SCREEN (GObject *win)
78 struct _GdkWin32Window {
82 struct _GdkWin32WindowClass {
83 GdkWindowClass parent_class;
86 G_DEFINE_TYPE (GdkWin32Window, gdk_win32_window, GDK_TYPE_WINDOW)
89 gdk_win32_window_class_init (GdkWin32WindowClass *window_class)
94 gdk_win32_window_init (GdkWin32Window *window)
99 G_DEFINE_TYPE (GdkWindowImplWin32, gdk_window_impl_win32, GDK_TYPE_WINDOW_IMPL)
102 _gdk_window_impl_win32_get_type (void)
104 static GType object_type = 0;
108 const GTypeInfo object_info =
110 sizeof (GdkWindowImplWin32Class),
111 (GBaseInitFunc) NULL,
112 (GBaseFinalizeFunc) NULL,
113 (GClassInitFunc) gdk_window_impl_win32_class_init,
114 NULL, /* class_finalize */
115 NULL, /* class_data */
116 sizeof (GdkWindowImplWin32),
118 (GInstanceInitFunc) gdk_window_impl_win32_init,
121 object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL,
122 "GdkWindowImplWin32",
130 gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
132 impl->toplevel_window_type = -1;
133 impl->hcursor = NULL;
134 impl->hicon_big = NULL;
135 impl->hicon_small = NULL;
136 impl->hint_flags = 0;
137 impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
138 impl->transient_owner = NULL;
139 impl->transient_children = NULL;
140 impl->num_transients = 0;
141 impl->changing_state = FALSE;
145 gdk_window_impl_win32_finalize (GObject *object)
148 GdkWindowImplWin32 *window_impl;
150 g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (object));
152 window_impl = GDK_WINDOW_IMPL_WIN32 (object);
154 wrapper = window_impl->wrapper;
156 if (!GDK_WINDOW_DESTROYED (wrapper))
158 gdk_win32_handle_table_remove (window_impl->handle);
161 if (window_impl->hcursor != NULL)
163 if (GetCursor () == window_impl->hcursor)
166 GDI_CALL (DestroyCursor, (window_impl->hcursor));
167 window_impl->hcursor = NULL;
170 if (window_impl->hicon_big != NULL)
172 GDI_CALL (DestroyIcon, (window_impl->hicon_big));
173 window_impl->hicon_big = NULL;
176 if (window_impl->hicon_small != NULL)
178 GDI_CALL (DestroyIcon, (window_impl->hicon_small));
179 window_impl->hicon_small = NULL;
182 G_OBJECT_CLASS (parent_class)->finalize (object);
186 _gdk_win32_adjust_client_rect (GdkWindow *window,
191 style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
192 exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
193 API_CALL (AdjustWindowRectEx, (rect, style, FALSE, exstyle));
197 _gdk_root_window_size_init (void)
203 window = GDK_WINDOW (_gdk_root);
204 rect = _gdk_monitors[0].rect;
205 for (i = 1; i < _gdk_num_monitors; i++)
206 gdk_rectangle_union (&rect, &_gdk_monitors[i].rect, &rect);
208 window->width = rect.width;
209 window->height = rect.height;
213 _gdk_windowing_window_init (GdkScreen *screen)
216 GdkWindowImplWin32 *impl_win32;
218 g_assert (_gdk_root == NULL);
220 _gdk_root = _gdk_display_create_window (_gdk_display);
222 window = (GdkWindow *)_gdk_root;
223 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
224 impl_win32 = GDK_WINDOW_IMPL_WIN32 (window->impl);
225 impl_win32->wrapper = window;
227 window->impl_window = window;
228 window->visual = gdk_screen_get_system_visual (screen);
230 window->window_type = GDK_WINDOW_ROOT;
231 window->depth = gdk_visual_get_system ()->depth;
233 _gdk_root_window_size_init ();
239 /* width and height already initialised in _gdk_root_window_size_init() */
240 window->viewable = TRUE;
242 gdk_win32_handle_table_insert ((HANDLE *) &impl_win32->handle, _gdk_root);
244 GDK_NOTE (MISC, g_print ("_gdk_root=%p\n", GDK_WINDOW_HWND (_gdk_root)));
248 get_default_title (void)
251 title = g_get_application_name ();
253 title = g_get_prgname ();
259 * is a wrapper function for RegisterWindowClassEx.
260 * It creates at least one unique class for every
261 * GdkWindowType. If support for single window-specific icons
262 * is ever needed (e.g Dialog specific), every such window should
266 RegisterGdkClass (GdkWindowType wtype, GdkWindowTypeHint wtype_hint)
268 static ATOM klassTOPLEVEL = 0;
269 static ATOM klassCHILD = 0;
270 static ATOM klassTEMP = 0;
271 static ATOM klassTEMPSHADOW = 0;
272 static HICON hAppIcon = NULL;
273 static HICON hAppIconSm = NULL;
274 static WNDCLASSEXW wcl;
277 wcl.cbSize = sizeof (WNDCLASSEX);
278 wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
279 * on WM_SIZE and WM_MOVE. Flicker, Performance!
281 wcl.lpfnWndProc = _gdk_win32_window_procedure;
284 wcl.hInstance = _gdk_app_hmodule;
288 /* initialize once! */
289 if (0 == hAppIcon && 0 == hAppIconSm)
291 gchar sLoc [MAX_PATH+1];
293 if (0 != GetModuleFileName (_gdk_app_hmodule, sLoc, MAX_PATH))
295 ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
297 if (0 == hAppIcon && 0 == hAppIconSm)
299 if (0 != GetModuleFileName (_gdk_dll_hinstance, sLoc, MAX_PATH))
301 ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
306 if (0 == hAppIcon && 0 == hAppIconSm)
308 hAppIcon = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
309 GetSystemMetrics (SM_CXICON),
310 GetSystemMetrics (SM_CYICON), 0);
311 hAppIconSm = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
312 GetSystemMetrics (SM_CXSMICON),
313 GetSystemMetrics (SM_CYSMICON), 0);
318 hAppIcon = hAppIconSm;
319 else if (0 == hAppIconSm)
320 hAppIconSm = hAppIcon;
322 wcl.lpszMenuName = NULL;
324 /* initialize once per class */
326 * HB: Setting the background brush leads to flicker, because we
327 * don't get asked how to clear the background. This is not what
328 * we want, at least not for input_only windows ...
330 #define ONCE_PER_CLASS() \
331 wcl.hIcon = CopyIcon (hAppIcon); \
332 wcl.hIconSm = CopyIcon (hAppIconSm); \
333 wcl.hbrBackground = NULL; \
334 wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
338 case GDK_WINDOW_TOPLEVEL:
339 if (0 == klassTOPLEVEL)
341 wcl.lpszClassName = L"gdkWindowToplevel";
344 klassTOPLEVEL = RegisterClassExW (&wcl);
346 klass = klassTOPLEVEL;
349 case GDK_WINDOW_CHILD:
352 wcl.lpszClassName = L"gdkWindowChild";
354 wcl.style |= CS_PARENTDC; /* MSDN: ... enhances system performance. */
356 klassCHILD = RegisterClassExW (&wcl);
361 case GDK_WINDOW_TEMP:
362 if ((wtype_hint == GDK_WINDOW_TYPE_HINT_MENU) ||
363 (wtype_hint == GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU) ||
364 (wtype_hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU) ||
365 (wtype_hint == GDK_WINDOW_TYPE_HINT_TOOLTIP))
367 if (klassTEMPSHADOW == 0)
369 wcl.lpszClassName = L"gdkWindowTempShadow";
370 wcl.style |= CS_SAVEBITS;
371 if (LOBYTE (g_win32_get_windows_version()) > 0x05 ||
372 LOWORD (g_win32_get_windows_version()) == 0x0105)
374 /* Windows XP (5.1) or above */
375 wcl.style |= 0x00020000; /* CS_DROPSHADOW */
378 klassTEMPSHADOW = RegisterClassExW (&wcl);
381 klass = klassTEMPSHADOW;
387 wcl.lpszClassName = L"gdkWindowTemp";
388 wcl.style |= CS_SAVEBITS;
390 klassTEMP = RegisterClassExW (&wcl);
398 g_assert_not_reached ();
404 WIN32_API_FAILED ("RegisterClassExW");
405 g_error ("That is a fatal error");
411 * Create native windows.
413 * With the default Gdk the created windows are mostly toplevel windows.
415 * Placement of the window is derived from the passed in window,
416 * except for toplevel window where OS/Window Manager placement
419 * The visual parameter, is based on GDK_WA_VISUAL if set already.
420 * From attributes the only things used is: colormap, title,
421 * wmclass and type_hint. [1]. We are checking redundant information
422 * and complain if that changes, which would break this implementation
425 * [1] http://mail.gnome.org/archives/gtk-devel-list/2010-August/msg00214.html
428 _gdk_win32_display_create_window_impl (GdkDisplay *display,
430 GdkWindow *real_parent,
432 GdkEventMask event_mask,
433 GdkWindowAttr *attributes,
434 gint attributes_mask)
439 DWORD dwStyle = 0, dwExStyle;
441 GdkWindowImplWin32 *impl;
444 gboolean override_redirect;
445 gint window_width, window_height;
446 gint offset_x = 0, offset_y = 0;
447 gint x, y, real_x = 0, real_y = 0;
448 /* check consistency of redundant information */
449 guint remaining_mask = attributes_mask;
452 g_print ("_gdk_window_impl_new: %s %s\n",
453 (window->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
454 (window->window_type == GDK_WINDOW_CHILD ? "CHILD" :
455 (window->window_type == GDK_WINDOW_TEMP ? "TEMP" :
457 (attributes->wclass == GDK_INPUT_OUTPUT ? "" : "input-only"))
460 /* to ensure to not miss important information some additional check against
461 * attributes which may silently work on X11 */
462 if ((attributes_mask & GDK_WA_X) != 0)
464 g_assert (attributes->x == window->x);
465 remaining_mask &= ~GDK_WA_X;
467 if ((attributes_mask & GDK_WA_Y) != 0)
469 g_assert (attributes->y == window->y);
470 remaining_mask &= ~GDK_WA_Y;
472 override_redirect = FALSE;
473 if ((attributes_mask & GDK_WA_NOREDIR) != 0)
475 override_redirect = !!attributes->override_redirect;
476 remaining_mask &= ~GDK_WA_NOREDIR;
479 if ((remaining_mask & ~(GDK_WA_WMCLASS|GDK_WA_VISUAL|GDK_WA_CURSOR|GDK_WA_TITLE|GDK_WA_TYPE_HINT)) != 0)
480 g_warning ("_gdk_window_impl_new: uexpected attribute 0x%X",
481 remaining_mask & ~(GDK_WA_WMCLASS|GDK_WA_VISUAL|GDK_WA_CURSOR|GDK_WA_TITLE|GDK_WA_TYPE_HINT));
483 hparent = GDK_WINDOW_HWND (real_parent);
485 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
486 impl->wrapper = GDK_WINDOW (window);
487 window->impl = GDK_WINDOW_IMPL (impl);
489 if (attributes_mask & GDK_WA_VISUAL)
490 g_assert (gdk_screen_get_system_visual (screen) == attributes->visual);
492 impl->override_redirect = override_redirect;
494 /* wclass is not any longer set always, but if is ... */
495 if ((attributes_mask & GDK_WA_WMCLASS) == GDK_WA_WMCLASS)
496 g_assert ((attributes->wclass == GDK_INPUT_OUTPUT) == !window->input_only);
498 if (!window->input_only)
504 /* I very much doubt using WS_EX_TRANSPARENT actually
505 * corresponds to how X11 InputOnly windows work, but it appears
506 * to work well enough for the actual use cases in gtk.
508 dwExStyle = WS_EX_TRANSPARENT;
509 GDK_NOTE (MISC, g_print ("... GDK_INPUT_ONLY\n"));
512 switch (window->window_type)
514 case GDK_WINDOW_TOPLEVEL:
515 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
517 /* The common code warns for this case. */
518 hparent = GetDesktopWindow ();
520 /* Children of foreign windows aren't toplevel windows */
521 if (GDK_WINDOW_TYPE (real_parent) == GDK_WINDOW_FOREIGN)
523 dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN;
527 if (window->window_type == GDK_WINDOW_TOPLEVEL)
528 dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
530 dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
532 offset_x = _gdk_offset_x;
533 offset_y = _gdk_offset_y;
537 case GDK_WINDOW_CHILD:
538 dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
541 case GDK_WINDOW_TEMP:
542 /* A temp window is not necessarily a top level window */
543 dwStyle = (_gdk_root == real_parent ? WS_POPUP : WS_CHILDWINDOW);
544 dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
545 dwExStyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
546 offset_x = _gdk_offset_x;
547 offset_y = _gdk_offset_y;
551 g_assert_not_reached ();
554 if (window->window_type != GDK_WINDOW_CHILD)
556 rect.left = window->x;
557 rect.top = window->y;
558 rect.right = window->width;
559 rect.bottom = window->height;
561 AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
563 real_x = window->x - offset_x;
564 real_y = window->y - offset_y;
566 if (window->window_type == GDK_WINDOW_TOPLEVEL)
568 /* We initially place it at default so that we can get the
569 default window positioning if we want */
570 x = y = CW_USEDEFAULT;
574 /* TEMP, FOREIGN: Put these where requested */
579 window_width = rect.right - rect.left;
580 window_height = rect.bottom - rect.top;
584 /* adjust position relative to real_parent */
585 window_width = window->width;
586 window_height = window->height;
587 /* use given position for initial placement, native coordinates */
588 x = window->x + window->parent->abs_x - offset_x;
589 y = window->y + window->parent->abs_y - offset_y;
592 if (attributes_mask & GDK_WA_TITLE)
593 title = attributes->title;
595 title = get_default_title ();
596 if (!title || !*title)
599 impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask;
601 if (attributes_mask & GDK_WA_TYPE_HINT)
602 gdk_window_set_type_hint (window, attributes->type_hint);
604 if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
605 dwExStyle |= WS_EX_TOOLWINDOW;
607 klass = RegisterGdkClass (window->window_type, impl->type_hint);
609 wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
611 hwndNew = CreateWindowExW (dwExStyle,
612 MAKEINTRESOURCEW (klass),
617 window_width, window_height,
622 if (GDK_WINDOW_HWND (window) != hwndNew)
624 g_warning ("gdk_window_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
625 GDK_WINDOW_HWND (window),
628 /* HB: IHMO due to a race condition the handle was increased by
629 * one, which causes much trouble. Because I can't find the
630 * real bug, try to workaround it ...
631 * To reproduce: compile with MSVC 5, DEBUG=1
634 gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
635 GDK_WINDOW_HWND (window) = hwndNew;
636 gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
638 /* the old behaviour, but with warning */
639 impl->handle = hwndNew;
644 if (window->window_type != GDK_WINDOW_CHILD)
646 GetWindowRect (GDK_WINDOW_HWND (window), &rect);
647 impl->initial_x = rect.left;
648 impl->initial_y = rect.top;
650 /* Now we know the initial position, move to actually specified position */
651 if (real_x != x || real_y != y)
653 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
654 real_x, real_y, 0, 0,
655 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
659 g_object_ref (window);
660 gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
662 GDK_NOTE (MISC, g_print ("... \"%s\" %dx%d@%+d%+d %p = %p\n",
664 window_width, window_height,
665 window->x - offset_x,
666 window->y - offset_y,
668 GDK_WINDOW_HWND (window)));
670 /* Add window handle to title */
671 GDK_NOTE (MISC_OR_EVENTS, gdk_window_set_title (window, title));
675 if (impl->handle == NULL)
677 WIN32_API_FAILED ("CreateWindowExW");
678 g_object_unref (window);
682 // if (!from_set_skip_taskbar_hint && window->window_type == GDK_WINDOW_TEMP)
683 // gdk_window_set_skip_taskbar_hint (window, TRUE);
685 if (attributes_mask & GDK_WA_CURSOR)
686 gdk_window_set_cursor (window, attributes->cursor);
690 gdk_win32_window_foreign_new_for_display (GdkDisplay *display,
694 GdkWindowImplWin32 *impl;
700 g_return_val_if_fail (display == _gdk_display, NULL);
702 if ((window = gdk_win32_window_lookup_for_display (display, anid)) != NULL)
703 return g_object_ref (window);
705 window = _gdk_display_create_window (display);
706 window->visual = gdk_screen_get_system_visual (_gdk_screen);
707 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
708 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
709 impl->wrapper = window;
710 parent = GetParent (anid);
712 window->parent = gdk_win32_handle_table_lookup (parent);
713 if (!window->parent || GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_FOREIGN)
714 window->parent = _gdk_root;
716 window->parent->children = g_list_prepend (window->parent->children, window);
718 GetClientRect ((HWND) anid, &rect);
720 point.y = rect.right;
721 ClientToScreen ((HWND) anid, &point);
722 if (parent != GetDesktopWindow ())
723 ScreenToClient (parent, &point);
726 window->width = rect.right - rect.left;
727 window->height = rect.bottom - rect.top;
728 window->window_type = GDK_WINDOW_FOREIGN;
729 window->destroyed = FALSE;
730 window->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
731 if (IsWindowVisible ((HWND) anid))
732 window->state &= (~GDK_WINDOW_STATE_WITHDRAWN);
734 window->state |= GDK_WINDOW_STATE_WITHDRAWN;
735 if (GetWindowLong ((HWND)anid, GWL_EXSTYLE) & WS_EX_TOPMOST)
736 window->state |= GDK_WINDOW_STATE_ABOVE;
738 window->state &= (~GDK_WINDOW_STATE_ABOVE);
739 window->state &= (~GDK_WINDOW_STATE_BELOW);
740 window->viewable = TRUE;
742 window->depth = gdk_visual_get_system ()->depth;
744 g_object_ref (window);
745 gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
747 GDK_NOTE (MISC, g_print ("gdk_win32_window_foreign_new_for_display: %p: %s@%+d%+d\n",
749 _gdk_win32_window_description (window),
750 window->x, window->y));
756 gdk_win32_window_destroy (GdkWindow *window,
758 gboolean foreign_destroy)
760 GdkWindowImplWin32 *window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
763 g_return_if_fail (GDK_IS_WINDOW (window));
765 GDK_NOTE (MISC, g_print ("gdk_win32_window_destroy: %p\n",
766 GDK_WINDOW_HWND (window)));
768 /* Remove ourself from the modal stack */
769 _gdk_remove_modal_window (window);
771 /* Remove all our transient children */
772 tmp = window_impl->transient_children;
775 GdkWindow *child = tmp->data;
776 GdkWindowImplWin32 *child_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW (child)->impl);
778 child_impl->transient_owner = NULL;
779 tmp = g_slist_next (tmp);
781 g_slist_free (window_impl->transient_children);
782 window_impl->transient_children = NULL;
784 /* Remove ourself from our transient owner */
785 if (window_impl->transient_owner != NULL)
787 gdk_window_set_transient_for (window, NULL);
790 if (!recursing && !foreign_destroy)
792 window->destroyed = TRUE;
793 DestroyWindow (GDK_WINDOW_HWND (window));
797 static cairo_surface_t *
798 gdk_win32_window_resize_cairo_surface (GdkWindow *window,
799 cairo_surface_t *surface,
803 /* XXX: Make Cairo surface use DC clip */
804 cairo_surface_destroy (surface);
810 gdk_win32_window_destroy_foreign (GdkWindow *window)
812 /* It's somebody else's window, but in our hierarchy, so reparent it
813 * to the desktop, and then try to destroy it.
815 gdk_window_hide (window);
816 gdk_window_reparent (window, NULL, 0, 0);
818 PostMessage (GDK_WINDOW_HWND (window), WM_CLOSE, 0, 0);
821 /* This function is called when the window really gone.
824 gdk_win32_window_destroy_notify (GdkWindow *window)
826 g_return_if_fail (GDK_IS_WINDOW (window));
829 g_print ("gdk_window_destroy_notify: %p%s\n",
830 GDK_WINDOW_HWND (window),
831 (GDK_WINDOW_DESTROYED (window) ? " (destroyed)" : "")));
833 if (!GDK_WINDOW_DESTROYED (window))
835 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
836 g_warning ("window %p unexpectedly destroyed",
837 GDK_WINDOW_HWND (window));
839 _gdk_window_destroy (window, TRUE);
842 gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
843 g_object_unref (window);
847 get_outer_rect (GdkWindow *window,
852 rect->left = rect->top = 0;
854 rect->bottom = height;
856 _gdk_win32_adjust_client_rect (window, rect);
860 adjust_for_gravity_hints (GdkWindow *window,
865 GdkWindowImplWin32 *impl;
867 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
869 if (impl->hint_flags & GDK_HINT_WIN_GRAVITY)
871 #ifdef G_ENABLE_DEBUG
872 gint orig_x = *x, orig_y = *y;
875 switch (impl->hints.win_gravity)
877 case GDK_GRAVITY_NORTH:
878 case GDK_GRAVITY_CENTER:
879 case GDK_GRAVITY_SOUTH:
880 *x -= (outer_rect->right - outer_rect->left) / 2;
881 *x += window->width / 2;
884 case GDK_GRAVITY_SOUTH_EAST:
885 case GDK_GRAVITY_EAST:
886 case GDK_GRAVITY_NORTH_EAST:
887 *x -= outer_rect->right - outer_rect->left;
891 case GDK_GRAVITY_STATIC:
892 *x += outer_rect->left;
899 switch (impl->hints.win_gravity)
901 case GDK_GRAVITY_WEST:
902 case GDK_GRAVITY_CENTER:
903 case GDK_GRAVITY_EAST:
904 *y -= (outer_rect->bottom - outer_rect->top) / 2;
905 *y += window->height / 2;
908 case GDK_GRAVITY_SOUTH_WEST:
909 case GDK_GRAVITY_SOUTH:
910 case GDK_GRAVITY_SOUTH_EAST:
911 *y -= outer_rect->bottom - outer_rect->top;
912 *y += window->height;
915 case GDK_GRAVITY_STATIC:
916 *y += outer_rect->top;
923 (orig_x != *x || orig_y != *y) ?
924 g_print ("adjust_for_gravity_hints: x: %d->%d, y: %d->%d\n",
925 orig_x, *x, orig_y, *y)
931 show_window_internal (GdkWindow *window,
932 gboolean already_mapped,
935 GdkWindowImplWin32 *window_impl;
936 gboolean focus_on_map = FALSE;
939 if (window->destroyed)
942 GDK_NOTE (MISC, g_print ("show_window_internal: %p: %s%s\n",
943 GDK_WINDOW_HWND (window),
944 _gdk_win32_window_state_to_string (window->state),
945 (deiconify ? " deiconify" : "")));
947 /* If asked to show (not deiconify) an withdrawn and iconified
952 (window->state & GDK_WINDOW_STATE_ICONIFIED))
954 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMINNOACTIVE);
958 /* If asked to just show an iconified window, do nothing. */
959 if (!deiconify && (window->state & GDK_WINDOW_STATE_ICONIFIED))
962 /* If asked to deiconify an already noniconified window, do
963 * nothing. (Especially, don't cause the window to rise and
964 * activate. There are different calls for that.)
966 if (deiconify && !(window->state & GDK_WINDOW_STATE_ICONIFIED))
969 /* If asked to show (but not raise) a window that is already
970 * visible, do nothing.
972 if (!deiconify && !already_mapped && IsWindowVisible (GDK_WINDOW_HWND (window)))
978 focus_on_map = window->focus_on_map;
980 exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
982 /* Use SetWindowPos to show transparent windows so automatic redraws
983 * in other windows can be suppressed.
985 if (exstyle & WS_EX_TRANSPARENT)
987 UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
989 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
990 flags |= SWP_NOACTIVATE;
992 SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOP, 0, 0, 0, 0, flags);
997 /* For initial map of "normal" windows we want to emulate WM window
998 * positioning behaviour, which means:
999 * + Use user specified position if GDK_HINT_POS or GDK_HINT_USER_POS
1001 * + default to the initial CW_USEDEFAULT placement,
1002 * no matter if the user moved the window before showing it.
1003 * + Certain window types and hints have more elaborate positioning
1006 window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1007 if (!already_mapped &&
1008 GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL &&
1009 (window_impl->hint_flags & (GDK_HINT_POS | GDK_HINT_USER_POS)) == 0 &&
1010 !window_impl->override_redirect)
1012 gboolean center = FALSE;
1013 RECT window_rect, center_on_rect;
1016 x = window_impl->initial_x;
1017 y = window_impl->initial_y;
1019 if (window_impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
1024 monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
1025 mi.cbSize = sizeof (mi);
1026 if (monitor && GetMonitorInfo (monitor, &mi))
1027 center_on_rect = mi.rcMonitor;
1030 center_on_rect.left = 0;
1031 center_on_rect.right = 0;
1032 center_on_rect.right = GetSystemMetrics (SM_CXSCREEN);
1033 center_on_rect.bottom = GetSystemMetrics (SM_CYSCREEN);
1037 else if (window_impl->transient_owner != NULL &&
1038 GDK_WINDOW_IS_MAPPED (window_impl->transient_owner))
1040 GdkWindow *owner = window_impl->transient_owner;
1041 /* Center on transient parent */
1042 center_on_rect.left = owner->x;
1043 center_on_rect.top = owner->y;
1044 center_on_rect.right = center_on_rect.left + owner->width;
1045 center_on_rect.bottom = center_on_rect.top + owner->height;
1046 _gdk_win32_adjust_client_rect (GDK_WINDOW (owner), ¢er_on_rect);
1052 window_rect.left = 0;
1053 window_rect.top = 0;
1054 window_rect.right = window->width;
1055 window_rect.bottom = window->height;
1056 _gdk_win32_adjust_client_rect (window, &window_rect);
1058 x = center_on_rect.left + ((center_on_rect.right - center_on_rect.left) - (window_rect.right - window_rect.left)) / 2;
1059 y = center_on_rect.top + ((center_on_rect.bottom - center_on_rect.top) - (window_rect.bottom - window_rect.top)) / 2;
1062 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1064 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
1067 if (!already_mapped &&
1068 GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL &&
1069 !window_impl->override_redirect)
1071 /* Ensure new windows are fully onscreen */
1077 GetWindowRect (GDK_WINDOW_HWND (window), &window_rect);
1079 monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
1080 mi.cbSize = sizeof (mi);
1081 if (monitor && GetMonitorInfo (monitor, &mi))
1083 x = window_rect.left;
1084 y = window_rect.top;
1086 if (window_rect.right > mi.rcWork.right)
1088 window_rect.left -= (window_rect.right - mi.rcWork.right);
1089 window_rect.right -= (window_rect.right - mi.rcWork.right);
1092 if (window_rect.bottom > mi.rcWork.bottom)
1094 window_rect.top -= (window_rect.bottom - mi.rcWork.bottom);
1095 window_rect.bottom -= (window_rect.bottom - mi.rcWork.bottom);
1098 if (window_rect.left < mi.rcWork.left)
1100 window_rect.right += (mi.rcWork.left - window_rect.left);
1101 window_rect.left += (mi.rcWork.left - window_rect.left);
1104 if (window_rect.top < mi.rcWork.top)
1106 window_rect.bottom += (mi.rcWork.top - window_rect.top);
1107 window_rect.top += (mi.rcWork.top - window_rect.top);
1110 if (x != window_rect.left || y != window_rect.top)
1111 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1112 window_rect.left, window_rect.top, 0, 0,
1113 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
1118 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1120 gdk_window_fullscreen (window);
1122 else if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1124 ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
1126 else if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1129 ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
1131 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
1133 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
1135 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
1139 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
1142 /* Sync STATE_ABOVE to TOPMOST */
1143 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_TEMP &&
1144 (((window->state & GDK_WINDOW_STATE_ABOVE) &&
1145 !(exstyle & WS_EX_TOPMOST)) ||
1146 (!(window->state & GDK_WINDOW_STATE_ABOVE) &&
1147 (exstyle & WS_EX_TOPMOST))))
1149 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
1150 (window->state & GDK_WINDOW_STATE_ABOVE)?HWND_TOPMOST:HWND_NOTOPMOST,
1152 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
1157 gdk_win32_window_show (GdkWindow *window,
1158 gboolean already_mapped)
1160 show_window_internal (window, FALSE, FALSE);
1164 gdk_win32_window_hide (GdkWindow *window)
1166 if (window->destroyed)
1169 GDK_NOTE (MISC, g_print ("gdk_win32_window_hide: %p: %s\n",
1170 GDK_WINDOW_HWND (window),
1171 _gdk_win32_window_state_to_string (window->state)));
1173 if (GDK_WINDOW_IS_MAPPED (window))
1174 gdk_synthesize_window_state (window,
1176 GDK_WINDOW_STATE_WITHDRAWN);
1178 _gdk_window_clear_update_area (window);
1180 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
1181 ShowOwnedPopups (GDK_WINDOW_HWND (window), FALSE);
1183 if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
1185 SetWindowPos (GDK_WINDOW_HWND (window), HWND_BOTTOM,
1187 SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
1191 ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
1196 gdk_win32_window_withdraw (GdkWindow *window)
1198 if (window->destroyed)
1201 GDK_NOTE (MISC, g_print ("gdk_win32_window_withdraw: %p: %s\n",
1202 GDK_WINDOW_HWND (window),
1203 _gdk_win32_window_state_to_string (window->state)));
1205 gdk_window_hide (window); /* ??? */
1209 gdk_win32_window_move (GdkWindow *window,
1212 GdkWindowImplWin32 *impl;
1214 g_return_if_fail (GDK_IS_WINDOW (window));
1216 if (GDK_WINDOW_DESTROYED (window))
1219 GDK_NOTE (MISC, g_print ("gdk_win32_window_move: %p: %+d%+d\n",
1220 GDK_WINDOW_HWND (window), x, y));
1222 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1224 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1227 /* Don't check GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD.
1228 * Foreign windows (another app's windows) might be children of our
1229 * windows! Especially in the case of gtkplug/socket.
1231 if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1233 _gdk_window_move_resize_child (window, x, y, window->width, window->height);
1239 get_outer_rect (window, window->width, window->height, &outer_rect);
1241 adjust_for_gravity_hints (window, &outer_rect, &x, &y);
1243 GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,0,0,"
1244 "NOACTIVATE|NOSIZE|NOZORDER)\n",
1245 GDK_WINDOW_HWND (window),
1246 x - _gdk_offset_x, y - _gdk_offset_y));
1248 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1249 x - _gdk_offset_x, y - _gdk_offset_y, 0, 0,
1250 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
1255 gdk_win32_window_resize (GdkWindow *window,
1256 gint width, gint height)
1258 GdkWindowImplWin32 *impl;
1260 g_return_if_fail (GDK_IS_WINDOW (window));
1262 if (GDK_WINDOW_DESTROYED (window))
1270 GDK_NOTE (MISC, g_print ("gdk_win32_window_resize: %p: %dx%d\n",
1271 GDK_WINDOW_HWND (window), width, height));
1273 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1275 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1278 if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1280 _gdk_window_move_resize_child (window, window->x, window->y, width, height);
1286 get_outer_rect (window, width, height, &outer_rect);
1288 GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,0,0,%ld,%ld,"
1289 "NOACTIVATE|NOMOVE|NOZORDER)\n",
1290 GDK_WINDOW_HWND (window),
1291 outer_rect.right - outer_rect.left,
1292 outer_rect.bottom - outer_rect.top));
1294 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1296 outer_rect.right - outer_rect.left,
1297 outer_rect.bottom - outer_rect.top,
1298 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER));
1299 window->resize_count += 1;
1304 gdk_win32_window_move_resize_internal (GdkWindow *window,
1310 GdkWindowImplWin32 *impl;
1312 g_return_if_fail (GDK_IS_WINDOW (window));
1314 if (GDK_WINDOW_DESTROYED (window))
1322 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1324 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1327 GDK_NOTE (MISC, g_print ("gdk_win32_window_move_resize: %p: %dx%d@%+d%+d\n",
1328 GDK_WINDOW_HWND (window),
1329 width, height, x, y));
1331 if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
1333 _gdk_window_move_resize_child (window, x, y, width, height);
1339 get_outer_rect (window, width, height, &outer_rect);
1341 adjust_for_gravity_hints (window, &outer_rect, &x, &y);
1343 GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%ld,%ld,"
1344 "NOACTIVATE|NOZORDER)\n",
1345 GDK_WINDOW_HWND (window),
1346 x - _gdk_offset_x, y - _gdk_offset_y,
1347 outer_rect.right - outer_rect.left,
1348 outer_rect.bottom - outer_rect.top));
1350 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
1351 x - _gdk_offset_x, y - _gdk_offset_y,
1352 outer_rect.right - outer_rect.left,
1353 outer_rect.bottom - outer_rect.top,
1354 SWP_NOACTIVATE | SWP_NOZORDER));
1359 gdk_win32_window_move_resize (GdkWindow *window,
1366 GdkWindowImplWin32 *window_impl;
1368 window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1369 window_impl->inhibit_configure = TRUE;
1371 /* We ignore changes to the window being moved or resized by the
1372 user, as we don't want to fight the user */
1373 if (GDK_WINDOW_HWND (window) == _modal_move_resize_window)
1376 if (with_move && (width < 0 && height < 0))
1378 gdk_win32_window_move (window, x, y);
1384 gdk_win32_window_move_resize_internal (window, x, y, width, height);
1388 gdk_win32_window_resize (window, width, height);
1393 window_impl->inhibit_configure = FALSE;
1395 if (WINDOW_IS_TOPLEVEL (window))
1396 _gdk_win32_emit_configure_event (window);
1400 gdk_win32_window_reparent (GdkWindow *window,
1401 GdkWindow *new_parent,
1406 GdkWindow *old_parent;
1407 GdkWindowImplWin32 *impl;
1408 gboolean was_toplevel;
1412 new_parent = _gdk_root;
1414 old_parent = window->parent;
1415 parent = new_parent;
1416 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1418 GDK_NOTE (MISC, g_print ("gdk_win32_window_reparent: %p: %p\n",
1419 GDK_WINDOW_HWND (window),
1420 GDK_WINDOW_HWND (new_parent)));
1422 style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
1424 was_toplevel = GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) == GetDesktopWindow ();
1425 if (was_toplevel && new_parent != _gdk_root)
1427 /* Reparenting from top-level (child of desktop). Clear out
1430 style &= ~(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
1432 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1434 else if (new_parent == _gdk_root)
1436 /* Reparenting to top-level. Add decorations. */
1437 style &= ~(WS_CHILD);
1438 style |= WS_OVERLAPPEDWINDOW;
1439 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, style);
1442 API_CALL (SetParent, (GDK_WINDOW_HWND (window),
1443 GDK_WINDOW_HWND (new_parent)));
1445 API_CALL (MoveWindow, (GDK_WINDOW_HWND (window),
1446 x, y, window->width, window->height, TRUE));
1448 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1451 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1452 new_parent = _gdk_root;
1454 window->parent = new_parent;
1456 /* Switch the window type as appropriate */
1458 switch (GDK_WINDOW_TYPE (new_parent))
1460 case GDK_WINDOW_ROOT:
1461 if (impl->toplevel_window_type != -1)
1462 GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
1463 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1464 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1467 case GDK_WINDOW_TOPLEVEL:
1468 case GDK_WINDOW_CHILD:
1469 case GDK_WINDOW_TEMP:
1470 if (WINDOW_IS_TOPLEVEL (window))
1472 /* Save the original window type so we can restore it if the
1473 * window is reparented back to be a toplevel.
1475 impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
1476 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1481 old_parent->children =
1482 g_list_remove (old_parent->children, window);
1484 parent->children = g_list_prepend (parent->children, window);
1490 gdk_win32_window_raise (GdkWindow *window)
1492 if (!GDK_WINDOW_DESTROYED (window))
1494 GDK_NOTE (MISC, g_print ("gdk_win32_window_raise: %p\n",
1495 GDK_WINDOW_HWND (window)));
1497 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
1498 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOPMOST,
1500 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1501 else if (window->accept_focus)
1502 /* Do not wrap this in an API_CALL macro as SetForegroundWindow might
1503 * fail when for example dragging a window belonging to a different
1504 * application at the time of a gtk_window_present() call due to focus
1505 * stealing prevention. */
1506 SetForegroundWindow (GDK_WINDOW_HWND (window));
1508 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
1510 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1515 gdk_win32_window_lower (GdkWindow *window)
1517 if (!GDK_WINDOW_DESTROYED (window))
1519 GDK_NOTE (MISC, g_print ("gdk_win32_window_lower: %p\n"
1520 "... SetWindowPos(%p,HWND_BOTTOM,0,0,0,0,"
1521 "NOACTIVATE|NOMOVE|NOSIZE)\n",
1522 GDK_WINDOW_HWND (window),
1523 GDK_WINDOW_HWND (window)));
1525 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_BOTTOM,
1527 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
1532 gdk_win32_window_set_urgency_hint (GdkWindow *window,
1535 FLASHWINFO flashwinfo;
1536 typedef BOOL (WINAPI *PFN_FlashWindowEx) (FLASHWINFO*);
1537 PFN_FlashWindowEx flashWindowEx = NULL;
1539 g_return_if_fail (GDK_IS_WINDOW (window));
1540 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1542 if (GDK_WINDOW_DESTROYED (window))
1545 flashWindowEx = (PFN_FlashWindowEx) GetProcAddress (GetModuleHandle ("user32.dll"), "FlashWindowEx");
1549 flashwinfo.cbSize = sizeof (flashwinfo);
1550 flashwinfo.hwnd = GDK_WINDOW_HWND (window);
1552 flashwinfo.dwFlags = FLASHW_ALL | FLASHW_TIMER;
1554 flashwinfo.dwFlags = FLASHW_STOP;
1555 flashwinfo.uCount = 0;
1556 flashwinfo.dwTimeout = 0;
1558 flashWindowEx (&flashwinfo);
1562 FlashWindow (GDK_WINDOW_HWND (window), urgent);
1567 get_effective_window_decorations (GdkWindow *window,
1568 GdkWMDecoration *decoration)
1570 GdkWindowImplWin32 *impl;
1572 impl = (GdkWindowImplWin32 *)window->impl;
1574 if (gdk_window_get_decorations (window, decoration))
1577 if (window->window_type != GDK_WINDOW_TOPLEVEL)
1582 if ((impl->hint_flags & GDK_HINT_MIN_SIZE) &&
1583 (impl->hint_flags & GDK_HINT_MAX_SIZE) &&
1584 impl->hints.min_width == impl->hints.max_width &&
1585 impl->hints.min_height == impl->hints.max_height)
1587 *decoration = GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MAXIMIZE;
1589 if (impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
1590 impl->type_hint == GDK_WINDOW_TYPE_HINT_MENU ||
1591 impl->type_hint == GDK_WINDOW_TYPE_HINT_TOOLBAR)
1593 *decoration |= GDK_DECOR_MINIMIZE;
1595 else if (impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
1597 *decoration |= GDK_DECOR_MENU | GDK_DECOR_MINIMIZE;
1602 else if (impl->hint_flags & GDK_HINT_MAX_SIZE)
1604 *decoration = GDK_DECOR_ALL | GDK_DECOR_MAXIMIZE;
1605 if (impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
1606 impl->type_hint == GDK_WINDOW_TYPE_HINT_MENU ||
1607 impl->type_hint == GDK_WINDOW_TYPE_HINT_TOOLBAR)
1609 *decoration |= GDK_DECOR_MINIMIZE;
1616 switch (impl->type_hint)
1618 case GDK_WINDOW_TYPE_HINT_DIALOG:
1619 *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1622 case GDK_WINDOW_TYPE_HINT_MENU:
1623 *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1626 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
1627 case GDK_WINDOW_TYPE_HINT_UTILITY:
1628 gdk_window_set_skip_taskbar_hint (window, TRUE);
1629 gdk_window_set_skip_pager_hint (window, TRUE);
1630 *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1633 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
1634 *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MENU |
1635 GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
1638 case GDK_WINDOW_TYPE_HINT_DOCK:
1641 case GDK_WINDOW_TYPE_HINT_DESKTOP:
1646 case GDK_WINDOW_TYPE_HINT_NORMAL:
1647 *decoration = GDK_DECOR_ALL;
1656 gdk_win32_window_set_geometry_hints (GdkWindow *window,
1657 const GdkGeometry *geometry,
1658 GdkWindowHints geom_mask)
1660 GdkWindowImplWin32 *impl;
1663 g_return_if_fail (GDK_IS_WINDOW (window));
1665 if (GDK_WINDOW_DESTROYED (window))
1668 GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints: %p\n",
1669 GDK_WINDOW_HWND (window)));
1671 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1673 fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
1675 fi->hint_flags = geom_mask;
1677 impl->hint_flags = geom_mask;
1678 impl->hints = *geometry;
1680 if (geom_mask & GDK_HINT_POS)
1681 ; /* even the X11 mplementation doesn't care */
1683 if (geom_mask & GDK_HINT_MIN_SIZE)
1685 GDK_NOTE (MISC, g_print ("... MIN_SIZE: %dx%d\n",
1686 geometry->min_width, geometry->min_height));
1689 if (geom_mask & GDK_HINT_MAX_SIZE)
1691 GDK_NOTE (MISC, g_print ("... MAX_SIZE: %dx%d\n",
1692 geometry->max_width, geometry->max_height));
1695 if (geom_mask & GDK_HINT_BASE_SIZE)
1697 GDK_NOTE (MISC, g_print ("... BASE_SIZE: %dx%d\n",
1698 geometry->base_width, geometry->base_height));
1701 if (geom_mask & GDK_HINT_RESIZE_INC)
1703 GDK_NOTE (MISC, g_print ("... RESIZE_INC: (%d,%d)\n",
1704 geometry->width_inc, geometry->height_inc));
1707 if (geom_mask & GDK_HINT_ASPECT)
1709 GDK_NOTE (MISC, g_print ("... ASPECT: %g--%g\n",
1710 geometry->min_aspect, geometry->max_aspect));
1713 if (geom_mask & GDK_HINT_WIN_GRAVITY)
1715 GDK_NOTE (MISC, g_print ("... GRAVITY: %d\n", geometry->win_gravity));
1718 update_style_bits (window);
1722 gdk_win32_window_set_title (GdkWindow *window,
1727 g_return_if_fail (GDK_IS_WINDOW (window));
1728 g_return_if_fail (title != NULL);
1730 if (GDK_WINDOW_DESTROYED (window))
1733 /* Empty window titles not allowed, so set it to just a period. */
1737 GDK_NOTE (MISC, g_print ("gdk_window_set_title: %p: %s\n",
1738 GDK_WINDOW_HWND (window), title));
1740 GDK_NOTE (MISC_OR_EVENTS, title = g_strdup_printf ("%p %s", GDK_WINDOW_HWND (window), title));
1742 wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
1743 API_CALL (SetWindowTextW, (GDK_WINDOW_HWND (window), wtitle));
1746 GDK_NOTE (MISC_OR_EVENTS, g_free ((char *) title));
1750 gdk_win32_window_set_role (GdkWindow *window,
1753 g_return_if_fail (GDK_IS_WINDOW (window));
1755 GDK_NOTE (MISC, g_print ("gdk_window_set_role: %p: %s\n",
1756 GDK_WINDOW_HWND (window),
1757 (role ? role : "NULL")));
1762 gdk_win32_window_set_transient_for (GdkWindow *window,
1765 HWND window_id, parent_id;
1766 GdkWindowImplWin32 *window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1767 GdkWindowImplWin32 *parent_impl = NULL;
1770 g_return_if_fail (GDK_IS_WINDOW (window));
1772 window_id = GDK_WINDOW_HWND (window);
1773 parent_id = parent != NULL ? GDK_WINDOW_HWND (parent) : NULL;
1775 GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %p: %p\n", window_id, parent_id));
1777 if (GDK_WINDOW_DESTROYED (window) || (parent && GDK_WINDOW_DESTROYED (parent)))
1779 if (GDK_WINDOW_DESTROYED (window))
1780 GDK_NOTE (MISC, g_print ("... destroyed!\n"));
1782 GDK_NOTE (MISC, g_print ("... owner destroyed!\n"));
1787 if (window->window_type == GDK_WINDOW_CHILD)
1789 GDK_NOTE (MISC, g_print ("... a child window!\n"));
1795 GdkWindowImplWin32 *trans_impl = GDK_WINDOW_IMPL_WIN32 (window_impl->transient_owner->impl);
1796 if (trans_impl->transient_children != NULL)
1798 item = g_slist_find (trans_impl->transient_children, window);
1800 trans_impl->transient_children = g_slist_delete_link (trans_impl->transient_children, item);
1801 trans_impl->num_transients--;
1803 if (!trans_impl->num_transients)
1805 trans_impl->transient_children = NULL;
1808 g_object_unref (G_OBJECT (window_impl->transient_owner));
1809 g_object_unref (G_OBJECT (window));
1811 window_impl->transient_owner = NULL;
1815 parent_impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
1817 parent_impl->transient_children = g_slist_append (parent_impl->transient_children, window);
1818 g_object_ref (G_OBJECT (window));
1819 parent_impl->num_transients++;
1820 window_impl->transient_owner = parent;
1821 g_object_ref (G_OBJECT (parent));
1824 /* This changes the *owner* of the window, despite the misleading
1825 * name. (Owner and parent are unrelated concepts.) At least that's
1826 * what people who seem to know what they talk about say on
1827 * USENET. Search on Google.
1830 if (SetWindowLongPtr (window_id, GWLP_HWNDPARENT, (LONG_PTR) parent_id) == 0 &&
1831 GetLastError () != 0)
1832 WIN32_API_FAILED ("SetWindowLongPtr");
1836 _gdk_push_modal_window (GdkWindow *window)
1838 modal_window_stack = g_slist_prepend (modal_window_stack,
1843 _gdk_remove_modal_window (GdkWindow *window)
1847 g_return_if_fail (window != NULL);
1849 /* It's possible to be NULL here if someone sets the modal hint of the window
1850 * to FALSE before a modal window stack has ever been created. */
1851 if (modal_window_stack == NULL)
1854 /* Find the requested window in the stack and remove it. Yeah, I realize this
1855 * means we're not a 'real stack', strictly speaking. Sue me. :) */
1856 tmp = g_slist_find (modal_window_stack, window);
1859 modal_window_stack = g_slist_delete_link (modal_window_stack, tmp);
1864 _gdk_modal_blocked (GdkWindow *window)
1867 gboolean found_any = FALSE;
1869 for (l = modal_window_stack; l != NULL; l = l->next)
1871 GdkWindow *modal = l->data;
1873 if (modal == window)
1876 if (GDK_WINDOW_IS_MAPPED (modal))
1884 _gdk_modal_current (void)
1888 for (l = modal_window_stack; l != NULL; l = l->next)
1890 GdkWindow *modal = l->data;
1892 if (GDK_WINDOW_IS_MAPPED (modal))
1900 gdk_win32_window_set_background (GdkWindow *window,
1901 cairo_pattern_t *pattern)
1906 gdk_win32_window_set_device_cursor (GdkWindow *window,
1910 GdkWindowImplWin32 *impl;
1911 GdkWin32Cursor *cursor_private;
1913 HCURSOR hprevcursor;
1915 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1916 cursor_private = (GdkWin32Cursor*) cursor;
1918 if (GDK_WINDOW_DESTROYED (window))
1924 hcursor = cursor_private->hcursor;
1926 GDK_NOTE (MISC, g_print ("gdk_win32_window_set_cursor: %p: %p\n",
1927 GDK_WINDOW_HWND (window),
1930 /* First get the old cursor, if any (we wait to free the old one
1931 * since it may be the current cursor set in the Win32 API right
1934 hprevcursor = impl->hcursor;
1936 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
1938 if (hcursor == NULL)
1939 impl->hcursor = NULL;
1942 /* We must copy the cursor as it is OK to destroy the GdkCursor
1943 * while still in use for some window. See for instance
1944 * gimp_change_win_cursor() which calls gdk_window_set_cursor
1945 * (win, cursor), and immediately afterwards gdk_cursor_destroy
1948 if ((impl->hcursor = CopyCursor (hcursor)) == NULL)
1949 WIN32_API_FAILED ("CopyCursor");
1950 GDK_NOTE (MISC, g_print ("... CopyCursor (%p) = %p\n",
1951 hcursor, impl->hcursor));
1954 /* Destroy the previous cursor */
1955 if (hprevcursor != NULL)
1957 GDK_NOTE (MISC, g_print ("... DestroyCursor (%p)\n", hprevcursor));
1958 API_CALL (DestroyCursor, (hprevcursor));
1963 gdk_win32_window_get_geometry (GdkWindow *window,
1972 if (!GDK_WINDOW_DESTROYED (window))
1976 API_CALL (GetClientRect, (GDK_WINDOW_HWND (window), &rect));
1978 if (window != _gdk_root)
1981 GdkWindow *parent = gdk_window_get_parent (window);
1985 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1986 ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
1992 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
1993 ScreenToClient (GDK_WINDOW_HWND (parent), &pt);
1997 if (parent == _gdk_root)
1999 rect.left += _gdk_offset_x;
2000 rect.top += _gdk_offset_y;
2001 rect.right += _gdk_offset_x;
2002 rect.bottom += _gdk_offset_y;
2011 *width = rect.right - rect.left;
2013 *height = rect.bottom - rect.top;
2015 GDK_NOTE (MISC, g_print ("gdk_win32_window_get_geometry: %p: %ldx%ldx%d@%+ld%+ld\n",
2016 GDK_WINDOW_HWND (window),
2017 rect.right - rect.left, rect.bottom - rect.top,
2018 gdk_window_get_visual (window)->depth,
2019 rect.left, rect.top));
2024 gdk_win32_window_get_root_coords (GdkWindow *window,
2036 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
2041 *root_x = tx + _gdk_offset_x;
2043 *root_y = ty + _gdk_offset_y;
2045 GDK_NOTE (MISC, g_print ("gdk_win32_window_get_root_coords: %p: %+d%+d %+d%+d\n",
2046 GDK_WINDOW_HWND (window),
2048 tx + _gdk_offset_x, ty + _gdk_offset_y));
2053 gdk_win32_window_restack_under (GdkWindow *window,
2054 GList *native_siblings)
2060 gdk_win32_window_restack_toplevel (GdkWindow *window,
2068 gdk_win32_window_get_root_origin (GdkWindow *window,
2074 g_return_if_fail (GDK_IS_WINDOW (window));
2076 gdk_window_get_frame_extents (window, &rect);
2084 GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %p: %+d%+d\n",
2085 GDK_WINDOW_HWND (window), rect.x, rect.y));
2089 gdk_win32_window_get_frame_extents (GdkWindow *window,
2095 g_return_if_fail (GDK_IS_WINDOW (window));
2096 g_return_if_fail (rect != NULL);
2103 if (GDK_WINDOW_DESTROYED (window))
2106 /* FIXME: window is documented to be a toplevel GdkWindow, so is it really
2107 * necessary to walk its parent chain?
2109 while (window->parent && window->parent->parent)
2110 window = window->parent;
2112 hwnd = GDK_WINDOW_HWND (window);
2113 API_CALL (GetWindowRect, (hwnd, &r));
2115 rect->x = r.left + _gdk_offset_x;
2116 rect->y = r.top + _gdk_offset_y;
2117 rect->width = r.right - r.left;
2118 rect->height = r.bottom - r.top;
2120 GDK_NOTE (MISC, g_print ("gdk_window_get_frame_extents: %p: %ldx%ld@%+ld%+ld\n",
2121 GDK_WINDOW_HWND (window),
2122 r.right - r.left, r.bottom - r.top,
2127 gdk_window_win32_get_device_state (GdkWindow *window,
2131 GdkModifierType *mask)
2135 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
2137 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
2141 return (child != NULL);
2145 _gdk_windowing_get_device_state (GdkDisplay *display,
2150 GdkModifierType *mask)
2152 g_return_if_fail (display == _gdk_display);
2155 *screen = _gdk_screen;
2157 GDK_DEVICE_GET_CLASS (device)->query_state (device,
2158 gdk_screen_get_root_window (_gdk_screen),
2166 gdk_display_warp_device (GdkDisplay *display,
2172 g_return_if_fail (display == _gdk_display);
2173 g_return_if_fail (screen == _gdk_screen);
2174 g_return_if_fail (GDK_IS_DEVICE (device));
2175 g_return_if_fail (display == gdk_device_get_display (device));
2177 GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
2181 _gdk_windowing_window_at_device_position (GdkDisplay *display,
2185 GdkModifierType *mask,
2186 gboolean get_toplevel)
2188 return GDK_DEVICE_GET_CLASS (device)->window_at_position (device, win_x, win_y, mask, get_toplevel);
2192 gdk_win32_window_get_events (GdkWindow *window)
2194 GdkWindowImplWin32 *impl;
2196 if (GDK_WINDOW_DESTROYED (window))
2199 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2201 return impl->native_event_mask;
2205 gdk_win32_window_set_events (GdkWindow *window,
2206 GdkEventMask event_mask)
2208 GdkWindowImplWin32 *impl;
2210 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2212 /* gdk_window_new() always sets the GDK_STRUCTURE_MASK, so better
2213 * set it here, too. Not that I know or remember why it is
2214 * necessary, will have to test some day.
2216 impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask;
2220 do_shape_combine_region (GdkWindow *window,
2226 GetClientRect (GDK_WINDOW_HWND (window), &rect);
2227 _gdk_win32_adjust_client_rect (window, &rect);
2229 OffsetRgn (hrgn, -rect.left, -rect.top);
2230 OffsetRgn (hrgn, x, y);
2232 /* If this is a top-level window, add the title bar to the region */
2233 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL)
2235 HRGN tmp = CreateRectRgn (0, 0, rect.right - rect.left, -rect.top);
2236 CombineRgn (hrgn, hrgn, tmp, RGN_OR);
2240 SetWindowRgn (GDK_WINDOW_HWND (window), hrgn, TRUE);
2244 gdk_win32_window_set_override_redirect (GdkWindow *window,
2245 gboolean override_redirect)
2247 GdkWindowImplWin32 *window_impl;
2249 g_return_if_fail (GDK_IS_WINDOW (window));
2251 window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2253 window_impl->override_redirect = !!override_redirect;
2257 gdk_win32_window_set_accept_focus (GdkWindow *window,
2258 gboolean accept_focus)
2260 g_return_if_fail (GDK_IS_WINDOW (window));
2262 accept_focus = accept_focus != FALSE;
2264 if (window->accept_focus != accept_focus)
2265 window->accept_focus = accept_focus;
2269 gdk_win32_window_set_focus_on_map (GdkWindow *window,
2270 gboolean focus_on_map)
2272 g_return_if_fail (GDK_IS_WINDOW (window));
2274 focus_on_map = focus_on_map != FALSE;
2276 if (window->focus_on_map != focus_on_map)
2277 window->focus_on_map = focus_on_map;
2281 gdk_win32_window_set_icon_list (GdkWindow *window,
2284 GdkPixbuf *pixbuf, *big_pixbuf, *small_pixbuf;
2285 gint big_diff, small_diff;
2286 gint big_w, big_h, small_w, small_h;
2289 HICON small_hicon, big_hicon;
2290 GdkWindowImplWin32 *impl;
2291 gint i, big_i, small_i;
2293 g_return_if_fail (GDK_IS_WINDOW (window));
2295 if (GDK_WINDOW_DESTROYED (window))
2298 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2300 /* ideal sizes for small and large icons */
2301 big_w = GetSystemMetrics (SM_CXICON);
2302 big_h = GetSystemMetrics (SM_CYICON);
2303 small_w = GetSystemMetrics (SM_CXSMICON);
2304 small_h = GetSystemMetrics (SM_CYSMICON);
2306 /* find closest sized icons in the list */
2308 small_pixbuf = NULL;
2314 pixbuf = (GdkPixbuf*) pixbufs->data;
2315 w = gdk_pixbuf_get_width (pixbuf);
2316 h = gdk_pixbuf_get_height (pixbuf);
2318 dw = ABS (w - big_w);
2319 dh = ABS (h - big_h);
2320 diff = dw*dw + dh*dh;
2321 if (big_pixbuf == NULL || diff < big_diff)
2323 big_pixbuf = pixbuf;
2328 dw = ABS (w - small_w);
2329 dh = ABS (h - small_h);
2330 diff = dw*dw + dh*dh;
2331 if (small_pixbuf == NULL || diff < small_diff)
2333 small_pixbuf = pixbuf;
2338 pixbufs = g_list_next (pixbufs);
2342 /* Create the icons */
2343 big_hicon = _gdk_win32_pixbuf_to_hicon (big_pixbuf);
2344 small_hicon = _gdk_win32_pixbuf_to_hicon (small_pixbuf);
2347 SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_BIG,
2349 SendMessageW (GDK_WINDOW_HWND (window), WM_SETICON, ICON_SMALL,
2350 (LPARAM)small_hicon);
2352 /* Store the icons, destroying any previous icons */
2353 if (impl->hicon_big)
2354 GDI_CALL (DestroyIcon, (impl->hicon_big));
2355 impl->hicon_big = big_hicon;
2356 if (impl->hicon_small)
2357 GDI_CALL (DestroyIcon, (impl->hicon_small));
2358 impl->hicon_small = small_hicon;
2362 gdk_win32_window_set_icon_name (GdkWindow *window,
2365 /* In case I manage to confuse this again (or somebody else does):
2366 * Please note that "icon name" here really *does* mean the name or
2367 * title of an window minimized as an icon on the desktop, or in the
2368 * taskbar. It has nothing to do with the freedesktop.org icon
2372 g_return_if_fail (GDK_IS_WINDOW (window));
2374 if (GDK_WINDOW_DESTROYED (window))
2378 /* This is not the correct thing to do. We should keep both the
2379 * "normal" window title, and the icon name. When the window is
2380 * minimized, call SetWindowText() with the icon name, and when the
2381 * window is restored, with the normal window title. Also, the name
2382 * is in UTF-8, so we should do the normal conversion to either wide
2383 * chars or system codepage, and use either the W or A version of
2384 * SetWindowText(), depending on Windows version.
2386 API_CALL (SetWindowText, (GDK_WINDOW_HWND (window), name));
2391 gdk_win32_window_get_group (GdkWindow *window)
2393 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2394 g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
2396 if (GDK_WINDOW_DESTROYED (window))
2399 g_warning ("gdk_window_get_group not yet implemented");
2405 gdk_win32_window_set_group (GdkWindow *window,
2408 g_return_if_fail (GDK_IS_WINDOW (window));
2409 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2410 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
2412 if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
2415 g_warning ("gdk_window_set_group not implemented");
2419 update_single_bit (LONG *style,
2424 /* all controls the interpretation of gdk_bit -- if all is TRUE,
2425 * gdk_bit indicates whether style_bit is off; if all is FALSE, gdk
2426 * bit indicate whether style_bit is on
2428 if ((!all && gdk_bit) || (all && !gdk_bit))
2429 *style |= style_bit;
2431 *style &= ~style_bit;
2435 update_style_bits (GdkWindow *window)
2437 GdkWindowImplWin32 *impl = (GdkWindowImplWin32 *)window->impl;
2438 GdkWMDecoration decorations;
2439 LONG old_style, new_style, old_exstyle, new_exstyle;
2441 RECT rect, before, after;
2443 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
2446 old_style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2447 old_exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
2449 GetClientRect (GDK_WINDOW_HWND (window), &before);
2451 AdjustWindowRectEx (&before, old_style, FALSE, old_exstyle);
2453 new_style = old_style;
2454 new_exstyle = old_exstyle;
2456 if (window->window_type == GDK_WINDOW_TEMP)
2457 new_exstyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
2458 else if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
2459 new_exstyle |= WS_EX_TOOLWINDOW ;
2461 new_exstyle &= ~WS_EX_TOOLWINDOW;
2463 if (get_effective_window_decorations (window, &decorations))
2465 all = (decorations & GDK_DECOR_ALL);
2466 update_single_bit (&new_style, all, decorations & GDK_DECOR_BORDER, WS_BORDER);
2467 update_single_bit (&new_style, all, decorations & GDK_DECOR_RESIZEH, WS_THICKFRAME);
2468 update_single_bit (&new_style, all, decorations & GDK_DECOR_TITLE, WS_CAPTION);
2469 update_single_bit (&new_style, all, decorations & GDK_DECOR_MENU, WS_SYSMENU);
2470 update_single_bit (&new_style, all, decorations & GDK_DECOR_MINIMIZE, WS_MINIMIZEBOX);
2471 update_single_bit (&new_style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
2474 if (old_style == new_style && old_exstyle == new_exstyle )
2476 GDK_NOTE (MISC, g_print ("update_style_bits: %p: no change\n",
2477 GDK_WINDOW_HWND (window)));
2481 if (old_style != new_style)
2483 GDK_NOTE (MISC, g_print ("update_style_bits: %p: STYLE: %s => %s\n",
2484 GDK_WINDOW_HWND (window),
2485 _gdk_win32_window_style_to_string (old_style),
2486 _gdk_win32_window_style_to_string (new_style)));
2488 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, new_style);
2491 if (old_exstyle != new_exstyle)
2493 GDK_NOTE (MISC, g_print ("update_style_bits: %p: EXSTYLE: %s => %s\n",
2494 GDK_WINDOW_HWND (window),
2495 _gdk_win32_window_exstyle_to_string (old_exstyle),
2496 _gdk_win32_window_exstyle_to_string (new_exstyle)));
2498 SetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE, new_exstyle);
2501 AdjustWindowRectEx (&after, new_style, FALSE, new_exstyle);
2503 GetWindowRect (GDK_WINDOW_HWND (window), &rect);
2504 rect.left += after.left - before.left;
2505 rect.top += after.top - before.top;
2506 rect.right += after.right - before.right;
2507 rect.bottom += after.bottom - before.bottom;
2509 SetWindowPos (GDK_WINDOW_HWND (window), NULL,
2510 rect.left, rect.top,
2511 rect.right - rect.left, rect.bottom - rect.top,
2512 SWP_FRAMECHANGED | SWP_NOACTIVATE |
2513 SWP_NOREPOSITION | SWP_NOZORDER);
2518 update_single_system_menu_entry (HMENU hmenu,
2523 /* all controls the interpretation of gdk_bit -- if all is TRUE,
2524 * gdk_bit indicates whether menu entry is disabled; if all is
2525 * FALSE, gdk bit indicate whether menu entry is enabled
2527 if ((!all && gdk_bit) || (all && !gdk_bit))
2528 EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_ENABLED);
2530 EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_GRAYED);
2534 update_system_menu (GdkWindow *window)
2536 GdkWMFunction functions;
2539 if (_gdk_window_get_functions (window, &functions))
2541 HMENU hmenu = GetSystemMenu (GDK_WINDOW_HWND (window), FALSE);
2543 all = (functions & GDK_FUNC_ALL);
2544 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_RESIZE, SC_SIZE);
2545 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MOVE, SC_MOVE);
2546 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MINIMIZE, SC_MINIMIZE);
2547 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MAXIMIZE, SC_MAXIMIZE);
2548 update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_CLOSE, SC_CLOSE);
2553 get_decorations_quark ()
2555 static GQuark quark = 0;
2558 quark = g_quark_from_static_string ("gdk-window-decorations");
2564 gdk_win32_window_set_decorations (GdkWindow *window,
2565 GdkWMDecoration decorations)
2567 GdkWMDecoration* decorations_copy;
2569 g_return_if_fail (GDK_IS_WINDOW (window));
2571 GDK_NOTE (MISC, g_print ("gdk_window_set_decorations: %p: %s %s%s%s%s%s%s\n",
2572 GDK_WINDOW_HWND (window),
2573 (decorations & GDK_DECOR_ALL ? "clearing" : "setting"),
2574 (decorations & GDK_DECOR_BORDER ? "BORDER " : ""),
2575 (decorations & GDK_DECOR_RESIZEH ? "RESIZEH " : ""),
2576 (decorations & GDK_DECOR_TITLE ? "TITLE " : ""),
2577 (decorations & GDK_DECOR_MENU ? "MENU " : ""),
2578 (decorations & GDK_DECOR_MINIMIZE ? "MINIMIZE " : ""),
2579 (decorations & GDK_DECOR_MAXIMIZE ? "MAXIMIZE " : "")));
2581 decorations_copy = g_malloc (sizeof (GdkWMDecoration));
2582 *decorations_copy = decorations;
2583 g_object_set_qdata_full (G_OBJECT (window), get_decorations_quark (), decorations_copy, g_free);
2585 update_style_bits (window);
2589 gdk_win32_window_get_decorations (GdkWindow *window,
2590 GdkWMDecoration *decorations)
2592 GdkWMDecoration* decorations_set;
2594 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2596 decorations_set = g_object_get_qdata (G_OBJECT (window), get_decorations_quark ());
2597 if (decorations_set)
2598 *decorations = *decorations_set;
2600 return (decorations_set != NULL);
2604 get_functions_quark ()
2606 static GQuark quark = 0;
2609 quark = g_quark_from_static_string ("gdk-window-functions");
2615 gdk_win32_window_set_functions (GdkWindow *window,
2616 GdkWMFunction functions)
2618 GdkWMFunction* functions_copy;
2620 g_return_if_fail (GDK_IS_WINDOW (window));
2622 GDK_NOTE (MISC, g_print ("gdk_window_set_functions: %p: %s %s%s%s%s%s\n",
2623 GDK_WINDOW_HWND (window),
2624 (functions & GDK_FUNC_ALL ? "clearing" : "setting"),
2625 (functions & GDK_FUNC_RESIZE ? "RESIZE " : ""),
2626 (functions & GDK_FUNC_MOVE ? "MOVE " : ""),
2627 (functions & GDK_FUNC_MINIMIZE ? "MINIMIZE " : ""),
2628 (functions & GDK_FUNC_MAXIMIZE ? "MAXIMIZE " : ""),
2629 (functions & GDK_FUNC_CLOSE ? "CLOSE " : "")));
2631 functions_copy = g_malloc (sizeof (GdkWMFunction));
2632 *functions_copy = functions;
2633 g_object_set_qdata_full (G_OBJECT (window), get_functions_quark (), functions_copy, g_free);
2635 update_system_menu (window);
2639 _gdk_window_get_functions (GdkWindow *window,
2640 GdkWMFunction *functions)
2642 GdkWMFunction* functions_set;
2644 functions_set = g_object_get_qdata (G_OBJECT (window), get_functions_quark ());
2646 *functions = *functions_set;
2648 return (functions_set != NULL);
2652 gdk_win32_window_set_static_gravities (GdkWindow *window,
2653 gboolean use_static)
2655 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2661 gdk_win32_window_begin_resize_drag (GdkWindow *window,
2671 g_return_if_fail (GDK_IS_WINDOW (window));
2673 if (GDK_WINDOW_DESTROYED (window))
2676 /* Tell Windows to start interactively resizing the window by pretending that
2677 * the left pointer button was clicked in the suitable edge or corner. This
2678 * will only work if the button is down when this function is called, and
2679 * will only work with button 1 (left), since Windows only allows window
2680 * dragging using the left mouse button.
2685 /* Must break the automatic grab that occured when the button was
2686 * pressed, otherwise it won't work.
2688 gdk_display_pointer_ungrab (_gdk_display, 0);
2692 case GDK_WINDOW_EDGE_NORTH_WEST:
2693 winedge = HTTOPLEFT;
2696 case GDK_WINDOW_EDGE_NORTH:
2700 case GDK_WINDOW_EDGE_NORTH_EAST:
2701 winedge = HTTOPRIGHT;
2704 case GDK_WINDOW_EDGE_WEST:
2708 case GDK_WINDOW_EDGE_EAST:
2712 case GDK_WINDOW_EDGE_SOUTH_WEST:
2713 winedge = HTBOTTOMLEFT;
2716 case GDK_WINDOW_EDGE_SOUTH:
2720 case GDK_WINDOW_EDGE_SOUTH_EAST:
2722 winedge = HTBOTTOMRIGHT;
2726 DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, winedge,
2727 MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2731 gdk_win32_window_begin_move_drag (GdkWindow *window,
2738 g_return_if_fail (GDK_IS_WINDOW (window));
2740 if (GDK_WINDOW_DESTROYED (window))
2743 /* Tell Windows to start interactively moving the window by pretending that
2744 * the left pointer button was clicked in the titlebar. This will only work
2745 * if the button is down when this function is called, and will only work
2746 * with button 1 (left), since Windows only allows window dragging using the
2747 * left mouse button.
2752 /* Must break the automatic grab that occured when the button was pressed,
2753 * otherwise it won't work.
2755 gdk_display_pointer_ungrab (_gdk_display, 0);
2757 DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, HTCAPTION,
2758 MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
2763 * Setting window states
2766 gdk_win32_window_iconify (GdkWindow *window)
2768 HWND old_active_window;
2770 g_return_if_fail (GDK_IS_WINDOW (window));
2772 if (GDK_WINDOW_DESTROYED (window))
2775 GDK_NOTE (MISC, g_print ("gdk_window_iconify: %p: %s\n",
2776 GDK_WINDOW_HWND (window),
2777 _gdk_win32_window_state_to_string (window->state)));
2779 if (GDK_WINDOW_IS_MAPPED (window))
2781 old_active_window = GetActiveWindow ();
2782 ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
2783 if (old_active_window != GDK_WINDOW_HWND (window))
2784 SetActiveWindow (old_active_window);
2788 gdk_synthesize_window_state (window,
2790 GDK_WINDOW_STATE_ICONIFIED);
2795 gdk_win32_window_deiconify (GdkWindow *window)
2797 g_return_if_fail (GDK_IS_WINDOW (window));
2799 if (GDK_WINDOW_DESTROYED (window))
2802 GDK_NOTE (MISC, g_print ("gdk_window_deiconify: %p: %s\n",
2803 GDK_WINDOW_HWND (window),
2804 _gdk_win32_window_state_to_string (window->state)));
2806 if (GDK_WINDOW_IS_MAPPED (window))
2808 show_window_internal (window, GDK_WINDOW_IS_MAPPED (window), TRUE);
2812 gdk_synthesize_window_state (window,
2813 GDK_WINDOW_STATE_ICONIFIED,
2819 gdk_win32_window_stick (GdkWindow *window)
2821 g_return_if_fail (GDK_IS_WINDOW (window));
2823 if (GDK_WINDOW_DESTROYED (window))
2826 /* FIXME: Do something? */
2830 gdk_win32_window_unstick (GdkWindow *window)
2832 g_return_if_fail (GDK_IS_WINDOW (window));
2834 if (GDK_WINDOW_DESTROYED (window))
2837 /* FIXME: Do something? */
2841 gdk_win32_window_maximize (GdkWindow *window)
2843 g_return_if_fail (GDK_IS_WINDOW (window));
2845 if (GDK_WINDOW_DESTROYED (window))
2848 GDK_NOTE (MISC, g_print ("gdk_window_maximize: %p: %s\n",
2849 GDK_WINDOW_HWND (window),
2850 _gdk_win32_window_state_to_string (window->state)));
2852 if (GDK_WINDOW_IS_MAPPED (window))
2853 ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
2855 gdk_synthesize_window_state (window,
2857 GDK_WINDOW_STATE_MAXIMIZED);
2861 gdk_win32_window_unmaximize (GdkWindow *window)
2863 g_return_if_fail (GDK_IS_WINDOW (window));
2865 if (GDK_WINDOW_DESTROYED (window))
2868 GDK_NOTE (MISC, g_print ("gdk_window_unmaximize: %p: %s\n",
2869 GDK_WINDOW_HWND (window),
2870 _gdk_win32_window_state_to_string (window->state)));
2872 if (GDK_WINDOW_IS_MAPPED (window))
2873 ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
2875 gdk_synthesize_window_state (window,
2876 GDK_WINDOW_STATE_MAXIMIZED,
2881 gdk_win32_window_fullscreen (GdkWindow *window)
2883 gint x, y, width, height;
2888 g_return_if_fail (GDK_IS_WINDOW (window));
2890 fi = g_new (FullscreenInfo, 1);
2892 if (!GetWindowRect (GDK_WINDOW_HWND (window), &(fi->r)))
2896 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2898 monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
2899 mi.cbSize = sizeof (mi);
2900 if (monitor && GetMonitorInfo (monitor, &mi))
2902 x = mi.rcMonitor.left;
2903 y = mi.rcMonitor.top;
2904 width = mi.rcMonitor.right - x;
2905 height = mi.rcMonitor.bottom - y;
2910 width = GetSystemMetrics (SM_CXSCREEN);
2911 height = GetSystemMetrics (SM_CYSCREEN);
2914 /* remember for restoring */
2915 fi->hint_flags = impl->hint_flags;
2916 impl->hint_flags &= ~GDK_HINT_MAX_SIZE;
2917 g_object_set_data (G_OBJECT (window), "fullscreen-info", fi);
2918 fi->style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
2920 /* Send state change before configure event */
2921 gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
2923 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
2924 (fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP);
2926 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
2927 x, y, width, height,
2928 SWP_NOCOPYBITS | SWP_SHOWWINDOW));
2933 gdk_win32_window_unfullscreen (GdkWindow *window)
2937 g_return_if_fail (GDK_IS_WINDOW (window));
2939 fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
2942 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2944 gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
2946 impl->hint_flags = fi->hint_flags;
2947 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, fi->style);
2948 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_NOTOPMOST,
2949 fi->r.left, fi->r.top,
2950 fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
2951 SWP_NOCOPYBITS | SWP_SHOWWINDOW));
2953 g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
2955 update_style_bits (window);
2960 gdk_win32_window_set_keep_above (GdkWindow *window,
2963 g_return_if_fail (GDK_IS_WINDOW (window));
2965 if (GDK_WINDOW_DESTROYED (window))
2968 GDK_NOTE (MISC, g_print ("gdk_window_set_keep_above: %p: %s\n",
2969 GDK_WINDOW_HWND (window),
2970 setting ? "YES" : "NO"));
2972 if (GDK_WINDOW_IS_MAPPED (window))
2974 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
2975 setting ? HWND_TOPMOST : HWND_NOTOPMOST,
2977 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
2980 gdk_synthesize_window_state (window,
2981 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
2982 setting ? GDK_WINDOW_STATE_ABOVE : 0);
2986 gdk_win32_window_set_keep_below (GdkWindow *window,
2989 g_return_if_fail (GDK_IS_WINDOW (window));
2991 if (GDK_WINDOW_DESTROYED (window))
2994 GDK_NOTE (MISC, g_print ("gdk_window_set_keep_below: %p: %s\n",
2995 GDK_WINDOW_HWND (window),
2996 setting ? "YES" : "NO"));
2998 if (GDK_WINDOW_IS_MAPPED (window))
3000 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
3001 setting ? HWND_BOTTOM : HWND_NOTOPMOST,
3003 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
3006 gdk_synthesize_window_state (window,
3007 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
3008 setting ? GDK_WINDOW_STATE_BELOW : 0);
3012 gdk_win32_window_focus (GdkWindow *window,
3015 g_return_if_fail (GDK_IS_WINDOW (window));
3017 if (GDK_WINDOW_DESTROYED (window))
3020 GDK_NOTE (MISC, g_print ("gdk_window_focus: %p: %s\n",
3021 GDK_WINDOW_HWND (window),
3022 _gdk_win32_window_state_to_string (window->state)));
3024 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
3025 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMAXIMIZED);
3027 ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
3028 SetFocus (GDK_WINDOW_HWND (window));
3032 gdk_win32_window_set_modal_hint (GdkWindow *window,
3035 g_return_if_fail (GDK_IS_WINDOW (window));
3037 if (GDK_WINDOW_DESTROYED (window))
3040 GDK_NOTE (MISC, g_print ("gdk_window_set_modal_hint: %p: %s\n",
3041 GDK_WINDOW_HWND (window),
3042 modal ? "YES" : "NO"));
3044 if (modal == window->modal_hint)
3047 window->modal_hint = modal;
3050 /* Not sure about this one.. -- Cody */
3051 if (GDK_WINDOW_IS_MAPPED (window))
3052 API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
3053 modal ? HWND_TOPMOST : HWND_NOTOPMOST,
3055 SWP_NOMOVE | SWP_NOSIZE));
3060 _gdk_push_modal_window (window);
3061 gdk_window_raise (window);
3065 _gdk_remove_modal_window (window);
3072 gdk_win32_window_set_skip_taskbar_hint (GdkWindow *window,
3073 gboolean skips_taskbar)
3075 static GdkWindow *owner = NULL;
3078 g_return_if_fail (GDK_IS_WINDOW (window));
3080 GDK_NOTE (MISC, g_print ("gdk_window_set_skip_taskbar_hint: %p: %s, doing nothing\n",
3081 GDK_WINDOW_HWND (window),
3082 skips_taskbar ? "YES" : "NO"));
3084 // ### TODO: Need to figure out what to do here.
3092 wa.window_type = GDK_WINDOW_TEMP;
3093 wa.wclass = GDK_INPUT_OUTPUT;
3094 wa.width = wa.height = 1;
3096 owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
3100 SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_WINDOW_HWND (owner));
3102 #if 0 /* Should we also turn off the minimize and maximize buttons? */
3103 SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
3104 GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE) & ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU));
3106 SetWindowPos (GDK_WINDOW_HWND (window), NULL,
3108 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
3109 SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
3114 SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, 0);
3119 gdk_win32_window_set_skip_pager_hint (GdkWindow *window,
3120 gboolean skips_pager)
3122 g_return_if_fail (GDK_IS_WINDOW (window));
3124 GDK_NOTE (MISC, g_print ("gdk_window_set_skip_pager_hint: %p: %s, doing nothing\n",
3125 GDK_WINDOW_HWND (window),
3126 skips_pager ? "YES" : "NO"));
3130 gdk_win32_window_set_type_hint (GdkWindow *window,
3131 GdkWindowTypeHint hint)
3133 g_return_if_fail (GDK_IS_WINDOW (window));
3135 if (GDK_WINDOW_DESTROYED (window))
3140 static GEnumClass *class = NULL;
3142 class = g_type_class_ref (GDK_TYPE_WINDOW_TYPE_HINT);
3143 g_print ("gdk_window_set_type_hint: %p: %s\n",
3144 GDK_WINDOW_HWND (window),
3145 g_enum_get_value (class, hint)->value_name);
3148 ((GdkWindowImplWin32 *)window->impl)->type_hint = hint;
3150 update_style_bits (window);
3153 static GdkWindowTypeHint
3154 gdk_win32_window_get_type_hint (GdkWindow *window)
3156 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
3158 if (GDK_WINDOW_DESTROYED (window))
3159 return GDK_WINDOW_TYPE_HINT_NORMAL;
3161 return GDK_WINDOW_IMPL_WIN32 (window->impl)->type_hint;
3165 cairo_region_to_hrgn (const cairo_region_t *region,
3172 cairo_rectangle_int_t r;
3173 const int nrects = cairo_region_num_rectangles (region);
3175 sizeof (RGNDATAHEADER) + (sizeof (RECT) * nrects);
3178 rgndata = g_malloc (nbytes);
3179 rgndata->rdh.dwSize = sizeof (RGNDATAHEADER);
3180 rgndata->rdh.iType = RDH_RECTANGLES;
3181 rgndata->rdh.nCount = rgndata->rdh.nRgnSize = 0;
3182 SetRect (&rgndata->rdh.rcBound,
3183 G_MAXLONG, G_MAXLONG, G_MINLONG, G_MINLONG);
3185 for (i = 0; i < nrects; i++)
3187 rect = ((RECT *) rgndata->Buffer) + rgndata->rdh.nCount++;
3189 cairo_region_get_rectangle (region, i, &r);
3190 rect->left = r.x + x_origin;
3191 rect->right = rect->left + r.width;
3192 rect->top = r.y + y_origin;
3193 rect->bottom = rect->top + r.height;
3195 if (rect->left < rgndata->rdh.rcBound.left)
3196 rgndata->rdh.rcBound.left = rect->left;
3197 if (rect->right > rgndata->rdh.rcBound.right)
3198 rgndata->rdh.rcBound.right = rect->right;
3199 if (rect->top < rgndata->rdh.rcBound.top)
3200 rgndata->rdh.rcBound.top = rect->top;
3201 if (rect->bottom > rgndata->rdh.rcBound.bottom)
3202 rgndata->rdh.rcBound.bottom = rect->bottom;
3204 if ((hrgn = ExtCreateRegion (NULL, nbytes, rgndata)) == NULL)
3205 WIN32_API_FAILED ("ExtCreateRegion");
3213 gdk_win32_window_shape_combine_region (GdkWindow *window,
3214 const cairo_region_t *shape_region,
3218 if (GDK_WINDOW_DESTROYED (window))
3223 GDK_NOTE (MISC, g_print ("gdk_win32_window_shape_combine_region: %p: none\n",
3224 GDK_WINDOW_HWND (window)));
3225 SetWindowRgn (GDK_WINDOW_HWND (window), NULL, TRUE);
3231 hrgn = cairo_region_to_hrgn (shape_region, 0, 0);
3233 GDK_NOTE (MISC, g_print ("gdk_win32_window_shape_combine_region: %p: %p\n",
3234 GDK_WINDOW_HWND (window),
3237 do_shape_combine_region (window, hrgn, offset_x, offset_y);
3242 gdk_win32_window_lookup_for_display (GdkDisplay *display,
3245 g_return_val_if_fail (display == _gdk_display, NULL);
3247 return (GdkWindow*) gdk_win32_handle_table_lookup (anid);
3251 gdk_win32_window_set_opacity (GdkWindow *window,
3255 typedef BOOL (WINAPI *PFN_SetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
3256 PFN_SetLayeredWindowAttributes setLayeredWindowAttributes = NULL;
3258 g_return_if_fail (GDK_IS_WINDOW (window));
3259 g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
3261 if (GDK_WINDOW_DESTROYED (window))
3266 else if (opacity > 1)
3269 exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
3271 if (!(exstyle & WS_EX_LAYERED))
3272 SetWindowLong (GDK_WINDOW_HWND (window),
3274 exstyle | WS_EX_LAYERED);
3276 setLayeredWindowAttributes =
3277 (PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes");
3279 if (setLayeredWindowAttributes)
3281 API_CALL (setLayeredWindowAttributes, (GDK_WINDOW_HWND (window),
3288 static cairo_region_t *
3289 gdk_win32_window_get_shape (GdkWindow *window)
3291 HRGN hrgn = CreateRectRgn (0, 0, 0, 0);
3292 int type = GetWindowRgn (GDK_WINDOW_HWND (window), hrgn);
3294 if (type == SIMPLEREGION || type == COMPLEXREGION)
3296 cairo_region_t *region = _gdk_win32_hrgn_to_region (hrgn);
3298 DeleteObject (hrgn);
3306 _gdk_win32_window_queue_antiexpose (GdkWindow *window,
3307 cairo_region_t *area)
3309 HRGN hrgn = cairo_region_to_hrgn (area, 0, 0);
3311 GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
3312 GDK_WINDOW_HWND (window),
3313 _gdk_win32_cairo_region_to_string (area)));
3315 ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
3317 DeleteObject (hrgn);
3322 /* Gets called from gdwindow.c(do_move_region_bits_on_impl)
3323 * and got tested with testgtk::big_window. Given the previous,
3324 * untested implementation this one looks much too simple ;)
3327 _gdk_win32_window_translate (GdkWindow *window,
3328 cairo_region_t *area, /* In impl window coords */
3332 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
3333 GdkRectangle extents;
3335 HRGN hrgn, area_hrgn;
3339 /* Note: This is the destination area, not the source, and
3340 it has been moved by dx, dy from the source area */
3341 area_hrgn = cairo_region_to_hrgn (area, 0, 0);
3343 /* First we copy any outstanding invalid areas in the
3344 source area to the new position in the destination area */
3345 hrgn = CreateRectRgn (0, 0, 0, 0);
3346 ret = GetUpdateRgn (GDK_WINDOW_HWND (window), hrgn, FALSE);
3348 WIN32_API_FAILED ("GetUpdateRgn");
3349 else if (ret != NULLREGION)
3351 /* Convert the source invalid region as it would be copied */
3352 OffsetRgn (hrgn, dx, dy);
3353 /* Keep what intersects the copy destination area */
3354 ret = CombineRgn (hrgn, hrgn, area_hrgn, RGN_AND);
3355 /* And invalidate it */
3357 WIN32_API_FAILED ("CombineRgn");
3358 else if (ret != NULLREGION)
3359 API_CALL (InvalidateRgn, (GDK_WINDOW_HWND (window), hrgn, TRUE));
3362 /* Then we copy the bits, invalidating whatever is copied from
3363 otherwise invisible areas */
3365 hdc = _gdk_win32_impl_acquire_dc (impl);
3367 /* Clip hdc to target region */
3368 API_CALL (SelectClipRgn, (hdc, area_hrgn));
3370 cairo_region_get_extents (area, &extents);
3372 rect.left = MIN (extents.x, extents.x - dx);
3373 rect.top = MIN (extents.y, extents.y - dy);
3374 rect.right = MAX (extents.x + extents.width, extents.x - dx + extents.width);
3375 rect.bottom = MAX (extents.y + extents.height, extents.y - dy + extents.height);
3377 SetRectRgn (hrgn, 0, 0, 0, 0);
3379 if (!ScrollDC (hdc, dx, dy, &rect, NULL, hrgn, NULL))
3380 WIN32_GDI_FAILED ("ScrollDC");
3381 else if (!InvalidateRgn (GDK_WINDOW_HWND (window), hrgn, FALSE))
3382 WIN32_GDI_FAILED ("InvalidateRgn");
3384 /* Unset hdc clip region */
3385 API_CALL (SelectClipRgn, (hdc, NULL));
3387 _gdk_win32_impl_release_dc (impl);
3389 if (!DeleteObject (hrgn))
3390 WIN32_GDI_FAILED ("DeleteObject");
3392 if (!DeleteObject (area_hrgn))
3393 WIN32_GDI_FAILED ("DeleteObject");
3397 gdk_win32_input_shape_combine_region (GdkWindow *window,
3398 const cairo_region_t *shape_region,
3402 if (GDK_WINDOW_DESTROYED (window))
3404 /* CHECK: are these really supposed to be the same? */
3405 gdk_win32_window_shape_combine_region (window, shape_region, offset_x, offset_y);
3409 gdk_win32_window_process_updates_recurse (GdkWindow *window,
3410 cairo_region_t *region)
3412 _gdk_window_process_updates_recurse (window, region);
3416 gdk_win32_window_is_win32 (GdkWindow *window)
3418 return GDK_WINDOW_IS_WIN32 (window);
3422 * _gdk_win32_acquire_dc
3423 * @impl: a Win32 #GdkWindowImplWin32 implementation
3425 * Gets a DC with the given drawable selected into it.
3427 * Return value: The DC, on success. Otherwise
3428 * %NULL. If this function succeeded
3429 * _gdk_win32_impl_release_dc() must be called
3430 * release the DC when you are done using it.
3433 _gdk_win32_impl_acquire_dc (GdkWindowImplWin32 *impl)
3435 if (GDK_IS_WINDOW_IMPL_WIN32 (impl) &&
3436 GDK_WINDOW_DESTROYED (impl->wrapper))
3441 impl->hdc = GetDC (impl->handle);
3443 WIN32_GDI_FAILED ("GetDC");
3458 * _gdk_win32_impl_release_dc
3459 * @impl: a Win32 #GdkWindowImplWin32 implementation
3461 * Releases the reference count for the DC
3462 * from _gdk_win32_impl_acquire_dc()
3465 _gdk_win32_impl_release_dc (GdkWindowImplWin32 *impl)
3467 g_return_if_fail (impl->hdc_count > 0);
3470 if (impl->hdc_count == 0)
3472 if (impl->saved_dc_bitmap)
3474 GDI_CALL (SelectObject, (impl->hdc, impl->saved_dc_bitmap));
3475 impl->saved_dc_bitmap = NULL;
3480 GDI_CALL (ReleaseDC, (impl->handle, impl->hdc));
3487 gdk_win32_window_get_impl_hwnd (GdkWindow *window)
3489 if (GDK_WINDOW_IS_WIN32 (window))
3490 return GDK_WINDOW_HWND (window);
3495 gdk_win32_cairo_surface_destroy (void *data)
3497 GdkWindowImplWin32 *impl = data;
3499 _gdk_win32_impl_release_dc (impl);
3500 impl->cairo_surface = NULL;
3503 static cairo_surface_t *
3504 gdk_win32_ref_cairo_surface (GdkWindow *window)
3506 GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
3508 if (GDK_IS_WINDOW_IMPL_WIN32 (impl) &&
3509 GDK_WINDOW_DESTROYED (impl->wrapper))
3512 if (!impl->cairo_surface)
3514 HDC hdc = _gdk_win32_impl_acquire_dc (impl);
3518 impl->cairo_surface = cairo_win32_surface_create (hdc);
3520 cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
3521 impl, gdk_win32_cairo_surface_destroy);
3524 cairo_surface_reference (impl->cairo_surface);
3526 return impl->cairo_surface;
3530 gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
3532 GObjectClass *object_class = G_OBJECT_CLASS (klass);
3533 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
3535 parent_class = g_type_class_peek_parent (klass);
3537 object_class->finalize = gdk_window_impl_win32_finalize;
3539 impl_class->ref_cairo_surface = gdk_win32_ref_cairo_surface;
3541 impl_class->show = gdk_win32_window_show;
3542 impl_class->hide = gdk_win32_window_hide;
3543 impl_class->withdraw = gdk_win32_window_withdraw;
3544 impl_class->set_events = gdk_win32_window_set_events;
3545 impl_class->get_events = gdk_win32_window_get_events;
3546 impl_class->raise = gdk_win32_window_raise;
3547 impl_class->lower = gdk_win32_window_lower;
3548 impl_class->restack_under = gdk_win32_window_restack_under;
3549 impl_class->restack_toplevel = gdk_win32_window_restack_toplevel;
3550 impl_class->move_resize = gdk_win32_window_move_resize;
3551 impl_class->set_background = gdk_win32_window_set_background;
3552 impl_class->reparent = gdk_win32_window_reparent;
3553 impl_class->set_device_cursor = gdk_win32_window_set_device_cursor;
3554 impl_class->get_geometry = gdk_win32_window_get_geometry;
3555 impl_class->get_device_state = gdk_window_win32_get_device_state;
3556 impl_class->get_root_coords = gdk_win32_window_get_root_coords;
3558 impl_class->shape_combine_region = gdk_win32_window_shape_combine_region;
3559 impl_class->input_shape_combine_region = gdk_win32_input_shape_combine_region;
3560 impl_class->set_static_gravities = gdk_win32_window_set_static_gravities;
3561 impl_class->queue_antiexpose = _gdk_win32_window_queue_antiexpose;
3562 impl_class->translate = _gdk_win32_window_translate;
3563 impl_class->destroy = gdk_win32_window_destroy;
3564 impl_class->destroy_foreign = gdk_win32_window_destroy_foreign;
3565 impl_class->resize_cairo_surface = gdk_win32_window_resize_cairo_surface;
3566 impl_class->get_shape = gdk_win32_window_get_shape;
3567 //FIXME?: impl_class->get_input_shape = gdk_win32_window_get_input_shape;
3569 //impl_class->beep = gdk_x11_window_beep;
3571 impl_class->focus = gdk_win32_window_focus;
3572 impl_class->set_type_hint = gdk_win32_window_set_type_hint;
3573 impl_class->get_type_hint = gdk_win32_window_get_type_hint;
3574 impl_class->set_modal_hint = gdk_win32_window_set_modal_hint;
3575 impl_class->set_skip_taskbar_hint = gdk_win32_window_set_skip_taskbar_hint;
3576 impl_class->set_skip_pager_hint = gdk_win32_window_set_skip_pager_hint;
3577 impl_class->set_urgency_hint = gdk_win32_window_set_urgency_hint;
3578 impl_class->set_geometry_hints = gdk_win32_window_set_geometry_hints;
3579 impl_class->set_title = gdk_win32_window_set_title;
3580 impl_class->set_role = gdk_win32_window_set_role;
3581 //impl_class->set_startup_id = gdk_x11_window_set_startup_id;
3582 impl_class->set_transient_for = gdk_win32_window_set_transient_for;
3583 impl_class->get_root_origin = gdk_win32_window_get_root_origin;
3584 impl_class->get_frame_extents = gdk_win32_window_get_frame_extents;
3585 impl_class->set_override_redirect = gdk_win32_window_set_override_redirect;
3586 impl_class->set_accept_focus = gdk_win32_window_set_accept_focus;
3587 impl_class->set_focus_on_map = gdk_win32_window_set_focus_on_map;
3588 impl_class->set_icon_list = gdk_win32_window_set_icon_list;
3589 impl_class->set_icon_name = gdk_win32_window_set_icon_name;
3590 impl_class->iconify = gdk_win32_window_iconify;
3591 impl_class->deiconify = gdk_win32_window_deiconify;
3592 impl_class->stick = gdk_win32_window_stick;
3593 impl_class->unstick = gdk_win32_window_unstick;
3594 impl_class->maximize = gdk_win32_window_maximize;
3595 impl_class->unmaximize = gdk_win32_window_unmaximize;
3596 impl_class->fullscreen = gdk_win32_window_fullscreen;
3597 impl_class->unfullscreen = gdk_win32_window_unfullscreen;
3598 impl_class->set_keep_above = gdk_win32_window_set_keep_above;
3599 impl_class->set_keep_below = gdk_win32_window_set_keep_below;
3600 impl_class->get_group = gdk_win32_window_get_group;
3601 impl_class->set_group = gdk_win32_window_set_group;
3602 impl_class->set_decorations = gdk_win32_window_set_decorations;
3603 impl_class->get_decorations = gdk_win32_window_get_decorations;
3604 impl_class->set_functions = gdk_win32_window_set_functions;
3606 impl_class->begin_resize_drag = gdk_win32_window_begin_resize_drag;
3607 impl_class->begin_move_drag = gdk_win32_window_begin_move_drag;
3608 impl_class->set_opacity = gdk_win32_window_set_opacity;
3609 //impl_class->set_composited = gdk_win32_window_set_composited;
3610 impl_class->destroy_notify = gdk_win32_window_destroy_notify;
3611 impl_class->get_drag_protocol = _gdk_win32_window_get_drag_protocol;
3612 impl_class->register_dnd = _gdk_win32_window_register_dnd;
3613 impl_class->drag_begin = _gdk_win32_window_drag_begin;
3614 impl_class->process_updates_recurse = gdk_win32_window_process_updates_recurse;
3615 //? impl_class->sync_rendering = _gdk_win32_window_sync_rendering;
3616 impl_class->simulate_key = _gdk_win32_window_simulate_key;
3617 impl_class->simulate_button = _gdk_win32_window_simulate_button;
3618 impl_class->get_property = _gdk_win32_window_get_property;
3619 impl_class->change_property = _gdk_win32_window_change_property;
3620 impl_class->delete_property = _gdk_win32_window_delete_property;
3624 gdk_win32_window_get_handle (GdkWindow *window)
3626 /* Try to ensure the window has a native window */
3627 if (!_gdk_window_has_impl (window))
3628 gdk_window_ensure_native (window);
3630 if (!GDK_WINDOW_IS_WIN32 (window))
3632 g_warning (G_STRLOC " window is not a native Win32 window");
3636 return GDK_WINDOW_HWND (window);