msvcrt: Added unicode modes support _setmode function.
[wine] / dlls / winemac.drv / window.c
1 /*
2  * MACDRV windowing driver
3  *
4  * Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard
5  * Copyright 1993 David Metcalfe
6  * Copyright 1995, 1996 Alex Korobka
7  * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25
26 #include "macdrv.h"
27 #include "winuser.h"
28 #include "wine/unicode.h"
29 #include "wine/server.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
32
33
34 static CRITICAL_SECTION win_data_section;
35 static CRITICAL_SECTION_DEBUG critsect_debug =
36 {
37     0, 0, &win_data_section,
38     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
39       0, 0, { (DWORD_PTR)(__FILE__ ": win_data_section") }
40 };
41 static CRITICAL_SECTION win_data_section = { &critsect_debug, -1, 0, 0, 0, 0 };
42
43 static CFMutableDictionaryRef win_datas;
44
45
46 /***********************************************************************
47  *              get_cocoa_window_features
48  */
49 static void get_cocoa_window_features(struct macdrv_win_data *data,
50                                       DWORD style, DWORD ex_style,
51                                       struct macdrv_window_features* wf)
52 {
53     memset(wf, 0, sizeof(*wf));
54
55     if (IsRectEmpty(&data->window_rect)) return;
56
57     if ((style & WS_CAPTION) == WS_CAPTION && !(ex_style & WS_EX_LAYERED))
58     {
59         wf->shadow = 1;
60         wf->title_bar = 1;
61         if (style & WS_SYSMENU) wf->close_button = 1;
62         if (style & WS_MINIMIZEBOX) wf->minimize_button = 1;
63         if (style & WS_MAXIMIZEBOX) wf->resizable = 1;
64         if (ex_style & WS_EX_TOOLWINDOW) wf->utility = 1;
65     }
66     if (ex_style & WS_EX_DLGMODALFRAME) wf->shadow = 1;
67     else if (style & WS_THICKFRAME)
68     {
69         wf->shadow = 1;
70         wf->resizable = 1;
71     }
72     else if ((style & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) wf->shadow = 1;
73 }
74
75
76 /***********************************************************************
77  *              get_mac_rect_offset
78  *
79  * Helper for macdrv_window_to_mac_rect and macdrv_mac_to_window_rect.
80  */
81 static void get_mac_rect_offset(struct macdrv_win_data *data, DWORD style, RECT *rect)
82 {
83     DWORD ex_style, style_mask = 0, ex_style_mask = 0;
84     struct macdrv_window_features wf;
85
86     rect->top = rect->bottom = rect->left = rect->right = 0;
87
88     ex_style = GetWindowLongW(data->hwnd, GWL_EXSTYLE);
89
90     get_cocoa_window_features(data, style, ex_style, &wf);
91
92     if (wf.title_bar) style_mask |= WS_CAPTION;
93     if (wf.shadow)
94     {
95         style_mask |= WS_DLGFRAME | WS_THICKFRAME;
96         ex_style_mask |= WS_EX_DLGMODALFRAME;
97     }
98
99     AdjustWindowRectEx(rect, style & style_mask, FALSE, ex_style & ex_style_mask);
100
101     TRACE("%p/%p style %08x ex_style %08x -> %s\n", data->hwnd, data->cocoa_window,
102           style, ex_style, wine_dbgstr_rect(rect));
103 }
104
105
106 /***********************************************************************
107  *              show_window
108  */
109 static void show_window(struct macdrv_win_data *data)
110 {
111     TRACE("win %p/%p\n", data->hwnd, data->cocoa_window);
112
113     data->on_screen = macdrv_order_cocoa_window(data->cocoa_window, NULL, NULL);
114 }
115
116
117 /***********************************************************************
118  *              hide_window
119  */
120 static void hide_window(struct macdrv_win_data *data)
121 {
122     TRACE("win %p/%p\n", data->hwnd, data->cocoa_window);
123
124     macdrv_hide_cocoa_window(data->cocoa_window);
125     data->on_screen = FALSE;
126 }
127
128
129 /***********************************************************************
130  *              macdrv_window_to_mac_rect
131  *
132  * Convert a rect from client to Mac window coordinates
133  */
134 static void macdrv_window_to_mac_rect(struct macdrv_win_data *data, DWORD style, RECT *rect)
135 {
136     RECT rc;
137
138     if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return;
139     if (IsRectEmpty(rect)) return;
140
141     get_mac_rect_offset(data, style, &rc);
142
143     rect->left   -= rc.left;
144     rect->right  -= rc.right;
145     rect->top    -= rc.top;
146     rect->bottom -= rc.bottom;
147     if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
148     if (rect->left >= rect->right) rect->right = rect->left + 1;
149 }
150
151
152 /***********************************************************************
153  *              macdrv_mac_to_window_rect
154  *
155  * Opposite of macdrv_window_to_mac_rect
156  */
157 static void macdrv_mac_to_window_rect(struct macdrv_win_data *data, RECT *rect)
158 {
159     RECT rc;
160     DWORD style = GetWindowLongW(data->hwnd, GWL_STYLE);
161
162     if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return;
163     if (IsRectEmpty(rect)) return;
164
165     get_mac_rect_offset(data, style, &rc);
166
167     rect->left   += rc.left;
168     rect->right  += rc.right;
169     rect->top    += rc.top;
170     rect->bottom += rc.bottom;
171     if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
172     if (rect->left >= rect->right) rect->right = rect->left + 1;
173 }
174
175
176 /***********************************************************************
177  *              constrain_window_frame
178  *
179  * Alter a window frame rectangle to fit within a) Cocoa's documented
180  * limits, and b) sane sizes, like twice the desktop rect.
181  */
182 static void constrain_window_frame(CGRect* frame)
183 {
184     CGRect desktop_rect = macdrv_get_desktop_rect();
185     int max_width, max_height;
186
187     max_width = min(32000, 2 * CGRectGetWidth(desktop_rect));
188     max_height = min(32000, 2 * CGRectGetHeight(desktop_rect));
189
190     if (frame->origin.x < -16000) frame->origin.x = -16000;
191     if (frame->origin.y < -16000) frame->origin.y = -16000;
192     if (frame->origin.x > 16000) frame->origin.x = 16000;
193     if (frame->origin.y > 16000) frame->origin.y = 16000;
194     if (frame->size.width > max_width) frame->size.width = max_width;
195     if (frame->size.height > max_height) frame->size.height = max_height;
196 }
197
198
199 /***********************************************************************
200  *              alloc_win_data
201  */
202 static struct macdrv_win_data *alloc_win_data(HWND hwnd)
203 {
204     struct macdrv_win_data *data;
205
206     if ((data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
207     {
208         data->hwnd = hwnd;
209         EnterCriticalSection(&win_data_section);
210         if (!win_datas)
211             win_datas = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
212         CFDictionarySetValue(win_datas, hwnd, data);
213     }
214     return data;
215 }
216
217
218 /***********************************************************************
219  *              get_win_data
220  *
221  * Lock and return the data structure associated with a window.
222  */
223 static struct macdrv_win_data *get_win_data(HWND hwnd)
224 {
225     struct macdrv_win_data *data;
226
227     if (!hwnd) return NULL;
228     EnterCriticalSection(&win_data_section);
229     if (win_datas && (data = (struct macdrv_win_data*)CFDictionaryGetValue(win_datas, hwnd)))
230         return data;
231     LeaveCriticalSection(&win_data_section);
232     return NULL;
233 }
234
235
236 /***********************************************************************
237  *              release_win_data
238  *
239  * Release the data returned by get_win_data.
240  */
241 static void release_win_data(struct macdrv_win_data *data)
242 {
243     if (data) LeaveCriticalSection(&win_data_section);
244 }
245
246
247 /***********************************************************************
248  *              macdrv_get_cocoa_window
249  *
250  * Return the Mac window associated with the full area of a window
251  */
252 static macdrv_window macdrv_get_cocoa_window(HWND hwnd)
253 {
254     struct macdrv_win_data *data = get_win_data(hwnd);
255     macdrv_window ret = data ? data->cocoa_window : NULL;
256     release_win_data(data);
257     return ret;
258 }
259
260
261 /***********************************************************************
262  *              set_cocoa_window_properties
263  *
264  * Set the window properties for a Cocoa window based on its Windows
265  * properties.
266  */
267 static void set_cocoa_window_properties(struct macdrv_win_data *data)
268 {
269     DWORD style, ex_style;
270     struct macdrv_window_features wf;
271
272     style = GetWindowLongW(data->hwnd, GWL_STYLE);
273     ex_style = GetWindowLongW(data->hwnd, GWL_EXSTYLE);
274
275     get_cocoa_window_features(data, style, ex_style, &wf);
276     macdrv_set_cocoa_window_features(data->cocoa_window, &wf);
277 }
278
279
280 /**********************************************************************
281  *              create_cocoa_window
282  *
283  * Create the whole Mac window for a given window
284  */
285 static void create_cocoa_window(struct macdrv_win_data *data)
286 {
287     WCHAR text[1024];
288     struct macdrv_window_features wf;
289     CGRect frame;
290     DWORD style, ex_style;
291
292     style = GetWindowLongW(data->hwnd, GWL_STYLE);
293     ex_style = GetWindowLongW(data->hwnd, GWL_EXSTYLE);
294
295     data->whole_rect = data->window_rect;
296     macdrv_window_to_mac_rect(data, style, &data->whole_rect);
297
298     memset(&wf, 0, sizeof(wf));
299     get_cocoa_window_features(data, style, ex_style, &wf);
300
301     frame = cgrect_from_rect(data->whole_rect);
302     constrain_window_frame(&frame);
303
304     TRACE("creating %p window %s whole %s client %s\n", data->hwnd, wine_dbgstr_rect(&data->window_rect),
305           wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
306
307     data->cocoa_window = macdrv_create_cocoa_window(&wf, frame);
308     if (!data->cocoa_window) return;
309
310     set_cocoa_window_properties(data);
311
312     /* set the window text */
313     if (!InternalGetWindowText(data->hwnd, text, sizeof(text)/sizeof(WCHAR))) text[0] = 0;
314     macdrv_set_cocoa_window_title(data->cocoa_window, text, strlenW(text));
315 }
316
317
318 /**********************************************************************
319  *              destroy_cocoa_window
320  *
321  * Destroy the whole Mac window for a given window.
322  */
323 static void destroy_cocoa_window(struct macdrv_win_data *data)
324 {
325     if (!data->cocoa_window) return;
326
327     TRACE("win %p Cocoa win %p\n", data->hwnd, data->cocoa_window);
328
329     macdrv_destroy_cocoa_window(data->cocoa_window);
330     data->cocoa_window = 0;
331     data->on_screen = FALSE;
332 }
333
334
335 /***********************************************************************
336  *              macdrv_create_win_data
337  *
338  * Create a Mac data window structure for an existing window.
339  */
340 static struct macdrv_win_data *macdrv_create_win_data(HWND hwnd, const RECT *window_rect,
341                                                       const RECT *client_rect)
342 {
343     struct macdrv_win_data *data;
344     HWND parent;
345
346     if (GetWindowThreadProcessId(hwnd, NULL) != GetCurrentThreadId()) return NULL;
347
348     if (!(parent = GetAncestor(hwnd, GA_PARENT)))  /* desktop */
349         return NULL;
350
351     /* don't create win data for HWND_MESSAGE windows */
352     if (parent != GetDesktopWindow() && !GetAncestor(parent, GA_PARENT)) return NULL;
353
354     if (!(data = alloc_win_data(hwnd))) return NULL;
355
356     data->whole_rect = data->window_rect = *window_rect;
357     data->client_rect = *client_rect;
358
359     if (parent == GetDesktopWindow())
360     {
361         create_cocoa_window(data);
362         TRACE("win %p/%p window %s whole %s client %s\n",
363                hwnd, data->cocoa_window, wine_dbgstr_rect(&data->window_rect),
364                wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
365     }
366
367     return data;
368 }
369
370
371 /***********************************************************************
372  *              sync_window_position
373  *
374  * Synchronize the Mac window position with the Windows one
375  */
376 static void sync_window_position(struct macdrv_win_data *data, UINT swp_flags)
377 {
378     CGRect frame = cgrect_from_rect(data->whole_rect);
379     constrain_window_frame(&frame);
380
381     data->on_screen = macdrv_set_cocoa_window_frame(data->cocoa_window, &frame);
382
383     TRACE("win %p/%p pos %s\n", data->hwnd, data->cocoa_window,
384           wine_dbgstr_rect(&data->whole_rect));
385
386     if (data->on_screen && (!(swp_flags & SWP_NOZORDER) || (swp_flags & SWP_SHOWWINDOW)))
387     {
388         HWND next = NULL;
389         macdrv_window prev_window = NULL;
390         macdrv_window next_window = NULL;
391
392         /* find window that this one must be after */
393         HWND prev = GetWindow(data->hwnd, GW_HWNDPREV);
394         while (prev && !((GetWindowLongW(prev, GWL_STYLE) & WS_VISIBLE) &&
395                          (prev_window = macdrv_get_cocoa_window(prev))))
396             prev = GetWindow(prev, GW_HWNDPREV);
397         if (!prev_window)
398         {
399             /* find window that this one must be before */
400             next = GetWindow(data->hwnd, GW_HWNDNEXT);
401             while (next && !((GetWindowLongW(next, GWL_STYLE) & WS_VISIBLE) &&
402                              (next_window = macdrv_get_cocoa_window(next))))
403                 next = GetWindow(next, GW_HWNDNEXT);
404         }
405
406         data->on_screen = macdrv_order_cocoa_window(data->cocoa_window, prev_window, next_window);
407
408         TRACE("win %p/%p below %p/%p above %p/%p\n",
409               data->hwnd, data->cocoa_window, prev, prev_window, next, next_window);
410     }
411 }
412
413
414 /***********************************************************************
415  *              move_window_bits
416  *
417  * Move the window bits when a window is moved.
418  */
419 static void move_window_bits(HWND hwnd, macdrv_window window, const RECT *old_rect, const RECT *new_rect,
420                              const RECT *old_client_rect, const RECT *new_client_rect,
421                              const RECT *new_window_rect)
422 {
423     RECT src_rect = *old_rect;
424     RECT dst_rect = *new_rect;
425     HDC hdc_src, hdc_dst;
426     HRGN rgn;
427     HWND parent = 0;
428
429     if (!window)
430     {
431         OffsetRect(&dst_rect, -new_window_rect->left, -new_window_rect->top);
432         parent = GetAncestor(hwnd, GA_PARENT);
433         hdc_src = GetDCEx(parent, 0, DCX_CACHE);
434         hdc_dst = GetDCEx(hwnd, 0, DCX_CACHE | DCX_WINDOW);
435     }
436     else
437     {
438         OffsetRect(&dst_rect, -new_client_rect->left, -new_client_rect->top);
439         /* make src rect relative to the old position of the window */
440         OffsetRect(&src_rect, -old_client_rect->left, -old_client_rect->top);
441         if (dst_rect.left == src_rect.left && dst_rect.top == src_rect.top) return;
442         hdc_src = hdc_dst = GetDCEx(hwnd, 0, DCX_CACHE);
443     }
444
445     rgn = CreateRectRgnIndirect(&dst_rect);
446     SelectClipRgn(hdc_dst, rgn);
447     DeleteObject(rgn);
448     ExcludeUpdateRgn(hdc_dst, hwnd);
449
450     TRACE("copying bits for win %p/%p %s -> %s\n", hwnd, window,
451           wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect));
452     BitBlt(hdc_dst, dst_rect.left, dst_rect.top,
453            dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top,
454            hdc_src, src_rect.left, src_rect.top, SRCCOPY);
455
456     ReleaseDC(hwnd, hdc_dst);
457     if (hdc_src != hdc_dst) ReleaseDC(parent, hdc_src);
458 }
459
460
461 /**********************************************************************
462  *              CreateDesktopWindow   (MACDRV.@)
463  */
464 BOOL CDECL macdrv_CreateDesktopWindow(HWND hwnd)
465 {
466     unsigned int width, height;
467
468     TRACE("%p\n", hwnd);
469
470     /* retrieve the real size of the desktop */
471     SERVER_START_REQ(get_window_rectangles)
472     {
473         req->handle = wine_server_user_handle(hwnd);
474         req->relative = COORDS_CLIENT;
475         wine_server_call(req);
476         width  = reply->window.right;
477         height = reply->window.bottom;
478     }
479     SERVER_END_REQ;
480
481     if (!width && !height)  /* not initialized yet */
482     {
483         CGRect rect = macdrv_get_desktop_rect();
484
485         SERVER_START_REQ(set_window_pos)
486         {
487             req->handle        = wine_server_user_handle(hwnd);
488             req->previous      = 0;
489             req->swp_flags     = SWP_NOZORDER;
490             req->window.left   = CGRectGetMinX(rect);
491             req->window.top    = CGRectGetMinY(rect);
492             req->window.right  = CGRectGetMaxX(rect);
493             req->window.bottom = CGRectGetMaxY(rect);
494             req->client        = req->window;
495             wine_server_call(req);
496         }
497         SERVER_END_REQ;
498     }
499
500     return TRUE;
501 }
502
503
504 /**********************************************************************
505  *              CreateWindow   (MACDRV.@)
506  */
507 BOOL CDECL macdrv_CreateWindow(HWND hwnd)
508 {
509     return TRUE;
510 }
511
512
513 /***********************************************************************
514  *              DestroyWindow   (MACDRV.@)
515  */
516 void CDECL macdrv_DestroyWindow(HWND hwnd)
517 {
518     struct macdrv_win_data *data;
519
520     TRACE("%p\n", hwnd);
521
522     if (!(data = get_win_data(hwnd))) return;
523
524     destroy_cocoa_window(data);
525
526     CFDictionaryRemoveValue(win_datas, hwnd);
527     release_win_data(data);
528     HeapFree(GetProcessHeap(), 0, data);
529 }
530
531
532 /*****************************************************************
533  *              SetParent   (MACDRV.@)
534  */
535 void CDECL macdrv_SetParent(HWND hwnd, HWND parent, HWND old_parent)
536 {
537     struct macdrv_win_data *data;
538
539     TRACE("%p, %p, %p\n", hwnd, parent, old_parent);
540
541     if (parent == old_parent) return;
542     if (!(data = get_win_data(hwnd))) return;
543
544     if (parent != GetDesktopWindow()) /* a child window */
545     {
546         if (old_parent == GetDesktopWindow())
547         {
548             /* destroy the old Mac window */
549             destroy_cocoa_window(data);
550         }
551     }
552     else  /* new top level window */
553         create_cocoa_window(data);
554     release_win_data(data);
555 }
556
557
558 /***********************************************************************
559  *              SetWindowStyle   (MACDRV.@)
560  *
561  * Update the state of the Cocoa window to reflect a style change
562  */
563 void CDECL macdrv_SetWindowStyle(HWND hwnd, INT offset, STYLESTRUCT *style)
564 {
565     struct macdrv_win_data *data;
566
567     TRACE("%p, %d, %p\n", hwnd, offset, style);
568
569     if (hwnd == GetDesktopWindow()) return;
570     if (!(data = get_win_data(hwnd))) return;
571
572     if (data->cocoa_window)
573         set_cocoa_window_properties(data);
574
575     release_win_data(data);
576 }
577
578
579 /*****************************************************************
580  *              SetWindowText   (MACDRV.@)
581  */
582 void CDECL macdrv_SetWindowText(HWND hwnd, LPCWSTR text)
583 {
584     macdrv_window win;
585
586     TRACE("%p, %s\n", hwnd, debugstr_w(text));
587
588     if ((win = macdrv_get_cocoa_window(hwnd)))
589         macdrv_set_cocoa_window_title(win, text, strlenW(text));
590 }
591
592
593 /***********************************************************************
594  *              WindowPosChanging   (MACDRV.@)
595  */
596 void CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags,
597                                     const RECT *window_rect, const RECT *client_rect,
598                                     RECT *visible_rect, struct window_surface **surface)
599 {
600     struct macdrv_win_data *data = get_win_data(hwnd);
601     DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
602
603     TRACE("%p after %p swp %04x window %s client %s visible %s surface %p\n", hwnd, insert_after,
604           swp_flags, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
605           wine_dbgstr_rect(visible_rect), surface);
606
607     if (!data && !(data = macdrv_create_win_data(hwnd, window_rect, client_rect))) return;
608
609     *visible_rect = *window_rect;
610     macdrv_window_to_mac_rect(data, style, visible_rect);
611     TRACE("visible_rect %s -> %s\n", wine_dbgstr_rect(window_rect),
612           wine_dbgstr_rect(visible_rect));
613
614     /* release the window surface if necessary */
615     if (!data->cocoa_window) goto done;
616     if (swp_flags & SWP_HIDEWINDOW) goto done;
617
618     if (*surface) window_surface_release(*surface);
619     *surface = NULL;
620
621 done:
622     release_win_data(data);
623 }
624
625
626 /***********************************************************************
627  *              WindowPosChanged   (MACDRV.@)
628  */
629 void CDECL macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
630                                    const RECT *window_rect, const RECT *client_rect,
631                                    const RECT *visible_rect, const RECT *valid_rects,
632                                    struct window_surface *surface)
633 {
634     struct macdrv_win_data *data;
635     DWORD new_style = GetWindowLongW(hwnd, GWL_STYLE);
636     RECT old_window_rect, old_whole_rect, old_client_rect;
637
638     if (!(data = get_win_data(hwnd))) return;
639
640     old_window_rect = data->window_rect;
641     old_whole_rect  = data->whole_rect;
642     old_client_rect = data->client_rect;
643     data->window_rect = *window_rect;
644     data->whole_rect  = *visible_rect;
645     data->client_rect = *client_rect;
646
647     TRACE("win %p/%p window %s whole %s client %s style %08x flags %08x surface %p\n",
648            hwnd, data->cocoa_window, wine_dbgstr_rect(window_rect),
649            wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(client_rect),
650            new_style, swp_flags, surface);
651
652     if (!IsRectEmpty(&valid_rects[0]))
653     {
654         macdrv_window window = data->cocoa_window;
655         int x_offset = old_whole_rect.left - data->whole_rect.left;
656         int y_offset = old_whole_rect.top - data->whole_rect.top;
657
658         /* if all that happened is that the whole window moved, copy everything */
659         if (!(swp_flags & SWP_FRAMECHANGED) &&
660             old_whole_rect.right   - data->whole_rect.right   == x_offset &&
661             old_whole_rect.bottom  - data->whole_rect.bottom  == y_offset &&
662             old_client_rect.left   - data->client_rect.left   == x_offset &&
663             old_client_rect.right  - data->client_rect.right  == x_offset &&
664             old_client_rect.top    - data->client_rect.top    == y_offset &&
665             old_client_rect.bottom - data->client_rect.bottom == y_offset &&
666             !memcmp(&valid_rects[0], &data->client_rect, sizeof(RECT)))
667         {
668             /* A Cocoa window's bits are moved automatically */
669             if (!window && (x_offset != 0 || y_offset != 0))
670             {
671                 release_win_data(data);
672                 move_window_bits(hwnd, window, &old_whole_rect, visible_rect,
673                                  &old_client_rect, client_rect, window_rect);
674                 if (!(data = get_win_data(hwnd))) return;
675             }
676         }
677         else
678         {
679             release_win_data(data);
680             move_window_bits(hwnd, window, &valid_rects[1], &valid_rects[0],
681                              &old_client_rect, client_rect, window_rect);
682             if (!(data = get_win_data(hwnd))) return;
683         }
684     }
685
686     if (!data->cocoa_window) goto done;
687
688     if (data->on_screen)
689     {
690         if ((swp_flags & SWP_HIDEWINDOW) && !(new_style & WS_VISIBLE))
691             hide_window(data);
692     }
693
694     if (new_style & WS_VISIBLE)
695     {
696         if (!data->on_screen || (swp_flags & (SWP_FRAMECHANGED|SWP_STATECHANGED)))
697             set_cocoa_window_properties(data);
698
699         if (!data->on_screen)
700             show_window(data);
701     }
702
703     sync_window_position(data, swp_flags);
704     set_cocoa_window_properties(data);
705
706 done:
707     release_win_data(data);
708 }