Documentation fixes.
[wine] / dlls / x11drv / window.c
1 /*
2  * Window related functions
3  *
4  * Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard
5  * Copyright 1993 David Metcalfe
6  * Copyright 1995, 1996 Alex Korobka
7  */
8
9 #include "config.h"
10
11 #include <stdlib.h>
12
13 #include "ts_xlib.h"
14 #include "ts_xutil.h"
15
16 #include "winbase.h"
17 #include "wingdi.h"
18 #include "winreg.h"
19 #include "winuser.h"
20
21 #include "debugtools.h"
22 #include "x11drv.h"
23 #include "win.h"
24 #include "dce.h"
25 #include "options.h"
26
27 DEFAULT_DEBUG_CHANNEL(x11drv);
28
29 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
30
31 #define HAS_DLGFRAME(style,exStyle) \
32     (((exStyle) & WS_EX_DLGMODALFRAME) || \
33      (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
34
35 #define HAS_THICKFRAME(style,exStyle) \
36     (((style) & WS_THICKFRAME) && \
37      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38
39 #define HAS_THINFRAME(style) \
40     (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
41
42 /* X context to associate a hwnd to an X window */
43 XContext winContext = 0;
44
45 Atom wmProtocols = None;
46 Atom wmDeleteWindow = None;
47 Atom wmTakeFocus = None;
48 Atom dndProtocol = None;
49 Atom dndSelection = None;
50 Atom wmChangeState = None;
51 Atom kwmDockWindow = None;
52 Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
53
54
55 /***********************************************************************
56  *              is_window_managed
57  *
58  * Check if a given window should be managed
59  */
60 inline static BOOL is_window_managed( WND *win )
61 {
62     if (!Options.managed) return FALSE;
63
64     /* tray window is always managed */
65     if (win->dwExStyle & WS_EX_TRAYWINDOW) return TRUE;
66     /* child windows are not managed */
67     if (win->dwStyle & WS_CHILD) return FALSE;
68     /* tool windows are not managed */
69     if (win->dwExStyle & WS_EX_TOOLWINDOW) return FALSE;
70     /* windows with caption or thick frame are managed */
71     if ((win->dwStyle & WS_CAPTION) == WS_CAPTION) return TRUE;
72     if (win->dwStyle & WS_THICKFRAME) return TRUE;
73     /* default: not managed */
74     return FALSE;
75 }
76
77
78 /***********************************************************************
79  *              is_window_top_level
80  *
81  * Check if a given window is a top level X11 window
82  */
83 inline static BOOL is_window_top_level( WND *win )
84 {
85     return (root_window == DefaultRootWindow(gdi_display) &&
86             win->parent->hwndSelf == GetDesktopWindow());
87 }
88
89
90 /***********************************************************************
91  *              is_client_window_mapped
92  *
93  * Check if the X client window should be mapped
94  */
95 inline static BOOL is_client_window_mapped( WND *win )
96 {
97     struct x11drv_win_data *data = win->pDriverData;
98     return !IsIconic( win->hwndSelf ) && !IsRectEmpty( &data->client_rect );
99 }
100
101
102 /***********************************************************************
103  *              get_window_attributes
104  *
105  * Fill the window attributes structure for an X window.
106  * Returned cursor must be freed by caller.
107  */
108 static int get_window_attributes( Display *display, WND *win, XSetWindowAttributes *attr )
109 {
110     BOOL is_top_level = is_window_top_level( win );
111     BOOL managed = is_top_level && is_window_managed( win );
112
113     if (managed) win->dwExStyle |= WS_EX_MANAGED;
114     else win->dwExStyle &= ~WS_EX_MANAGED;
115
116     attr->override_redirect = !managed;
117     attr->colormap          = X11DRV_PALETTE_PaletteXColormap;
118     attr->save_under        = ((win->clsStyle & CS_SAVEBITS) != 0);
119     attr->cursor            = None;
120     attr->event_mask        = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
121                                ButtonPressMask | ButtonReleaseMask);
122     if (is_window_top_level( win ))
123     {
124         attr->event_mask |= StructureNotifyMask | FocusChangeMask;
125         attr->cursor = X11DRV_GetCursor( display, GlobalLock16(GetCursor()) );
126     }
127     return (CWOverrideRedirect | CWSaveUnder | CWEventMask | CWColormap | CWCursor);
128 }
129
130
131 /***********************************************************************
132  *              sync_window_style
133  *
134  * Change the X window attributes when the window style has changed.
135  */
136 static void sync_window_style( Display *display, WND *win )
137 {
138     XSetWindowAttributes attr;
139     int mask;
140
141     wine_tsx11_lock();
142     mask = get_window_attributes( display, win, &attr );
143     XChangeWindowAttributes( display, get_whole_window(win), mask, &attr );
144     if (attr.cursor) XFreeCursor( display, attr.cursor );
145     wine_tsx11_unlock();
146 }
147
148
149 /***********************************************************************
150  *              get_window_changes
151  *
152  * fill the window changes structure
153  */
154 static int get_window_changes( XWindowChanges *changes, const RECT *old, const RECT *new )
155 {
156     int mask = 0;
157
158     if (old->right - old->left != new->right - new->left )
159     {
160         if (!(changes->width = new->right - new->left)) changes->width = 1;
161         mask |= CWWidth;
162     }
163     if (old->bottom - old->top != new->bottom - new->top)
164     {
165         if (!(changes->height = new->bottom - new->top)) changes->height = 1;
166         mask |= CWHeight;
167     }
168     if (old->left != new->left)
169     {
170         changes->x = new->left;
171         mask |= CWX;
172     }
173     if (old->top != new->top)
174     {
175         changes->y = new->top;
176         mask |= CWY;
177     }
178     return mask;
179 }
180
181
182 /***********************************************************************
183  *              create_icon_window
184  */
185 static Window create_icon_window( Display *display, WND *win )
186 {
187     struct x11drv_win_data *data = win->pDriverData;
188     XSetWindowAttributes attr;
189
190     attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
191                        ButtonPressMask | ButtonReleaseMask);
192     attr.bit_gravity = NorthWestGravity;
193     attr.backing_store = NotUseful/*WhenMapped*/;
194
195     wine_tsx11_lock();
196     data->icon_window = XCreateWindow( display, root_window, 0, 0,
197                                        GetSystemMetrics( SM_CXICON ),
198                                        GetSystemMetrics( SM_CYICON ),
199                                        0, screen_depth,
200                                        InputOutput, visual,
201                                        CWEventMask | CWBitGravity | CWBackingStore, &attr );
202     XSaveContext( display, data->icon_window, winContext, (char *)win->hwndSelf );
203     wine_tsx11_unlock();
204
205     TRACE( "created %lx\n", data->icon_window );
206     SetPropA( win->hwndSelf, "__wine_x11_icon_window", (HANDLE)data->icon_window );
207     return data->icon_window;
208 }
209
210
211
212 /***********************************************************************
213  *              destroy_icon_window
214  */
215 inline static void destroy_icon_window( Display *display, WND *win )
216 {
217     struct x11drv_win_data *data = win->pDriverData;
218
219     if (!data->icon_window) return;
220     XDeleteContext( display, data->icon_window, winContext );
221     XDestroyWindow( display, data->icon_window );
222     data->icon_window = 0;
223     RemovePropA( win->hwndSelf, "__wine_x11_icon_window" );
224 }
225
226
227 /***********************************************************************
228  *              set_icon_hints
229  *
230  * Set the icon wm hints
231  */
232 static void set_icon_hints( Display *display, WND *wndPtr, XWMHints *hints )
233 {
234     X11DRV_WND_DATA *data = wndPtr->pDriverData;
235     HICON hIcon = GetClassLongA( wndPtr->hwndSelf, GCL_HICON );
236
237     if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
238     if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
239     data->hWMIconBitmap = 0;
240     data->hWMIconMask = 0;
241
242     if (!(wndPtr->dwExStyle & WS_EX_MANAGED))
243     {
244         destroy_icon_window( display, wndPtr );
245         hints->flags &= ~(IconPixmapHint | IconMaskHint | IconWindowHint);
246     }
247     else if (!hIcon)
248     {
249         if (!data->icon_window) create_icon_window( display, wndPtr );
250         hints->icon_window = data->icon_window;
251         hints->flags = (hints->flags & ~(IconPixmapHint | IconMaskHint)) | IconWindowHint;
252     }
253     else
254     {
255         HBITMAP hbmOrig;
256         RECT rcMask;
257         BITMAP bmMask;
258         ICONINFO ii;
259         HDC hDC;
260
261         GetIconInfo(hIcon, &ii);
262
263         X11DRV_CreateBitmap(ii.hbmMask);
264         X11DRV_CreateBitmap(ii.hbmColor);
265
266         GetObjectA(ii.hbmMask, sizeof(bmMask), &bmMask);
267         rcMask.top    = 0;
268         rcMask.left   = 0;
269         rcMask.right  = bmMask.bmWidth;
270         rcMask.bottom = bmMask.bmHeight;
271
272         hDC = CreateCompatibleDC(0);
273         hbmOrig = SelectObject(hDC, ii.hbmMask);
274         InvertRect(hDC, &rcMask);
275         SelectObject(hDC, hbmOrig);
276         DeleteDC(hDC);
277
278         data->hWMIconBitmap = ii.hbmColor;
279         data->hWMIconMask = ii.hbmMask;
280
281         hints->icon_pixmap = X11DRV_BITMAP_Pixmap(data->hWMIconBitmap);
282         hints->icon_mask = X11DRV_BITMAP_Pixmap(data->hWMIconMask);
283         destroy_icon_window( display, wndPtr );
284         hints->flags = (hints->flags & ~IconWindowHint) | IconPixmapHint | IconMaskHint;
285     }
286 }
287
288
289 /***********************************************************************
290  *              set_size_hints
291  *
292  * set the window size hints
293  */
294 static void set_size_hints( Display *display, WND *win )
295 {
296     XSizeHints* size_hints;
297     struct x11drv_win_data *data = win->pDriverData;
298
299     if ((size_hints = XAllocSizeHints()))
300     {
301         size_hints->win_gravity = StaticGravity;
302         size_hints->x = data->whole_rect.left;
303         size_hints->y = data->whole_rect.top;
304         size_hints->flags = PWinGravity | PPosition;
305
306         if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
307         {
308             size_hints->max_width = data->whole_rect.right - data->whole_rect.left;
309             size_hints->max_height = data->whole_rect.bottom - data->whole_rect.top;
310             size_hints->min_width = size_hints->max_width;
311             size_hints->min_height = size_hints->max_height;
312             size_hints->flags |= PMinSize | PMaxSize;
313         }
314         XSetWMNormalHints( display, data->whole_window, size_hints );
315         XFree( size_hints );
316     }
317 }
318
319
320 /***********************************************************************
321  *              set_wm_hints
322  *
323  * Set the window manager hints for a newly-created window
324  */
325 static void set_wm_hints( Display *display, WND *win )
326 {
327     struct x11drv_win_data *data = win->pDriverData;
328     Window group_leader;
329     XClassHint *class_hints;
330     XWMHints* wm_hints;
331     Atom protocols[2];
332     int i;
333
334     wine_tsx11_lock();
335
336     /* wm protocols */
337     i = 0;
338     protocols[i++] = wmDeleteWindow;
339     if (wmTakeFocus) protocols[i++] = wmTakeFocus;
340     XSetWMProtocols( display, data->whole_window, protocols, i );
341
342     /* class hints */
343     if ((class_hints = XAllocClassHint()))
344     {
345         class_hints->res_name = "wine";
346         class_hints->res_class = "Wine";
347         XSetClassHint( display, data->whole_window, class_hints );
348         XFree( class_hints );
349     }
350
351     /* transient for hint */
352     if (win->owner)
353     {
354         struct x11drv_win_data *owner_data = win->owner->pDriverData;
355         XSetTransientForHint( display, data->whole_window, owner_data->whole_window );
356         group_leader = owner_data->whole_window;
357     }
358     else group_leader = data->whole_window;
359
360     /* wm hints */
361     if ((wm_hints = XAllocWMHints()))
362     {
363         wm_hints->flags = InputHint | StateHint | WindowGroupHint;
364         /* use globally active model if take focus is supported,
365          * passive model otherwise (cf. ICCCM) */
366         wm_hints->input = !wmTakeFocus;
367
368         set_icon_hints( display, win, wm_hints );
369
370         wm_hints->initial_state = (win->dwStyle & WS_MINIMIZE) ? IconicState : NormalState;
371         wm_hints->window_group = group_leader;
372
373         XSetWMHints( display, data->whole_window, wm_hints );
374         XFree(wm_hints);
375     }
376
377     /* size hints */
378     set_size_hints( display, win );
379
380     /* systray properties (KDE only for now) */
381     if (win->dwExStyle & WS_EX_TRAYWINDOW)
382     {
383         int val = 1;
384         if (kwmDockWindow != None)
385             TSXChangeProperty( display, data->whole_window, kwmDockWindow, kwmDockWindow,
386                                32, PropModeReplace, (char*)&val, 1 );
387         if (_kde_net_wm_system_tray_window_for != None)
388             TSXChangeProperty( display, data->whole_window, _kde_net_wm_system_tray_window_for,
389                                XA_WINDOW, 32, PropModeReplace, (char*)&data->whole_window, 1 );
390     }
391
392     wine_tsx11_unlock();
393 }
394
395
396 /***********************************************************************
397  *              X11DRV_set_iconic_state
398  *
399  * Set the X11 iconic state according to the window style.
400  */
401 void X11DRV_set_iconic_state( WND *win )
402 {
403     Display *display = thread_display();
404     struct x11drv_win_data *data = win->pDriverData;
405     XWMHints* wm_hints;
406     BOOL iconic = IsIconic( win->hwndSelf );
407
408     if (!(win->dwExStyle & WS_EX_MANAGED))
409     {
410         if (iconic) TSXUnmapWindow( display, data->client_window );
411         else if (is_client_window_mapped( win )) TSXMapWindow( display, data->client_window );
412     }
413
414     wine_tsx11_lock();
415
416     if (!(wm_hints = XGetWMHints( display, data->whole_window ))) wm_hints = XAllocWMHints();
417     wm_hints->flags |= StateHint | IconPositionHint;
418     wm_hints->initial_state = iconic ? IconicState : NormalState;
419     wm_hints->icon_x = win->rectWindow.left;
420     wm_hints->icon_y = win->rectWindow.top;
421     XSetWMHints( display, data->whole_window, wm_hints );
422
423     if (win->dwStyle & WS_VISIBLE)
424     {
425         if (iconic)
426             XIconifyWindow( display, data->whole_window, DefaultScreen(display) );
427         else
428             if (!IsRectEmpty( &win->rectWindow )) XMapWindow( display, data->whole_window );
429     }
430
431     XFree(wm_hints);
432     wine_tsx11_unlock();
433 }
434
435
436 /***********************************************************************
437  *              X11DRV_window_to_X_rect
438  *
439  * Convert a rect from client to X window coordinates
440  */
441 void X11DRV_window_to_X_rect( WND *win, RECT *rect )
442 {
443     if (!(win->dwExStyle & WS_EX_MANAGED)) return;
444     if (win->dwStyle & WS_ICONIC) return;
445     if (IsRectEmpty( rect )) return;
446
447     if (HAS_THICKFRAME( win->dwStyle, win->dwExStyle ))
448         InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
449     else if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
450         InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME) );
451     else if (HAS_THINFRAME( win->dwStyle ))
452         InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
453
454     if ((win->dwStyle & WS_CAPTION) == WS_CAPTION)
455     {
456         if (win->dwExStyle & WS_EX_TOOLWINDOW)
457             rect->top += GetSystemMetrics(SM_CYSMCAPTION);
458         else
459             rect->top += GetSystemMetrics(SM_CYCAPTION);
460     }
461
462     if (win->dwExStyle & WS_EX_CLIENTEDGE)
463         InflateRect( rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE) );
464     if (win->dwExStyle & WS_EX_STATICEDGE)
465         InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
466
467     if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
468     if (rect->left >= rect->right) rect->right = rect->left + 1;
469 }
470
471
472 /***********************************************************************
473  *              X11DRV_X_to_window_rect
474  *
475  * Opposite of X11DRV_window_to_X_rect
476  */
477 void X11DRV_X_to_window_rect( WND *win, RECT *rect )
478 {
479     if (!(win->dwExStyle & WS_EX_MANAGED)) return;
480     if (win->dwStyle & WS_ICONIC) return;
481     if (IsRectEmpty( rect )) return;
482
483     if (HAS_THICKFRAME( win->dwStyle, win->dwExStyle ))
484         InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
485     else if (HAS_DLGFRAME( win->dwStyle, win->dwExStyle ))
486         InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
487     else if (HAS_THINFRAME( win->dwStyle ))
488         InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER) );
489
490     if ((win->dwStyle & WS_CAPTION) == WS_CAPTION)
491     {
492         if (win->dwExStyle & WS_EX_TOOLWINDOW)
493             rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
494         else
495             rect->top -= GetSystemMetrics(SM_CYCAPTION);
496     }
497
498     if (win->dwExStyle & WS_EX_CLIENTEDGE)
499         InflateRect( rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE) );
500     if (win->dwExStyle & WS_EX_STATICEDGE)
501         InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER) );
502
503     if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
504     if (rect->left >= rect->right) rect->right = rect->left + 1;
505 }
506
507
508 /***********************************************************************
509  *              X11DRV_sync_whole_window_position
510  *
511  * Synchronize the X whole window position with the Windows one
512  */
513 int X11DRV_sync_whole_window_position( Display *display, WND *win, int zorder )
514 {
515     XWindowChanges changes;
516     int mask;
517     struct x11drv_win_data *data = win->pDriverData;
518     RECT whole_rect = win->rectWindow;
519
520     X11DRV_window_to_X_rect( win, &whole_rect );
521     mask = get_window_changes( &changes, &data->whole_rect, &whole_rect );
522
523     if (zorder)
524     {
525         /* find window that this one must be after */
526         WND *prev = win->parent->child;
527         if (prev == win)  /* top child */
528         {
529             changes.stack_mode = Above;
530             mask |= CWStackMode;
531         }
532         else
533         {
534             while (prev && prev->next != win) prev = prev->next;
535             if (prev)
536             {
537                 changes.stack_mode = Below;
538                 changes.sibling = get_whole_window(prev);
539                 mask |= CWStackMode | CWSibling;
540             }
541             else ERR( "previous window not found for %x, list corrupted?\n", win->hwndSelf );
542         }
543     }
544
545     data->whole_rect = whole_rect;
546
547     if (mask)
548     {
549         TRACE( "setting win %lx pos %d,%d,%dx%d after %lx changes=%x\n",
550                data->whole_window, whole_rect.left, whole_rect.top,
551                whole_rect.right - whole_rect.left, whole_rect.bottom - whole_rect.top,
552                changes.sibling, mask );
553         wine_tsx11_lock();
554         XSync( gdi_display, False );  /* flush graphics operations before moving the window */
555         if (is_window_top_level( win ))
556         {
557             if (mask & (CWWidth|CWHeight)) set_size_hints( display, win );
558             XReconfigureWMWindow( display, data->whole_window,
559                                   DefaultScreen(display), mask, &changes );
560         }
561         else XConfigureWindow( display, data->whole_window, mask, &changes );
562         wine_tsx11_unlock();
563     }
564     return mask;
565 }
566
567
568 /***********************************************************************
569  *              X11DRV_sync_client_window_position
570  *
571  * Synchronize the X client window position with the Windows one
572  */
573 int X11DRV_sync_client_window_position( Display *display, WND *win )
574 {
575     XWindowChanges changes;
576     int mask;
577     struct x11drv_win_data *data = win->pDriverData;
578     RECT client_rect = win->rectClient;
579
580     OffsetRect( &client_rect, -data->whole_rect.left, -data->whole_rect.top );
581
582     if ((mask = get_window_changes( &changes, &data->client_rect, &client_rect )))
583     {
584         BOOL was_mapped = is_client_window_mapped( win );
585
586         TRACE( "setting win %lx pos %d,%d,%dx%d (was %d,%d,%dx%d) after %lx changes=%x\n",
587                data->client_window, client_rect.left, client_rect.top,
588                client_rect.right - client_rect.left, client_rect.bottom - client_rect.top,
589                data->client_rect.left, data->client_rect.top,
590                data->client_rect.right - data->client_rect.left,
591                data->client_rect.bottom - data->client_rect.top,
592                changes.sibling, mask );
593         data->client_rect = client_rect;
594         wine_tsx11_lock();
595         XSync( gdi_display, False );  /* flush graphics operations before moving the window */
596         if (was_mapped && !is_client_window_mapped( win ))
597             XUnmapWindow( display, data->client_window );
598         XConfigureWindow( display, data->client_window, mask, &changes );
599         if (!was_mapped && is_client_window_mapped( win ))
600             XMapWindow( display, data->client_window );
601         wine_tsx11_unlock();
602     }
603     return mask;
604 }
605
606
607 /***********************************************************************
608  *              X11DRV_register_window
609  *
610  * Associate an X window to a HWND.
611  */
612 void X11DRV_register_window( Display *display, HWND hwnd, struct x11drv_win_data *data )
613 {
614     wine_tsx11_lock();
615     XSaveContext( display, data->whole_window, winContext, (char *)hwnd );
616     XSaveContext( display, data->client_window, winContext, (char *)hwnd );
617     wine_tsx11_unlock();
618 }
619
620
621 /**********************************************************************
622  *              create_desktop
623  */
624 static void create_desktop( Display *display, WND *wndPtr )
625 {
626     X11DRV_WND_DATA *data = wndPtr->pDriverData;
627
628     wine_tsx11_lock();
629     winContext     = XUniqueContext();
630     wmProtocols    = XInternAtom( display, "WM_PROTOCOLS", False );
631     wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", False );
632 /*    wmTakeFocus    = XInternAtom( display, "WM_TAKE_FOCUS", False );*/
633     wmTakeFocus = 0;  /* not yet */
634     dndProtocol = XInternAtom( display, "DndProtocol" , False );
635     dndSelection = XInternAtom( display, "DndSelection" , False );
636     wmChangeState = XInternAtom (display, "WM_CHANGE_STATE", False);
637     kwmDockWindow = XInternAtom( display, "KWM_DOCKWINDOW", False );
638     _kde_net_wm_system_tray_window_for = XInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
639     wine_tsx11_unlock();
640
641     data->whole_window = data->client_window = root_window;
642
643     SetPropA( wndPtr->hwndSelf, "__wine_x11_whole_window", (HANDLE)root_window );
644     SetPropA( wndPtr->hwndSelf, "__wine_x11_client_window", (HANDLE)root_window );
645     SetPropA( wndPtr->hwndSelf, "__wine_x11_visual_id", (HANDLE)XVisualIDFromVisual(visual) );
646
647     if (root_window != DefaultRootWindow(display)) X11DRV_create_desktop_thread();
648 }
649
650
651 /**********************************************************************
652  *              create_whole_window
653  *
654  * Create the whole X window for a given window
655  */
656 static Window create_whole_window( Display *display, WND *win )
657 {
658     struct x11drv_win_data *data = win->pDriverData;
659     int cx, cy, mask;
660     XSetWindowAttributes attr;
661     Window parent;
662     RECT rect;
663     BOOL is_top_level = is_window_top_level( win );
664
665     rect = win->rectWindow;
666     X11DRV_window_to_X_rect( win, &rect );
667
668     if (!(cx = rect.right - rect.left)) cx = 1;
669     if (!(cy = rect.bottom - rect.top)) cy = 1;
670
671     parent = get_client_window( win->parent );
672
673     wine_tsx11_lock();
674
675     mask = get_window_attributes( display, win, &attr );
676
677     /* set the attributes that don't change over the lifetime of the window */
678     attr.bit_gravity       = ForgetGravity;
679     attr.win_gravity       = NorthWestGravity;
680     attr.backing_store     = NotUseful/*WhenMapped*/;
681     mask |= CWBitGravity | CWWinGravity | CWBackingStore;
682
683     data->whole_rect = rect;
684     data->whole_window = XCreateWindow( display, parent, rect.left, rect.top, cx, cy,
685                                         0, screen_depth, InputOutput, visual,
686                                         mask, &attr );
687     if (attr.cursor) XFreeCursor( display, attr.cursor );
688
689     if (!data->whole_window) goto done;
690
691     /* non-maximized child must be at bottom of Z order */
692     if ((win->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
693     {
694         XWindowChanges changes;
695         changes.stack_mode = Below;
696         XConfigureWindow( display, data->whole_window, CWStackMode, &changes );
697     }
698
699     if (is_top_level) set_wm_hints( display, win );
700
701  done:
702     wine_tsx11_unlock();
703     return data->whole_window;
704 }
705
706
707 /**********************************************************************
708  *              create_client_window
709  *
710  * Create the client window for a given window
711  */
712 static Window create_client_window( Display *display, WND *win )
713 {
714     struct x11drv_win_data *data = win->pDriverData;
715     RECT rect = data->whole_rect;
716     XSetWindowAttributes attr;
717
718     OffsetRect( &rect, -data->whole_rect.left, -data->whole_rect.top );
719     data->client_rect = rect;
720
721     attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
722                        ButtonPressMask | ButtonReleaseMask);
723     attr.bit_gravity = (win->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ?
724                        ForgetGravity : NorthWestGravity;
725     attr.backing_store = NotUseful/*WhenMapped*/;
726
727     wine_tsx11_lock();
728     data->client_window = XCreateWindow( display, data->whole_window, 0, 0,
729                                          max( rect.right - rect.left, 1 ),
730                                          max( rect.bottom - rect.top, 1 ),
731                                          0, screen_depth,
732                                          InputOutput, visual,
733                                          CWEventMask | CWBitGravity | CWBackingStore, &attr );
734     if (data->client_window && is_client_window_mapped( win ))
735         XMapWindow( display, data->client_window );
736     wine_tsx11_unlock();
737     return data->client_window;
738 }
739
740
741 /*****************************************************************
742  *              SetWindowText   (X11DRV.@)
743  */
744 BOOL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
745 {
746     Display *display = thread_display();
747     UINT count;
748     char *buffer;
749     static UINT text_cp = (UINT)-1;
750     Window win;
751     WND *wndPtr = WIN_FindWndPtr( hwnd );
752
753     if (!wndPtr) return FALSE;
754     if ((win = get_whole_window(wndPtr)))
755     {
756         if (text_cp == (UINT)-1)
757         {
758             HKEY hkey;
759             /* default value */
760             text_cp = CP_ACP;
761             if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
762             {
763                 char buffer[20];
764                 DWORD type, count = sizeof(buffer);
765                 if(!RegQueryValueExA(hkey, "TextCP", 0, &type, buffer, &count))
766                     text_cp = atoi(buffer);
767                 RegCloseKey(hkey);
768             }
769             TRACE("text_cp = %u\n", text_cp);
770         }
771
772         /* allocate new buffer for window text */
773         count = WideCharToMultiByte(text_cp, 0, text, -1, NULL, 0, NULL, NULL);
774         if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count * sizeof(WCHAR) )))
775         {
776             ERR("Not enough memory for window text\n");
777             WIN_ReleaseWndPtr( wndPtr );
778             return FALSE;
779         }
780         WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
781
782         wine_tsx11_lock();
783         XStoreName( display, win, buffer );
784         XSetIconName( display, win, buffer );
785         wine_tsx11_unlock();
786
787         HeapFree( GetProcessHeap(), 0, buffer );
788     }
789     WIN_ReleaseWndPtr( wndPtr );
790     return TRUE;
791 }
792
793
794 /***********************************************************************
795  *              DestroyWindow   (X11DRV.@)
796  */
797 BOOL X11DRV_DestroyWindow( HWND hwnd )
798 {
799     Display *display = thread_display();
800     WND *wndPtr = WIN_FindWndPtr( hwnd );
801     X11DRV_WND_DATA *data = wndPtr->pDriverData;
802
803     if (!data) goto done;
804
805     if (data->whole_window)
806     {
807         TRACE( "win %x xwin %lx/%lx\n", hwnd, data->whole_window, data->client_window );
808         wine_tsx11_lock();
809         XSync( gdi_display, False );  /* flush any reference to this drawable in GDI queue */
810         XDeleteContext( display, data->whole_window, winContext );
811         XDeleteContext( display, data->client_window, winContext );
812         XDestroyWindow( display, data->whole_window );  /* this destroys client too */
813         destroy_icon_window( display, wndPtr );
814         wine_tsx11_unlock();
815     }
816
817     if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap );
818     if (data->hWMIconMask) DeleteObject( data->hWMIconMask);
819     HeapFree( GetProcessHeap(), 0, data );
820     wndPtr->pDriverData = NULL;
821  done:
822     WIN_ReleaseWndPtr( wndPtr );
823     return TRUE;
824 }
825
826
827 /**********************************************************************
828  *              CreateWindow   (X11DRV.@)
829  */
830 BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
831 {
832     Display *display = thread_display();
833     WND *wndPtr;
834     struct x11drv_win_data *data;
835     RECT rect;
836     BOOL ret = FALSE;
837
838     if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)))) return FALSE;
839     data->whole_window  = 0;
840     data->client_window = 0;
841     data->icon_window   = 0;
842     data->hWMIconBitmap = 0;
843     data->hWMIconMask   = 0;
844
845     wndPtr = WIN_FindWndPtr( hwnd );
846     wndPtr->pDriverData = data;
847
848     if (!wndPtr->parent)
849     {
850         SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
851         create_desktop( display, wndPtr );
852         WIN_ReleaseWndPtr( wndPtr );
853         return TRUE;
854     }
855
856     if (!create_whole_window( display, wndPtr )) goto failed;
857     if (!create_client_window( display, wndPtr )) goto failed;
858     TSXSync( display, False );
859
860     WIN_ReleaseWndPtr( wndPtr );
861
862     SetPropA( hwnd, "__wine_x11_whole_window", (HANDLE)data->whole_window );
863     SetPropA( hwnd, "__wine_x11_client_window", (HANDLE)data->client_window );
864
865     /* send WM_NCCREATE */
866     TRACE( "hwnd %x cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy );
867     if (unicode)
868         ret = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
869     else
870         ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
871     if (!ret)
872     {
873         X11DRV_DestroyWindow( hwnd );
874         return FALSE;
875     }
876
877     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
878
879     sync_window_style( display, wndPtr );
880
881     /* send WM_NCCALCSIZE */
882     rect = wndPtr->rectWindow;
883     SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
884     if (rect.left > rect.right || rect.top > rect.bottom) rect = wndPtr->rectWindow;
885     wndPtr->rectClient = rect;
886     X11DRV_sync_client_window_position( display, wndPtr );
887     X11DRV_register_window( display, hwnd, data );
888
889     TRACE( "win %x window %d,%d,%d,%d client %d,%d,%d,%d whole %d,%d,%d,%d X client %d,%d,%d,%d xwin %x/%x\n",
890            hwnd, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
891            wndPtr->rectWindow.right, wndPtr->rectWindow.bottom,
892            wndPtr->rectClient.left, wndPtr->rectClient.top,
893            wndPtr->rectClient.right, wndPtr->rectClient.bottom,
894            data->whole_rect.left, data->whole_rect.top,
895            data->whole_rect.right, data->whole_rect.bottom,
896            data->client_rect.left, data->client_rect.top,
897            data->client_rect.right, data->client_rect.bottom,
898            (unsigned int)data->whole_window, (unsigned int)data->client_window );
899
900     if ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
901         WIN_LinkWindow( hwnd, HWND_BOTTOM );
902     else
903         WIN_LinkWindow( hwnd, HWND_TOP );
904
905     WIN_ReleaseWndPtr( wndPtr );
906
907     if (unicode)
908         ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
909     else
910         ret = (SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
911
912     if (!ret)
913     {
914         WIN_UnlinkWindow( hwnd );
915         X11DRV_DestroyWindow( hwnd );
916         return FALSE;
917     }
918
919     /* Send the size messages */
920
921     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
922     if (!(wndPtr->flags & WIN_NEED_SIZE))
923     {
924         /* send it anyway */
925         if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
926             ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
927             WARN("sending bogus WM_SIZE message 0x%08lx\n",
928                  MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
929                           wndPtr->rectClient.bottom-wndPtr->rectClient.top));
930         SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
931                       MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
932                                wndPtr->rectClient.bottom-wndPtr->rectClient.top));
933         SendMessageW( hwnd, WM_MOVE, 0,
934                       MAKELONG( wndPtr->rectClient.left, wndPtr->rectClient.top ) );
935     }
936
937     /* Show the window, maximizing or minimizing if needed */
938
939     if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
940     {
941         extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ); /*FIXME*/
942
943         RECT newPos;
944         UINT swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
945         wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
946         WINPOS_MinMaximize( hwnd, swFlag, &newPos );
947         swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
948             ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
949             : SWP_NOZORDER | SWP_FRAMECHANGED;
950         SetWindowPos( hwnd, 0, newPos.left, newPos.top,
951                       newPos.right, newPos.bottom, swFlag );
952     }
953
954     WIN_ReleaseWndPtr( wndPtr );
955     return TRUE;
956
957
958  failed:
959     X11DRV_DestroyWindow( wndPtr->hwndSelf );
960     WIN_ReleaseWndPtr( wndPtr );
961     return FALSE;
962 }
963
964
965 /***********************************************************************
966  *              X11DRV_get_client_window
967  *
968  * Return the X window associated with the client area of a window
969  */
970 Window X11DRV_get_client_window( HWND hwnd )
971 {
972     Window ret = 0;
973     WND *win = WIN_FindWndPtr( hwnd );
974     if (win)
975     {
976         struct x11drv_win_data *data = win->pDriverData;
977         ret = data->client_window;
978         WIN_ReleaseWndPtr( win );
979     }
980     return ret;
981 }
982
983
984 /***********************************************************************
985  *              X11DRV_get_whole_window
986  *
987  * Return the X window associated with the full area of a window
988  */
989 Window X11DRV_get_whole_window( HWND hwnd )
990 {
991     Window ret = 0;
992     WND *win = WIN_FindWndPtr( hwnd );
993     if (win)
994     {
995         struct x11drv_win_data *data = win->pDriverData;
996         ret = data->whole_window;
997         WIN_ReleaseWndPtr( win );
998     }
999     return ret;
1000 }
1001
1002
1003 /***********************************************************************
1004  *              X11DRV_get_top_window
1005  *
1006  * Return the X window associated with the top-level parent of a window
1007  */
1008 Window X11DRV_get_top_window( HWND hwnd )
1009 {
1010     Window ret = 0;
1011     WND *win = WIN_FindWndPtr( hwnd );
1012     while (win && win->parent->hwndSelf != GetDesktopWindow())
1013         WIN_UpdateWndPtr( &win, win->parent );
1014     if (win)
1015     {
1016         struct x11drv_win_data *data = win->pDriverData;
1017         ret = data->whole_window;
1018         WIN_ReleaseWndPtr( win );
1019     }
1020     return ret;
1021 }
1022
1023
1024 /*****************************************************************
1025  *              SetParent   (X11DRV.@)
1026  */
1027 HWND X11DRV_SetParent( HWND hwnd, HWND parent )
1028 {
1029     Display *display = thread_display();
1030     WND *wndPtr;
1031     WND *pWndParent;
1032     DWORD dwStyle;
1033     HWND retvalue;
1034
1035     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
1036
1037     dwStyle = wndPtr->dwStyle;
1038
1039     if (!parent) parent = GetDesktopWindow();
1040
1041     if (!(pWndParent = WIN_FindWndPtr(parent)))
1042     {
1043         WIN_ReleaseWndPtr( wndPtr );
1044         return 0;
1045     }
1046
1047     /* Windows hides the window first, then shows it again
1048      * including the WM_SHOWWINDOW messages and all */
1049     if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
1050
1051     retvalue = wndPtr->parent->hwndSelf;  /* old parent */
1052     if (pWndParent != wndPtr->parent)
1053     {
1054         struct x11drv_win_data *data = wndPtr->pDriverData;
1055
1056         WIN_UnlinkWindow(wndPtr->hwndSelf);
1057         wndPtr->parent = pWndParent;
1058         WIN_LinkWindow(wndPtr->hwndSelf, HWND_TOP);
1059
1060         if (parent != GetDesktopWindow()) /* a child window */
1061         {
1062             if (!(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
1063             {
1064                 DestroyMenu( (HMENU)wndPtr->wIDmenu );
1065                 wndPtr->wIDmenu = 0;
1066             }
1067         }
1068
1069         wine_tsx11_lock();
1070         sync_window_style( display, wndPtr );
1071         if (is_window_top_level( wndPtr )) set_wm_hints( display, wndPtr );
1072         XReparentWindow( display, data->whole_window, get_client_window(pWndParent),
1073                          data->whole_rect.left, data->whole_rect.top );
1074         wine_tsx11_unlock();
1075     }
1076     WIN_ReleaseWndPtr( pWndParent );
1077     WIN_ReleaseWndPtr( wndPtr );
1078
1079     /* SetParent additionally needs to make hwnd the topmost window
1080        in the x-order and send the expected WM_WINDOWPOSCHANGING and
1081        WM_WINDOWPOSCHANGED notification messages. 
1082     */
1083     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
1084                   SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
1085                   ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
1086     /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
1087      * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
1088
1089     return retvalue;
1090 }
1091
1092
1093 /*******************************************************************
1094  *              EnableWindow   (X11DRV.@)
1095  */
1096 BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable )
1097 {
1098     Display *display = thread_display();
1099     XWMHints *wm_hints;
1100     WND *wndPtr;
1101     BOOL retvalue;
1102
1103     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1104
1105     retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1106
1107     if (enable && (wndPtr->dwStyle & WS_DISABLED))
1108     {
1109         /* Enable window */
1110         wndPtr->dwStyle &= ~WS_DISABLED;
1111
1112         if (wndPtr->dwExStyle & WS_EX_MANAGED)
1113         {
1114             wine_tsx11_lock();
1115             if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) )))
1116                 wm_hints = XAllocWMHints();
1117             if (wm_hints)
1118             {
1119                 wm_hints->flags |= InputHint;
1120                 wm_hints->input = TRUE;
1121                 XSetWMHints( display, get_whole_window(wndPtr), wm_hints );
1122                 XFree(wm_hints);
1123             }
1124             wine_tsx11_unlock();
1125         }
1126
1127         SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1128     }
1129     else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1130     {
1131         SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0 );
1132
1133         /* Disable window */
1134         wndPtr->dwStyle |= WS_DISABLED;
1135
1136         if (wndPtr->dwExStyle & WS_EX_MANAGED)
1137         {
1138             wine_tsx11_lock();
1139             if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) )))
1140                 wm_hints = XAllocWMHints();
1141             if (wm_hints)
1142             {
1143                 wm_hints->flags |= InputHint;
1144                 wm_hints->input = FALSE;
1145                 XSetWMHints( display, get_whole_window(wndPtr), wm_hints );
1146                 XFree(wm_hints);
1147             }
1148             wine_tsx11_unlock();
1149         }
1150
1151         if (hwnd == GetFocus())
1152             SetFocus( 0 );  /* A disabled window can't have the focus */
1153
1154         if (hwnd == GetCapture())
1155             ReleaseCapture();  /* A disabled window can't capture the mouse */
1156
1157         SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1158     }
1159     WIN_ReleaseWndPtr(wndPtr);
1160     return retvalue;
1161 }
1162
1163
1164 /*****************************************************************
1165  *              SetFocus   (X11DRV.@)
1166  *
1167  * Set the X focus.
1168  * Explicit colormap management seems to work only with OLVWM.
1169  */
1170 void X11DRV_SetFocus( HWND hwnd )
1171 {
1172     Display *display = thread_display();
1173     XWindowAttributes win_attr;
1174     Window win;
1175     WND *wndPtr = WIN_FindWndPtr( hwnd );
1176     WND *w = wndPtr;
1177
1178     if (!wndPtr) return;
1179
1180     /* Only mess with the X focus if there's */
1181     /* no desktop window and if the window is not managed by the WM. */
1182     if (root_window != DefaultRootWindow(display)) goto done;
1183
1184     while (w && !get_whole_window(w)) w = w->parent;
1185     if (!w) goto done;
1186     if (w->dwExStyle & WS_EX_MANAGED) goto done;
1187
1188     if (!hwnd)  /* If setting the focus to 0, uninstall the colormap */
1189     {
1190         if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
1191             TSXUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
1192     }
1193     else if ((win = get_whole_window(w)))
1194     {
1195         /* Set X focus and install colormap */
1196         wine_tsx11_lock();
1197         if (XGetWindowAttributes( display, win, &win_attr ) &&
1198             (win_attr.map_state == IsViewable))
1199         {
1200             /* If window is not viewable, don't change anything */
1201
1202             /* we must not use CurrentTime (ICCCM), so try to use last message time instead */
1203             /* FIXME: this is not entirely correct */
1204             XSetInputFocus( display, win, RevertToParent,
1205                             /*CurrentTime*/ GetMessageTime() + X11DRV_server_startticks );
1206             if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
1207                 XInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
1208         }
1209         wine_tsx11_unlock();
1210     }
1211
1212  done:
1213     WIN_ReleaseWndPtr( wndPtr );
1214 }
1215
1216
1217 /**********************************************************************
1218  *              SetWindowIcon (X11DRV.@)
1219  *
1220  * hIcon or hIconSm has changed (or is being initialised for the
1221  * first time). Complete the X11 driver-specific initialisation
1222  * and set the window hints.
1223  *
1224  * This is not entirely correct, may need to create
1225  * an icon window and set the pixmap as a background
1226  */
1227 HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
1228 {
1229     Display *display = thread_display();
1230     WND *wndPtr = WIN_FindWndPtr( hwnd );
1231     int index = small ? GCL_HICONSM : GCL_HICON;
1232     HICON old;
1233
1234     if (!wndPtr) return 0;
1235
1236     old = GetClassLongW( hwnd, index );
1237     SetClassLongW( hwnd, index, icon );
1238
1239     SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
1240                   SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
1241
1242     if (wndPtr->dwExStyle & WS_EX_MANAGED)
1243     {
1244         Window win = get_whole_window(wndPtr);
1245         XWMHints* wm_hints = TSXGetWMHints( display, win );
1246
1247         if (!wm_hints) wm_hints = TSXAllocWMHints();
1248         if (wm_hints)
1249         {
1250             set_icon_hints( display, wndPtr, wm_hints );
1251             TSXSetWMHints( display, win, wm_hints );
1252             TSXFree( wm_hints );
1253         }
1254     }
1255
1256     WIN_ReleaseWndPtr( wndPtr );
1257     return old;
1258 }