gdkwindow-win32.c 89.7 KB
Newer Older
1 2
/* GDK - The GIMP Drawing Kit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3
 * Copyright (C) 1998-2004 Tor Lillqvist
4
 * Copyright (C) 2001-2009 Hans Breuer
Cody Russell's avatar
grabs  
Cody Russell committed
5
 * Copyright (C) 2007-2009 Cody Russell
6 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 10 11 12 13 14
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18 19 20 21 22 23
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
24
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
25 26 27 28 29
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

30
#include "config.h"
31 32
#include <stdlib.h>

Tor Lillqvist's avatar
Tor Lillqvist committed
33
#include "gdk.h"
34
#include "gdkwindowimpl.h"
35
#include "gdkprivate-win32.h"
36 37
#include "gdkdeviceprivate.h"
#include "gdkdevicemanager-win32.h"
38
#include "gdkenumtypes.h"
Hans Breuer's avatar
Hans Breuer committed
39

Tor Lillqvist's avatar
Tor Lillqvist committed
40 41 42 43 44
static void gdk_window_impl_win32_init       (GdkWindowImplWin32      *window);
static void gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass);
static void gdk_window_impl_win32_finalize   (GObject                 *object);

static gpointer parent_class = NULL;
45
static GSList *modal_window_stack = NULL;
Tor Lillqvist's avatar
Tor Lillqvist committed
46

47 48 49
static void     update_style_bits         (GdkWindow         *window);
static gboolean _gdk_window_get_functions (GdkWindow         *window,
                                           GdkWMFunction     *functions);
50

51 52
#define WINDOW_IS_TOPLEVEL(window)		   \
  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
53 54
   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
   GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
55

56 57
static void gdk_window_impl_iface_init (GdkWindowImplIface *iface);

58 59 60 61 62 63
GdkScreen *
GDK_WINDOW_SCREEN (GObject *win)
{
  return _gdk_screen;
}

Tor Lillqvist's avatar
Tor Lillqvist committed
64
GType
65
_gdk_window_impl_win32_get_type (void)
66
{
Tor Lillqvist's avatar
Tor Lillqvist committed
67 68 69
  static GType object_type = 0;

  if (!object_type)
70
    {
71
      const GTypeInfo object_info =
Tor Lillqvist's avatar
Tor Lillqvist committed
72 73 74 75 76 77 78 79 80 81 82
      {
        sizeof (GdkWindowImplWin32Class),
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gdk_window_impl_win32_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data */
        sizeof (GdkWindowImplWin32),
        0,              /* n_preallocs */
        (GInstanceInitFunc) gdk_window_impl_win32_init,
      };
83 84 85 86 87 88 89

      const GInterfaceInfo window_impl_info =
      {
	(GInterfaceInitFunc) gdk_window_impl_iface_init,
	NULL,
	NULL
      };
Tor Lillqvist's avatar
Tor Lillqvist committed
90 91 92
      
      object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_WIN32,
                                            "GdkWindowImplWin32",
Tor Lillqvist's avatar
Tor Lillqvist committed
93
                                            &object_info, 0);
94 95 96
      g_type_add_interface_static (object_type,
				   GDK_TYPE_WINDOW_IMPL,
				   &window_impl_info);
97
    }
Tor Lillqvist's avatar
Tor Lillqvist committed
98 99 100 101 102 103 104
  
  return object_type;
}

static void
gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
{
105
  impl->toplevel_window_type = -1;
Tor Lillqvist's avatar
Tor Lillqvist committed
106
  impl->hcursor = NULL;
107 108
  impl->hicon_big = NULL;
  impl->hicon_small = NULL;
Tor Lillqvist's avatar
Tor Lillqvist committed
109
  impl->hint_flags = 0;
110
  impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
Tor Lillqvist's avatar
Tor Lillqvist committed
111
  impl->extension_events_selected = FALSE;
112
  impl->transient_owner = NULL;
113 114 115
  impl->transient_children = NULL;
  impl->num_transients = 0;
  impl->changing_state = FALSE;
Tor Lillqvist's avatar
Tor Lillqvist committed
116
}
117

118
static void
Tor Lillqvist's avatar
Tor Lillqvist committed
119
gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
120
{
Tor Lillqvist's avatar
Tor Lillqvist committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  
  parent_class = g_type_class_peek_parent (klass);

  object_class->finalize = gdk_window_impl_win32_finalize;
}

static void
gdk_window_impl_win32_finalize (GObject *object)
{
  GdkWindowObject *wrapper;
  GdkDrawableImplWin32 *draw_impl;
  GdkWindowImplWin32 *window_impl;
  
  g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (object));

  draw_impl = GDK_DRAWABLE_IMPL_WIN32 (object);
  window_impl = GDK_WINDOW_IMPL_WIN32 (object);
  
  wrapper = (GdkWindowObject*) draw_impl->wrapper;

  if (!GDK_WINDOW_DESTROYED (wrapper))
143
    {
Tor Lillqvist's avatar
Tor Lillqvist committed
144
      gdk_win32_handle_table_remove (draw_impl->handle);
145 146
    }

Tor Lillqvist's avatar
Tor Lillqvist committed
147 148
  if (window_impl->hcursor != NULL)
    {
149 150
      if (GetCursor () == window_impl->hcursor)
	SetCursor (NULL);
151

152
      GDI_CALL (DestroyCursor, (window_impl->hcursor));
Tor Lillqvist's avatar
Tor Lillqvist committed
153 154
      window_impl->hcursor = NULL;
    }
155

156 157 158 159 160
  if (window_impl->hicon_big != NULL)
    {
      GDI_CALL (DestroyIcon, (window_impl->hicon_big));
      window_impl->hicon_big = NULL;
    }
161

162
  if (window_impl->hicon_small != NULL)
163
    {
164 165
      GDI_CALL (DestroyIcon, (window_impl->hicon_small));
      window_impl->hicon_small = NULL;
166
    }
167

Tor Lillqvist's avatar
Tor Lillqvist committed
168
  G_OBJECT_CLASS (parent_class)->finalize (object);
169
}
170

171 172 173 174 175 176 177 178 179 180 181
void
_gdk_win32_adjust_client_rect (GdkWindow *window,
			       RECT      *rect)
{
  LONG style, exstyle;

  style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
  exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
  API_CALL (AdjustWindowRectEx, (rect, style, FALSE, exstyle));
}

182 183 184
void
_gdk_root_window_size_init (void)
{
Cody Russell's avatar
grabs  
Cody Russell committed
185
  GdkWindowObject *window_object;
186 187 188
  GdkRectangle rect;
  int i;

Cody Russell's avatar
grabs  
Cody Russell committed
189
  window_object = GDK_WINDOW_OBJECT (_gdk_root);
190
  rect = _gdk_monitors[0].rect;
191
  for (i = 1; i < _gdk_num_monitors; i++)
192
    gdk_rectangle_union (&rect, &_gdk_monitors[i].rect, &rect);
193

Cody Russell's avatar
grabs  
Cody Russell committed
194 195
  window_object->width = rect.width;
  window_object->height = rect.height;
196 197
}

198
void
199
_gdk_windowing_window_init (GdkScreen *screen)
200
{
Tor Lillqvist's avatar
Tor Lillqvist committed
201 202
  GdkWindowObject *private;
  GdkDrawableImplWin32 *draw_impl;
203

204
  g_assert (_gdk_root == NULL);
Tor Lillqvist's avatar
Tor Lillqvist committed
205
  
206 207
  _gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL);
  private = (GdkWindowObject *)_gdk_root;
208
  private->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
209
  private->impl_window = private;
210
  private->visual = gdk_screen_get_system_visual (screen);
211

Tor Lillqvist's avatar
Tor Lillqvist committed
212
  draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
213
  
214
  draw_impl->handle = GetDesktopWindow ();
Tor Lillqvist's avatar
Tor Lillqvist committed
215 216 217 218
  draw_impl->wrapper = GDK_DRAWABLE (private);
  
  private->window_type = GDK_WINDOW_ROOT;
  private->depth = gdk_visual_get_system ()->depth;
219

220
  _gdk_root_window_size_init ();
221 222 223 224 225

  private->x = 0;
  private->y = 0;
  private->abs_x = 0;
  private->abs_y = 0;
226
  /* width and height already initialised in _gdk_root_window_size_init() */
227
  private->viewable = TRUE;
228

229
  gdk_win32_handle_table_insert ((HANDLE *) &draw_impl->handle, _gdk_root);
230

231
  GDK_NOTE (MISC, g_print ("_gdk_root=%p\n", GDK_WINDOW_HWND (_gdk_root)));
232 233 234 235 236 237 238 239 240 241 242
}

static const gchar *
get_default_title (void)
{
  const char *title;
  title = g_get_application_name ();
  if (!title)
    title = g_get_prgname ();

  return title;
Tor Lillqvist's avatar
Tor Lillqvist committed
243 244
}

245 246 247 248 249 250 251
/* RegisterGdkClass
 *   is a wrapper function for RegisterWindowClassEx.
 *   It creates at least one unique class for every 
 *   GdkWindowType. If support for single window-specific icons
 *   is ever needed (e.g Dialog specific), every such window should
 *   get its own class
 */
252
static ATOM
Cody Russell's avatar
Cody Russell committed
253
RegisterGdkClass (GdkWindowType wtype, GdkWindowTypeHint wtype_hint)
254
{
Cody Russell's avatar
Cody Russell committed
255 256 257 258
  static ATOM klassTOPLEVEL   = 0;
  static ATOM klassCHILD      = 0;
  static ATOM klassTEMP       = 0;
  static ATOM klassTEMPSHADOW = 0;
259
  static HICON hAppIcon = NULL;
260
  static HICON hAppIconSm = NULL;
261
  static WNDCLASSEXW wcl; 
262 263
  ATOM klass = 0;

264
  wcl.cbSize = sizeof (WNDCLASSEX);
265 266 267
  wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
                  * on WM_SIZE and WM_MOVE. Flicker, Performance!
                  */
268
  wcl.lpfnWndProc = _gdk_win32_window_procedure;
269 270
  wcl.cbClsExtra = 0;
  wcl.cbWndExtra = 0;
271
  wcl.hInstance = _gdk_app_hmodule;
272
  wcl.hIcon = 0;
273
  wcl.hIconSm = 0;
274

275
  /* initialize once! */
276
  if (0 == hAppIcon && 0 == hAppIconSm)
277
    {
278
      gchar sLoc [MAX_PATH+1];
279

280
      if (0 != GetModuleFileName (_gdk_app_hmodule, sLoc, MAX_PATH))
281 282
        {
          ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
283

284 285 286
          if (0 == hAppIcon && 0 == hAppIconSm)
            {
              if (0 != GetModuleFileName (_gdk_dll_hinstance, sLoc, MAX_PATH))
287 288 289
		{
		  ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
		}
290 291
            }
        }
292

293 294 295 296 297 298 299 300 301
      if (0 == hAppIcon && 0 == hAppIconSm)
        {
          hAppIcon = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
                                GetSystemMetrics (SM_CXICON),
                                GetSystemMetrics (SM_CYICON), 0);
          hAppIconSm = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
                                  GetSystemMetrics (SM_CXSMICON),
                                  GetSystemMetrics (SM_CYSMICON), 0);
        }
302
    }
303

304 305 306 307
  if (0 == hAppIcon)
    hAppIcon = hAppIconSm;
  else if (0 == hAppIconSm)
    hAppIconSm = hAppIcon;
308 309 310 311

  wcl.lpszMenuName = NULL;

  /* initialize once per class */
Hans Breuer's avatar
updated  
Hans Breuer committed
312 313 314 315 316
  /*
   * HB: Setting the background brush leads to flicker, because we
   * don't get asked how to clear the background. This is not what
   * we want, at least not for input_only windows ...
   */
317 318
#define ONCE_PER_CLASS() \
  wcl.hIcon = CopyIcon (hAppIcon); \
319
  wcl.hIconSm = CopyIcon (hAppIconSm); \
320
  wcl.hbrBackground = NULL; \
321 322 323
  wcl.hCursor = LoadCursor (NULL, IDC_ARROW); 
  
  switch (wtype)
324 325 326 327
    {
    case GDK_WINDOW_TOPLEVEL:
      if (0 == klassTOPLEVEL)
	{
328
	  wcl.lpszClassName = L"gdkWindowToplevel";
329
	  
330
	  ONCE_PER_CLASS ();
331
	  klassTOPLEVEL = RegisterClassExW (&wcl);
332 333 334 335
	}
      klass = klassTOPLEVEL;
      break;
      
336 337
    case GDK_WINDOW_CHILD:
      if (0 == klassCHILD)
Tor Lillqvist's avatar
Tor Lillqvist committed
338
	{
339
	  wcl.lpszClassName = L"gdkWindowChild";
Tor Lillqvist's avatar
Tor Lillqvist committed
340 341
	  
	  wcl.style |= CS_PARENTDC; /* MSDN: ... enhances system performance. */
342
	  ONCE_PER_CLASS ();
343
	  klassCHILD = RegisterClassExW (&wcl);
Tor Lillqvist's avatar
Tor Lillqvist committed
344
	}
345 346
      klass = klassCHILD;
      break;
347 348
      
    case GDK_WINDOW_TEMP:
Cody Russell's avatar
Cody Russell committed
349 350 351 352 353 354 355
      if ((wtype_hint == GDK_WINDOW_TYPE_HINT_MENU) ||
          (wtype_hint == GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU) ||
          (wtype_hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU) ||
          (wtype_hint == GDK_WINDOW_TYPE_HINT_TOOLTIP))
        {
          if (klassTEMPSHADOW == 0)
            {
356
              wcl.lpszClassName = L"gdkWindowTempShadow";
Cody Russell's avatar
Cody Russell committed
357
              wcl.style |= CS_SAVEBITS;
358 359 360 361 362 363
              if (LOBYTE (g_win32_get_windows_version()) > 0x05 ||
		  LOWORD (g_win32_get_windows_version()) == 0x0105)
		{
		  /* Windows XP (5.1) or above */
		  wcl.style |= 0x00020000; /* CS_DROPSHADOW */
		}
Cody Russell's avatar
Cody Russell committed
364
              ONCE_PER_CLASS ();
365
              klassTEMPSHADOW = RegisterClassExW (&wcl);
Cody Russell's avatar
Cody Russell committed
366 367 368 369 370 371 372 373
            }

          klass = klassTEMPSHADOW;
        }
       else
        {
          if (klassTEMP == 0)
            {
374
              wcl.lpszClassName = L"gdkWindowTemp";
Cody Russell's avatar
Cody Russell committed
375 376
              wcl.style |= CS_SAVEBITS;
              ONCE_PER_CLASS ();
377
              klassTEMP = RegisterClassExW (&wcl);
Cody Russell's avatar
Cody Russell committed
378 379 380 381
            }

          klass = klassTEMP;
        }
382 383 384 385 386 387 388
      break;
      
    default:
      g_assert_not_reached ();
      break;
    }
  
389 390
  if (klass == 0)
    {
391
      WIN32_API_FAILED ("RegisterClassExW");
392 393
      g_error ("That is a fatal error");
    }
394
  return klass;
395
}
396

397 398
void
_gdk_window_impl_new (GdkWindow     *window,
Cody Russell's avatar
Cody Russell committed
399 400 401 402 403
		      GdkWindow     *real_parent,
		      GdkScreen     *screen,
		      GdkEventMask   event_mask,
		      GdkWindowAttr *attributes,
		      gint           attributes_mask)
404
{
405
  HWND hwndNew;
406 407
  HANDLE hparent;
  ATOM klass = 0;
408
  DWORD dwStyle = 0, dwExStyle;
409
  RECT rect;
410
  GdkWindow *orig_parent;
Tor Lillqvist's avatar
Tor Lillqvist committed
411 412 413
  GdkWindowObject *private;
  GdkWindowImplWin32 *impl;
  GdkDrawableImplWin32 *draw_impl;
414
  const gchar *title;
415
  wchar_t *wtitle;
416
  gint window_width, window_height;
417
  gint offset_x = 0, offset_y = 0;
418

419
  private = (GdkWindowObject *)window;
420

421
  orig_parent = real_parent;
422

423
  GDK_NOTE (MISC,
424 425 426
	    g_print ("_gdk_window_impl_new: %s\n",
		     (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
		      (attributes->window_type == GDK_WINDOW_CHILD ? "CHILD" :
427
			(attributes->window_type == GDK_WINDOW_TEMP ? "TEMP" :
Tor Lillqvist's avatar
Tor Lillqvist committed
428
			 "???")))));
429

430
  hparent = GDK_WINDOW_HWND (real_parent);
431

432
  impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
433
  private->impl = (GdkDrawable *)impl;
Cody Russell's avatar
Cody Russell committed
434
  draw_impl = GDK_DRAWABLE_IMPL_WIN32 (impl);
Tor Lillqvist's avatar
Tor Lillqvist committed
435
  draw_impl->wrapper = GDK_DRAWABLE (window);
436

437
  // XXX: xattributes_mask = 0
438

439
#if 0
440 441 442 443
  if (attributes_mask & GDK_WA_VISUAL)
    visual = attributes->visual;
  else
    visual = gdk_visual_get_system ();
444
#endif
445

446
#if 0
447 448
  impl->width = (attributes->width > 1) ? (attributes->width) : (1);
  impl->height = (attributes->height > 1) ? (attributes->height) : (1);
449
#endif
450
  impl->extension_events_selected = FALSE;
451

452
  // XXX ?
453 454 455
  if (attributes->wclass == GDK_INPUT_OUTPUT)
    {
      dwExStyle = 0;
Tor Lillqvist's avatar
Tor Lillqvist committed
456 457

      private->input_only = FALSE;
458 459 460
    }
  else
    {
461 462 463 464
      /* I very much doubt using WS_EX_TRANSPARENT actually
       * corresponds to how X11 InputOnly windows work, but it appears
       * to work well enough for the actual use cases in gtk.
       */
465
      dwExStyle = WS_EX_TRANSPARENT;
Tor Lillqvist's avatar
Tor Lillqvist committed
466 467
      private->depth = 0;
      private->input_only = TRUE;
468
      GDK_NOTE (MISC, g_print ("... GDK_INPUT_ONLY\n"));
469 470
    }

Tor Lillqvist's avatar
Tor Lillqvist committed
471
  switch (private->window_type)
472 473
    {
    case GDK_WINDOW_TOPLEVEL:
474
      if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
Cody Russell's avatar
grabs  
Cody Russell committed
475 476 477 478
	{
	  /* The common code warns for this case. */
	  hparent = GetDesktopWindow ();
	}
479 480
      /* Children of foreign windows aren't toplevel windows */
      if (GDK_WINDOW_TYPE (orig_parent) == GDK_WINDOW_FOREIGN)
Cody Russell's avatar
grabs  
Cody Russell committed
481 482 483
	{
	  dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN;
	}
484
      else
Cody Russell's avatar
grabs  
Cody Russell committed
485 486 487 488 489
	{
	  if (private->window_type == GDK_WINDOW_TOPLEVEL)
	    dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
	  else
	    dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
490

Cody Russell's avatar
grabs  
Cody Russell committed
491 492 493
	  offset_x = _gdk_offset_x;
	  offset_y = _gdk_offset_y;
	}
494
      break;
Tor Lillqvist's avatar
Tor Lillqvist committed
495

496 497 498
    case GDK_WINDOW_CHILD:
      dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
      break;
Tor Lillqvist's avatar
Tor Lillqvist committed
499

500
    case GDK_WINDOW_TEMP:
501
      /* A temp window is not necessarily a top level window */
502
      dwStyle = (_gdk_root == real_parent ? WS_POPUP : WS_CHILDWINDOW);
503
      dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
504
      dwExStyle |= WS_EX_TOOLWINDOW;
505 506
      offset_x = _gdk_offset_x;
      offset_y = _gdk_offset_y;
507
      break;
Tor Lillqvist's avatar
Tor Lillqvist committed
508

509 510 511
    default:
      g_assert_not_reached ();
    }
512

Tor Lillqvist's avatar
Tor Lillqvist committed
513
  if (private->window_type != GDK_WINDOW_CHILD)
514
    {
515
      rect.left = rect.top = 0;
516 517
      rect.right = private->width;
      rect.bottom = private->height;
518

519
      AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
520

521 522 523 524 525
      window_width = rect.right - rect.left;
      window_height = rect.bottom - rect.top;
    }
  else
    {
526 527
      window_width = private->width;
      window_height = private->height;
528
    }
529 530 531

  if (attributes_mask & GDK_WA_TITLE)
    title = attributes->title;
532
  else
533 534
    title = get_default_title ();
  if (!title || !*title)
535
    title = "";
536 537 538

  private->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
      
Cody Russell's avatar
Cody Russell committed
539 540 541 542 543
  if (attributes_mask & GDK_WA_TYPE_HINT)
    impl->type_hint = attributes->type_hint;
  else
    impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;

544 545 546
  if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
    dwExStyle |= WS_EX_TOOLWINDOW;

547 548 549
  if (private->parent)
    private->parent->children = g_list_prepend (private->parent->children, window);

Cody Russell's avatar
Cody Russell committed
550
  klass = RegisterGdkClass (private->window_type, impl->type_hint);
551

552 553 554
  wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
  
  hwndNew = CreateWindowExW (dwExStyle,
555 556 557 558 559 560 561 562 563 564 565
			     MAKEINTRESOURCEW (klass),
			     wtitle,
			     dwStyle,
			     ((attributes_mask & GDK_WA_X) ?
			       private->x - offset_x : CW_USEDEFAULT),
			     private->y - offset_y,
			     window_width, window_height,
			     hparent,
			     NULL,
			     _gdk_app_hmodule,
			     window);
Tor Lillqvist's avatar
Update.  
Tor Lillqvist committed
566 567
  if (GDK_WINDOW_HWND (window) != hwndNew)
    {
568 569 570
      g_warning ("gdk_window_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
		 GDK_WINDOW_HWND (window),
		 hwndNew);
Tor Lillqvist's avatar
Update.  
Tor Lillqvist committed
571 572 573 574 575 576 577 578 579 580 581 582

      /* HB: IHMO due to a race condition the handle was increased by
       * one, which causes much trouble. Because I can't find the 
       * real bug, try to workaround it ...
       * To reproduce: compile with MSVC 5, DEBUG=1
       */
# if 0
      gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
      GDK_WINDOW_HWND (window) = hwndNew;
      gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
# else
      /* the old behaviour, but with warning */
583
      draw_impl->handle = hwndNew;
Tor Lillqvist's avatar
Update.  
Tor Lillqvist committed
584 585 586
# endif

    }
587

588
  g_object_ref (window);
Tor Lillqvist's avatar
Update.  
Tor Lillqvist committed
589
  gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
590

591
  GDK_NOTE (MISC, g_print ("... \"%s\" %dx%d@%+d%+d %p = %p\n",
592
			   title,
593 594
			   window_width, window_height,
			   ((attributes_mask & GDK_WA_X) ?
595 596
			    private->x - offset_x: CW_USEDEFAULT),
			   private->y - offset_y, 
597 598
			   hparent,
			   GDK_WINDOW_HWND (window)));
599

600 601 602
  /* Add window handle to title */
  GDK_NOTE (MISC_OR_EVENTS, gdk_window_set_title (window, title));

603
  g_free (wtitle);
604

Tor Lillqvist's avatar
Tor Lillqvist committed
605
  if (draw_impl->handle == NULL)
606
    {
607
      WIN32_API_FAILED ("CreateWindowExW");
608
      g_object_unref (window);
609
      return;
610 611
    }

612 613
//  if (!from_set_skip_taskbar_hint && private->window_type == GDK_WINDOW_TEMP)
//    gdk_window_set_skip_taskbar_hint (window, TRUE);
614

615 616 617
  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
				  (attributes->cursor) :
				  NULL));
618 619
}

620
GdkWindow *
621 622
gdk_window_foreign_new_for_display (GdkDisplay      *display,
                                    GdkNativeWindow  anid)
623 624
{
  GdkWindow *window;
Tor Lillqvist's avatar
Tor Lillqvist committed
625 626 627 628
  GdkWindowObject *private;
  GdkWindowImplWin32 *impl;
  GdkDrawableImplWin32 *draw_impl;

629 630 631 632
  HANDLE parent;
  RECT rect;
  POINT point;

633
  g_return_val_if_fail (display == _gdk_display, NULL);
634

Tor Lillqvist's avatar
Tor Lillqvist committed
635 636
  window = g_object_new (GDK_TYPE_WINDOW, NULL);
  private = (GdkWindowObject *)window;
637
  private->visual = gdk_screen_get_system_visual (_gdk_screen);
638
  private->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
Tor Lillqvist's avatar
Tor Lillqvist committed
639 640 641
  impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
  draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
  draw_impl->wrapper = GDK_DRAWABLE (window);
642
  parent = GetParent ((HWND)anid);
Tor Lillqvist's avatar
Tor Lillqvist committed
643
  
Tor Lillqvist's avatar
Tor Lillqvist committed
644
  private->parent = gdk_win32_handle_table_lookup ((GdkNativeWindow) parent);
645
  if (!private->parent || GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_FOREIGN)
646
    private->parent = (GdkWindowObject *)_gdk_root;
Tor Lillqvist's avatar
Tor Lillqvist committed
647
  
648
  private->parent->children = g_list_prepend (private->parent->children, window);
649

Tor Lillqvist's avatar
Tor Lillqvist committed
650
  draw_impl->handle = (HWND) anid;
651 652 653 654
  GetClientRect ((HWND) anid, &rect);
  point.x = rect.left;
  point.y = rect.right;
  ClientToScreen ((HWND) anid, &point);
655
  if (parent != GetDesktopWindow ())
656 657 658
    ScreenToClient (parent, &point);
  private->x = point.x;
  private->y = point.y;
659 660
  private->width = rect.right - rect.left;
  private->height = rect.bottom - rect.top;
Tor Lillqvist's avatar
Tor Lillqvist committed
661 662
  private->window_type = GDK_WINDOW_FOREIGN;
  private->destroyed = FALSE;
663
  private->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
Hans Breuer's avatar
updated  
Hans Breuer committed
664 665 666 667
  if (IsWindowVisible ((HWND) anid))
    private->state &= (~GDK_WINDOW_STATE_WITHDRAWN);
  else
    private->state |= GDK_WINDOW_STATE_WITHDRAWN;
Hans Breuer's avatar
Hans Breuer committed
668 669 670 671 672
  if (GetWindowLong ((HWND)anid, GWL_EXSTYLE) & WS_EX_TOPMOST)
    private->state |= GDK_WINDOW_STATE_ABOVE;
  else
    private->state &= (~GDK_WINDOW_STATE_ABOVE);
  private->state &= (~GDK_WINDOW_STATE_BELOW);
673
  private->viewable = TRUE;
Hans Breuer's avatar
Hans Breuer committed
674

Tor Lillqvist's avatar
Tor Lillqvist committed
675
  private->depth = gdk_visual_get_system ()->depth;
676

677
  g_object_ref (window);
Tor Lillqvist's avatar
Update.  
Tor Lillqvist committed
678
  gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
679

680 681 682 683 684
  GDK_NOTE (MISC, g_print ("gdk_window_foreign_new_for_display: %p: %s@%+d%+d\n",
			   (HWND) anid,
			   _gdk_win32_drawable_description (window),
			   private->x, private->y));

685 686 687
  return window;
}

688
void
689
_gdk_win32_window_destroy (GdkWindow *window,
690 691
			   gboolean   recursing,
			   gboolean   foreign_destroy)
692
{
Tor Lillqvist's avatar
Tor Lillqvist committed
693
  GdkWindowObject *private = (GdkWindowObject *)window;
694
  GdkWindowImplWin32 *window_impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
695
  GSList *tmp;
696

Tor Lillqvist's avatar
Tor Lillqvist committed
697 698
  g_return_if_fail (GDK_IS_WINDOW (window));
  
699
  GDK_NOTE (MISC, g_print ("_gdk_win32_window_destroy: %p\n",
700
			   GDK_WINDOW_HWND (window)));
701

702 703 704
  /* Remove ourself from the modal stack */
  _gdk_remove_modal_window (window);

705 706 707 708 709 710 711 712 713 714 715 716 717
  /* Remove all our transient children */
  tmp = window_impl->transient_children;
  while (tmp != NULL)
    {
      GdkWindow *child = tmp->data;
      GdkWindowImplWin32 *child_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (child)->impl);

      child_impl->transient_owner = NULL;
      tmp = g_slist_next (tmp);
    }
  g_slist_free (window_impl->transient_children);
  window_impl->transient_children = NULL;

718 719 720 721 722
  /* Remove ourself from our transient owner */
  if (window_impl->transient_owner != NULL)
    {
      gdk_window_set_transient_for (window, NULL);
    }
723 724

  if (!recursing && !foreign_destroy)
725
    {
Owen Taylor's avatar
Owen Taylor committed
726 727
      _gdk_win32_drawable_finish (private->impl);

728 729 730
      private->destroyed = TRUE;
      DestroyWindow (GDK_WINDOW_HWND (window));
    }
731

732
  gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
733 734
}

735
static cairo_surface_t *
736
gdk_win32_window_resize_cairo_surface (GdkWindow       *window,
737 738 739 740 741 742 743 744 745 746
                                       cairo_surface_t *surface,
                                       gint             width,
                                       gint             height)
{
  /* XXX: Make Cairo surface use DC clip */
  cairo_surface_destroy (surface);

  return NULL;
}

747 748 749
void
_gdk_windowing_window_destroy_foreign (GdkWindow *window)
{
750 751
  /* It's somebody else's window, but in our hierarchy, so reparent it
   * to the desktop, and then try to destroy it.
752 753 754 755
   */
  gdk_window_hide (window);
  gdk_window_reparent (window, NULL, 0, 0);
  
756
  PostMessage (GDK_WINDOW_HWND (window), WM_CLOSE, 0, 0);
757 758
}

759 760
/* This function is called when the window really gone.
 */
761 762 763
void
gdk_window_destroy_notify (GdkWindow *window)
{
764
  g_return_if_fail (GDK_IS_WINDOW (window));
765

766
  GDK_NOTE (EVENTS,
767
	    g_print ("gdk_window_destroy_notify: %p%s\n",
768
		     GDK_WINDOW_HWND (window),
769
		     (GDK_WINDOW_DESTROYED (window) ? " (destroyed)" : "")));
770

Tor Lillqvist's avatar
Tor Lillqvist committed
771
  if (!GDK_WINDOW_DESTROYED (window))
772
    {
773
      if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
774 775
	g_warning ("window %p unexpectedly destroyed",
		   GDK_WINDOW_HWND (window));
776

777
      _gdk_window_destroy (window, TRUE);
778 779
    }
  
Tor Lillqvist's avatar
Tor Lillqvist committed
780
  gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
781
  g_object_unref (window);
782 783
}

784 785 786 787 788 789 790 791 792 793
static void
get_outer_rect (GdkWindow *window,
		gint       width,
		gint       height,
		RECT      *rect)
{
  rect->left = rect->top = 0;
  rect->right = width;
  rect->bottom = height;
      
Tor Lillqvist's avatar
Tor Lillqvist committed
794
  _gdk_win32_adjust_client_rect (window, rect);
795 796 797
}

static void
798
adjust_for_gravity_hints (GdkWindow *window,
799 800 801
			  RECT      *outer_rect,
			  gint		*x,
			  gint		*y)
802
{
803 804 805 806 807 808
	GdkWindowObject *obj;
	GdkWindowImplWin32 *impl;

	obj = GDK_WINDOW_OBJECT (window);
	impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);

809 810 811 812 813 814 815 816 817 818
  if (impl->hint_flags & GDK_HINT_WIN_GRAVITY)
    {
      gint orig_x = *x, orig_y = *y;

      switch (impl->hints.win_gravity)
	{
	case GDK_GRAVITY_NORTH:
	case GDK_GRAVITY_CENTER:
	case GDK_GRAVITY_SOUTH:
	  *x -= (outer_rect->right - outer_rect->l