winemac: Don't attempt to set surface for child windows in macdrv_WindowPosChanged().
[wine.git] / dlls / winemac.drv / window.c
blob6e0926c7ad5290293bedbbe75d104f9fc0f5fc08
1 /*
2 * MACDRV windowing driver
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.
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.
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.
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
24 #include "config.h"
26 #include "macdrv.h"
27 #include "winuser.h"
28 #include "wine/unicode.h"
29 #include "wine/server.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
34 static CRITICAL_SECTION win_data_section;
35 static CRITICAL_SECTION_DEBUG critsect_debug =
37 0, 0, &win_data_section,
38 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
39 0, 0, { (DWORD_PTR)(__FILE__ ": win_data_section") }
41 static CRITICAL_SECTION win_data_section = { &critsect_debug, -1, 0, 0, 0, 0 };
43 static CFMutableDictionaryRef win_datas;
45 static DWORD activate_on_focus_time;
48 /***********************************************************************
49 * get_cocoa_window_features
51 static void get_cocoa_window_features(struct macdrv_win_data *data,
52 DWORD style, DWORD ex_style,
53 struct macdrv_window_features* wf)
55 memset(wf, 0, sizeof(*wf));
57 if (disable_window_decorations) return;
58 if (IsRectEmpty(&data->window_rect)) return;
60 if ((style & WS_CAPTION) == WS_CAPTION && !(ex_style & WS_EX_LAYERED))
62 wf->shadow = TRUE;
63 if (!data->shaped)
65 wf->title_bar = TRUE;
66 if (style & WS_SYSMENU) wf->close_button = TRUE;
67 if (style & WS_MINIMIZEBOX) wf->minimize_button = TRUE;
68 if (style & WS_MAXIMIZEBOX) wf->maximize_button = TRUE;
69 if (ex_style & WS_EX_TOOLWINDOW) wf->utility = TRUE;
72 if (style & WS_THICKFRAME)
74 wf->shadow = TRUE;
75 if (!data->shaped) wf->resizable = TRUE;
77 else if (ex_style & WS_EX_DLGMODALFRAME) wf->shadow = TRUE;
78 else if ((style & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) wf->shadow = TRUE;
82 /*******************************************************************
83 * can_activate_window
85 * Check if we can activate the specified window.
87 static inline BOOL can_activate_window(HWND hwnd)
89 LONG style = GetWindowLongW(hwnd, GWL_STYLE);
91 if (!(style & WS_VISIBLE)) return FALSE;
92 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
93 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) return FALSE;
94 if (hwnd == GetDesktopWindow()) return FALSE;
95 return !(style & WS_DISABLED);
99 /***********************************************************************
100 * get_cocoa_window_state
102 static void get_cocoa_window_state(struct macdrv_win_data *data,
103 DWORD style, DWORD ex_style,
104 struct macdrv_window_state* state)
106 memset(state, 0, sizeof(*state));
107 state->disabled = (style & WS_DISABLED) != 0;
108 state->no_activate = !can_activate_window(data->hwnd);
109 state->floating = (ex_style & WS_EX_TOPMOST) != 0;
110 state->excluded_by_expose = state->excluded_by_cycle =
111 (!(ex_style & WS_EX_APPWINDOW) &&
112 (GetWindow(data->hwnd, GW_OWNER) || (ex_style & (WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE))));
113 if (IsRectEmpty(&data->window_rect))
114 state->excluded_by_expose = TRUE;
115 state->minimized = (style & WS_MINIMIZE) != 0;
116 state->minimized_valid = state->minimized != data->minimized;
117 state->maximized = (style & WS_MAXIMIZE) != 0;
121 /***********************************************************************
122 * get_mac_rect_offset
124 * Helper for macdrv_window_to_mac_rect and macdrv_mac_to_window_rect.
126 static void get_mac_rect_offset(struct macdrv_win_data *data, DWORD style, RECT *rect)
128 DWORD ex_style, style_mask = 0, ex_style_mask = 0;
130 rect->top = rect->bottom = rect->left = rect->right = 0;
132 ex_style = GetWindowLongW(data->hwnd, GWL_EXSTYLE);
134 if (!data->shaped)
136 struct macdrv_window_features wf;
137 get_cocoa_window_features(data, style, ex_style, &wf);
139 if (wf.title_bar)
141 style_mask |= WS_CAPTION;
142 ex_style_mask |= WS_EX_TOOLWINDOW;
144 if (wf.shadow)
146 style_mask |= WS_DLGFRAME | WS_THICKFRAME;
147 ex_style_mask |= WS_EX_DLGMODALFRAME;
151 AdjustWindowRectEx(rect, style & style_mask, FALSE, ex_style & ex_style_mask);
153 TRACE("%p/%p style %08x ex_style %08x shaped %d -> %s\n", data->hwnd, data->cocoa_window,
154 style, ex_style, data->shaped, wine_dbgstr_rect(rect));
158 /***********************************************************************
159 * macdrv_window_to_mac_rect
161 * Convert a rect from client to Mac window coordinates
163 static void macdrv_window_to_mac_rect(struct macdrv_win_data *data, DWORD style, RECT *rect)
165 RECT rc;
167 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return;
168 if (IsRectEmpty(rect)) return;
170 get_mac_rect_offset(data, style, &rc);
172 rect->left -= rc.left;
173 rect->right -= rc.right;
174 rect->top -= rc.top;
175 rect->bottom -= rc.bottom;
176 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
177 if (rect->left >= rect->right) rect->right = rect->left + 1;
181 /***********************************************************************
182 * macdrv_mac_to_window_rect
184 * Opposite of macdrv_window_to_mac_rect
186 static void macdrv_mac_to_window_rect(struct macdrv_win_data *data, RECT *rect)
188 RECT rc;
189 DWORD style = GetWindowLongW(data->hwnd, GWL_STYLE);
191 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return;
192 if (IsRectEmpty(rect)) return;
194 get_mac_rect_offset(data, style, &rc);
196 rect->left += rc.left;
197 rect->right += rc.right;
198 rect->top += rc.top;
199 rect->bottom += rc.bottom;
200 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
201 if (rect->left >= rect->right) rect->right = rect->left + 1;
205 /***********************************************************************
206 * constrain_window_frame
208 * Alter a window frame rectangle to fit within a) Cocoa's documented
209 * limits, and b) sane sizes, like twice the desktop rect.
211 static void constrain_window_frame(CGRect* frame)
213 CGRect desktop_rect = macdrv_get_desktop_rect();
214 int max_width, max_height;
216 max_width = min(32000, 2 * CGRectGetWidth(desktop_rect));
217 max_height = min(32000, 2 * CGRectGetHeight(desktop_rect));
219 if (frame->origin.x < -16000) frame->origin.x = -16000;
220 if (frame->origin.y < -16000) frame->origin.y = -16000;
221 if (frame->origin.x > 16000) frame->origin.x = 16000;
222 if (frame->origin.y > 16000) frame->origin.y = 16000;
223 if (frame->size.width > max_width) frame->size.width = max_width;
224 if (frame->size.height > max_height) frame->size.height = max_height;
228 /***********************************************************************
229 * alloc_win_data
231 static struct macdrv_win_data *alloc_win_data(HWND hwnd)
233 struct macdrv_win_data *data;
235 if ((data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
237 data->hwnd = hwnd;
238 data->color_key = CLR_INVALID;
239 data->swap_interval = 1;
240 EnterCriticalSection(&win_data_section);
241 if (!win_datas)
242 win_datas = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
243 CFDictionarySetValue(win_datas, hwnd, data);
245 return data;
249 /***********************************************************************
250 * get_win_data
252 * Lock and return the data structure associated with a window.
254 struct macdrv_win_data *get_win_data(HWND hwnd)
256 struct macdrv_win_data *data;
258 if (!hwnd) return NULL;
259 EnterCriticalSection(&win_data_section);
260 if (win_datas && (data = (struct macdrv_win_data*)CFDictionaryGetValue(win_datas, hwnd)))
261 return data;
262 LeaveCriticalSection(&win_data_section);
263 return NULL;
267 /***********************************************************************
268 * release_win_data
270 * Release the data returned by get_win_data.
272 void release_win_data(struct macdrv_win_data *data)
274 if (data) LeaveCriticalSection(&win_data_section);
278 /***********************************************************************
279 * macdrv_get_cocoa_window
281 * Return the Mac window associated with the full area of a window
283 macdrv_window macdrv_get_cocoa_window(HWND hwnd, BOOL require_on_screen)
285 struct macdrv_win_data *data = get_win_data(hwnd);
286 macdrv_window ret = NULL;
287 if (data && (data->on_screen || !require_on_screen))
288 ret = data->cocoa_window;
289 release_win_data(data);
290 return ret;
294 /***********************************************************************
295 * macdrv_get_cocoa_view
297 * Return the Cocoa view associated with a window
299 macdrv_view macdrv_get_cocoa_view(HWND hwnd)
301 struct macdrv_win_data *data = get_win_data(hwnd);
302 macdrv_view ret = data ? data->cocoa_view : NULL;
304 release_win_data(data);
305 return ret;
309 /***********************************************************************
310 * macdrv_get_client_cocoa_view
312 * Return the Cocoa view associated with a window's client area
314 macdrv_view macdrv_get_client_cocoa_view(HWND hwnd)
316 struct macdrv_win_data *data = get_win_data(hwnd);
317 macdrv_view ret = data ? data->client_cocoa_view : NULL;
319 release_win_data(data);
320 return ret;
324 /***********************************************************************
325 * set_cocoa_window_properties
327 * Set the window properties for a Cocoa window based on its Windows
328 * properties.
330 static void set_cocoa_window_properties(struct macdrv_win_data *data)
332 DWORD style, ex_style;
333 HWND owner;
334 macdrv_window owner_win;
335 struct macdrv_window_features wf;
336 struct macdrv_window_state state;
338 style = GetWindowLongW(data->hwnd, GWL_STYLE);
339 ex_style = GetWindowLongW(data->hwnd, GWL_EXSTYLE);
341 owner = GetWindow(data->hwnd, GW_OWNER);
342 if (owner)
343 owner = GetAncestor(owner, GA_ROOT);
344 owner_win = macdrv_get_cocoa_window(owner, TRUE);
345 macdrv_set_cocoa_parent_window(data->cocoa_window, owner_win);
347 get_cocoa_window_features(data, style, ex_style, &wf);
348 macdrv_set_cocoa_window_features(data->cocoa_window, &wf);
350 get_cocoa_window_state(data, style, ex_style, &state);
351 macdrv_set_cocoa_window_state(data->cocoa_window, &state);
352 if (state.minimized_valid)
353 data->minimized = state.minimized;
357 /***********************************************************************
358 * sync_window_region
360 * Update the window region.
362 static void sync_window_region(struct macdrv_win_data *data, HRGN win_region)
364 HRGN hrgn = win_region;
365 RGNDATA *region_data;
366 const CGRect* rects;
367 int count;
369 if (!data->cocoa_window) return;
370 data->shaped = FALSE;
372 if (IsRectEmpty(&data->window_rect)) /* set an empty shape */
374 TRACE("win %p/%p setting empty shape for zero-sized window\n", data->hwnd, data->cocoa_window);
375 macdrv_set_window_shape(data->cocoa_window, &CGRectZero, 1);
376 return;
379 if (hrgn == (HRGN)1) /* hack: win_region == 1 means retrieve region from server */
381 if (!(hrgn = CreateRectRgn(0, 0, 0, 0))) return;
382 if (GetWindowRgn(data->hwnd, hrgn) == ERROR)
384 DeleteObject(hrgn);
385 hrgn = 0;
389 if (hrgn && GetWindowLongW(data->hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
390 MirrorRgn(data->hwnd, hrgn);
391 if (hrgn)
393 OffsetRgn(hrgn, data->window_rect.left - data->whole_rect.left,
394 data->window_rect.top - data->whole_rect.top);
396 region_data = get_region_data(hrgn, 0);
397 if (region_data)
399 rects = (CGRect*)region_data->Buffer;
400 count = region_data->rdh.nCount;
401 /* Special case optimization. If the region entirely encloses the Cocoa
402 window, it's the same as there being no region. It's potentially
403 hard/slow to test this for arbitrary regions, so we just check for
404 very simple regions. */
405 if (count == 1 && CGRectContainsRect(rects[0], cgrect_from_rect(data->whole_rect)))
407 TRACE("optimizing for simple region that contains Cocoa content rect\n");
408 rects = NULL;
409 count = 0;
412 else
414 rects = NULL;
415 count = 0;
418 TRACE("win %p/%p win_region %p rects %p count %d\n", data->hwnd, data->cocoa_window, win_region, rects, count);
419 macdrv_set_window_shape(data->cocoa_window, rects, count);
421 HeapFree(GetProcessHeap(), 0, region_data);
422 data->shaped = (region_data != NULL);
424 if (hrgn && hrgn != win_region) DeleteObject(hrgn);
428 /***********************************************************************
429 * add_bounds_rect
431 static inline void add_bounds_rect(RECT *bounds, const RECT *rect)
433 if (rect->left >= rect->right || rect->top >= rect->bottom) return;
434 bounds->left = min(bounds->left, rect->left);
435 bounds->top = min(bounds->top, rect->top);
436 bounds->right = max(bounds->right, rect->right);
437 bounds->bottom = max(bounds->bottom, rect->bottom);
441 /***********************************************************************
442 * sync_window_opacity
444 static void sync_window_opacity(struct macdrv_win_data *data, COLORREF key, BYTE alpha,
445 BOOL per_pixel_alpha, DWORD flags)
447 CGFloat opacity = 1.0;
448 BOOL needs_flush = FALSE;
450 if (flags & LWA_ALPHA) opacity = alpha / 255.0;
452 TRACE("setting window %p/%p alpha to %g\n", data->hwnd, data->cocoa_window, opacity);
453 macdrv_set_window_alpha(data->cocoa_window, opacity);
455 if (flags & LWA_COLORKEY)
457 /* FIXME: treat PALETTEINDEX and DIBINDEX as black */
458 if ((key & (1 << 24)) || key >> 16 == 0x10ff)
459 key = RGB(0, 0, 0);
461 else
462 key = CLR_INVALID;
464 if (data->color_key != key)
466 if (key == CLR_INVALID)
468 TRACE("clearing color-key for window %p/%p\n", data->hwnd, data->cocoa_window);
469 macdrv_clear_window_color_key(data->cocoa_window);
471 else
473 TRACE("setting color-key for window %p/%p to RGB %d,%d,%d\n", data->hwnd, data->cocoa_window,
474 GetRValue(key), GetGValue(key), GetBValue(key));
475 macdrv_set_window_color_key(data->cocoa_window, GetRValue(key), GetGValue(key), GetBValue(key));
478 data->color_key = key;
479 needs_flush = TRUE;
482 if (!data->per_pixel_alpha != !per_pixel_alpha)
484 TRACE("setting window %p/%p per-pixel-alpha to %d\n", data->hwnd, data->cocoa_window, per_pixel_alpha);
485 macdrv_window_use_per_pixel_alpha(data->cocoa_window, per_pixel_alpha);
486 data->per_pixel_alpha = per_pixel_alpha;
487 needs_flush = TRUE;
490 if (needs_flush && data->surface)
492 RECT *bounds;
493 RECT rect;
495 rect = data->whole_rect;
496 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
497 data->surface->funcs->lock(data->surface);
498 bounds = data->surface->funcs->get_bounds(data->surface);
499 add_bounds_rect(bounds, &rect);
500 data->surface->funcs->unlock(data->surface);
505 /***********************************************************************
506 * sync_window_min_max_info
508 static void sync_window_min_max_info(HWND hwnd)
510 LONG style = GetWindowLongW(hwnd, GWL_STYLE);
511 LONG exstyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
512 RECT win_rect, primary_monitor_rect;
513 MINMAXINFO minmax;
514 LONG adjustedStyle;
515 INT xinc, yinc;
516 WINDOWPLACEMENT wpl;
517 HMONITOR monitor;
518 struct macdrv_win_data *data;
520 TRACE("win %p\n", hwnd);
522 if (!macdrv_get_cocoa_window(hwnd, FALSE)) return;
524 GetWindowRect(hwnd, &win_rect);
525 minmax.ptReserved.x = win_rect.left;
526 minmax.ptReserved.y = win_rect.top;
528 if ((style & WS_CAPTION) == WS_CAPTION)
529 adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
530 else
531 adjustedStyle = style;
533 primary_monitor_rect.left = primary_monitor_rect.top = 0;
534 primary_monitor_rect.right = GetSystemMetrics(SM_CXSCREEN);
535 primary_monitor_rect.bottom = GetSystemMetrics(SM_CYSCREEN);
536 AdjustWindowRectEx(&primary_monitor_rect, adjustedStyle, ((style & WS_POPUP) && GetMenu(hwnd)), exstyle);
538 xinc = -primary_monitor_rect.left;
539 yinc = -primary_monitor_rect.top;
541 minmax.ptMaxSize.x = primary_monitor_rect.right - primary_monitor_rect.left;
542 minmax.ptMaxSize.y = primary_monitor_rect.bottom - primary_monitor_rect.top;
543 minmax.ptMaxPosition.x = -xinc;
544 minmax.ptMaxPosition.y = -yinc;
545 if (style & (WS_DLGFRAME | WS_BORDER))
547 minmax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
548 minmax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
550 else
552 minmax.ptMinTrackSize.x = 2 * xinc;
553 minmax.ptMinTrackSize.y = 2 * yinc;
555 minmax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXMAXTRACK);
556 minmax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYMAXTRACK);
558 wpl.length = sizeof(wpl);
559 if (GetWindowPlacement(hwnd, &wpl) && (wpl.ptMaxPosition.x != -1 || wpl.ptMaxPosition.y != -1))
561 minmax.ptMaxPosition = wpl.ptMaxPosition;
563 /* Convert from GetWindowPlacement's workspace coordinates to screen coordinates. */
564 minmax.ptMaxPosition.x -= wpl.rcNormalPosition.left - win_rect.left;
565 minmax.ptMaxPosition.y -= wpl.rcNormalPosition.top - win_rect.top;
568 TRACE("initial ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax.ptMaxSize),
569 wine_dbgstr_point(&minmax.ptMaxPosition), wine_dbgstr_point(&minmax.ptMinTrackSize), wine_dbgstr_point(&minmax.ptMaxTrackSize));
571 SendMessageW(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&minmax);
573 TRACE("app's ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax.ptMaxSize),
574 wine_dbgstr_point(&minmax.ptMaxPosition), wine_dbgstr_point(&minmax.ptMinTrackSize), wine_dbgstr_point(&minmax.ptMaxTrackSize));
576 /* if the app didn't change the values, adapt them for the window's monitor */
577 if ((monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY)))
579 MONITORINFO mon_info;
580 RECT monitor_rect;
582 mon_info.cbSize = sizeof(mon_info);
583 GetMonitorInfoW(monitor, &mon_info);
585 if ((style & WS_MAXIMIZEBOX) && ((style & WS_CAPTION) == WS_CAPTION || !(style & WS_POPUP)))
586 monitor_rect = mon_info.rcWork;
587 else
588 monitor_rect = mon_info.rcMonitor;
590 if (minmax.ptMaxSize.x == primary_monitor_rect.right - primary_monitor_rect.left &&
591 minmax.ptMaxSize.y == primary_monitor_rect.bottom - primary_monitor_rect.top)
593 minmax.ptMaxSize.x = (monitor_rect.right - monitor_rect.left) + 2 * xinc;
594 minmax.ptMaxSize.y = (monitor_rect.bottom - monitor_rect.top) + 2 * yinc;
596 if (minmax.ptMaxPosition.x == -xinc && minmax.ptMaxPosition.y == -yinc)
598 minmax.ptMaxPosition.x = monitor_rect.left - xinc;
599 minmax.ptMaxPosition.y = monitor_rect.top - yinc;
603 minmax.ptMaxTrackSize.x = max(minmax.ptMaxTrackSize.x, minmax.ptMinTrackSize.x);
604 minmax.ptMaxTrackSize.y = max(minmax.ptMaxTrackSize.y, minmax.ptMinTrackSize.y);
606 TRACE("adjusted ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax.ptMaxSize),
607 wine_dbgstr_point(&minmax.ptMaxPosition), wine_dbgstr_point(&minmax.ptMinTrackSize), wine_dbgstr_point(&minmax.ptMaxTrackSize));
609 if ((data = get_win_data(hwnd)) && data->cocoa_window)
611 RECT min_rect, max_rect;
612 CGSize min_size, max_size;
614 SetRect(&min_rect, 0, 0, minmax.ptMinTrackSize.x, minmax.ptMinTrackSize.y);
615 macdrv_window_to_mac_rect(data, style, &min_rect);
616 min_size = CGSizeMake(min_rect.right - min_rect.left, min_rect.bottom - min_rect.top);
618 if (minmax.ptMaxTrackSize.x == GetSystemMetrics(SM_CXMAXTRACK) &&
619 minmax.ptMaxTrackSize.y == GetSystemMetrics(SM_CYMAXTRACK))
620 max_size = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX);
621 else
623 SetRect(&max_rect, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y);
624 macdrv_window_to_mac_rect(data, style, &max_rect);
625 max_size = CGSizeMake(max_rect.right - max_rect.left, max_rect.bottom - max_rect.top);
628 TRACE("min_size (%g,%g) max_size (%g,%g)\n", min_size.width, min_size.height, max_size.width, max_size.height);
629 macdrv_set_window_min_max_sizes(data->cocoa_window, min_size, max_size);
632 release_win_data(data);
636 /**********************************************************************
637 * create_client_cocoa_view
639 * Create the Cocoa view for a window's client area
641 static void create_client_cocoa_view(struct macdrv_win_data *data)
643 RECT rect = data->client_rect;
644 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
646 if (data->client_cocoa_view)
647 macdrv_set_view_frame(data->client_cocoa_view, cgrect_from_rect(rect));
648 else
650 data->client_cocoa_view = macdrv_create_view(cgrect_from_rect(rect));
651 macdrv_set_view_hidden(data->client_cocoa_view, FALSE);
653 macdrv_set_view_superview(data->client_cocoa_view, data->cocoa_view, data->cocoa_window, NULL, NULL);
657 /**********************************************************************
658 * create_cocoa_window
660 * Create the whole Mac window for a given window
662 static void create_cocoa_window(struct macdrv_win_data *data)
664 struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
665 WCHAR text[1024];
666 struct macdrv_window_features wf;
667 CGRect frame;
668 DWORD style, ex_style;
669 HRGN win_rgn;
670 COLORREF key;
671 BYTE alpha;
672 DWORD layered_flags;
674 if ((win_rgn = CreateRectRgn(0, 0, 0, 0)) &&
675 GetWindowRgn(data->hwnd, win_rgn) == ERROR)
677 DeleteObject(win_rgn);
678 win_rgn = 0;
680 data->shaped = (win_rgn != 0);
682 style = GetWindowLongW(data->hwnd, GWL_STYLE);
683 ex_style = GetWindowLongW(data->hwnd, GWL_EXSTYLE);
685 data->whole_rect = data->window_rect;
686 macdrv_window_to_mac_rect(data, style, &data->whole_rect);
688 get_cocoa_window_features(data, style, ex_style, &wf);
690 frame = cgrect_from_rect(data->whole_rect);
691 constrain_window_frame(&frame);
692 if (frame.size.width < 1 || frame.size.height < 1)
693 frame.size.width = frame.size.height = 1;
695 TRACE("creating %p window %s whole %s client %s\n", data->hwnd, wine_dbgstr_rect(&data->window_rect),
696 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
698 data->cocoa_window = macdrv_create_cocoa_window(&wf, frame, data->hwnd, thread_data->queue);
699 if (!data->cocoa_window) goto done;
700 create_client_cocoa_view(data);
702 set_cocoa_window_properties(data);
704 /* set the window text */
705 if (!InternalGetWindowText(data->hwnd, text, sizeof(text)/sizeof(WCHAR))) text[0] = 0;
706 macdrv_set_cocoa_window_title(data->cocoa_window, text, strlenW(text));
708 /* set the window region */
709 if (win_rgn || IsRectEmpty(&data->window_rect)) sync_window_region(data, win_rgn);
711 /* set the window opacity */
712 if (!GetLayeredWindowAttributes(data->hwnd, &key, &alpha, &layered_flags)) layered_flags = 0;
713 sync_window_opacity(data, key, alpha, FALSE, layered_flags);
715 done:
716 if (win_rgn) DeleteObject(win_rgn);
720 /**********************************************************************
721 * destroy_cocoa_window
723 * Destroy the whole Mac window for a given window.
725 static void destroy_cocoa_window(struct macdrv_win_data *data)
727 if (!data->cocoa_window) return;
729 TRACE("win %p Cocoa win %p\n", data->hwnd, data->cocoa_window);
731 macdrv_destroy_cocoa_window(data->cocoa_window);
732 data->cocoa_window = 0;
733 data->on_screen = FALSE;
734 data->color_key = CLR_INVALID;
735 if (data->surface) window_surface_release(data->surface);
736 data->surface = NULL;
737 if (data->unminimized_surface) window_surface_release(data->unminimized_surface);
738 data->unminimized_surface = NULL;
742 /**********************************************************************
743 * create_cocoa_view
745 * Create the Cocoa view for a given Windows child window
747 static void create_cocoa_view(struct macdrv_win_data *data)
749 BOOL equal = EqualRect(&data->window_rect, &data->client_rect);
750 CGRect frame = cgrect_from_rect(data->window_rect);
752 data->shaped = FALSE;
753 data->whole_rect = data->window_rect;
755 TRACE("creating %p window %s whole %s client %s\n", data->hwnd, wine_dbgstr_rect(&data->window_rect),
756 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
758 if (!equal)
759 data->cocoa_view = macdrv_create_view(frame);
760 create_client_cocoa_view(data);
761 if (equal)
763 data->cocoa_view = data->client_cocoa_view;
764 macdrv_set_view_hidden(data->cocoa_view, TRUE);
765 macdrv_set_view_frame(data->cocoa_view, frame);
770 /**********************************************************************
771 * destroy_cocoa_view
773 * Destroy the Cocoa view for a given window.
775 static void destroy_cocoa_view(struct macdrv_win_data *data)
777 if (!data->cocoa_view) return;
779 TRACE("win %p Cocoa view %p\n", data->hwnd, data->cocoa_view);
781 if (data->cocoa_view != data->client_cocoa_view)
782 macdrv_dispose_view(data->cocoa_view);
783 data->cocoa_view = NULL;
784 data->on_screen = FALSE;
788 /***********************************************************************
789 * set_cocoa_view_parent
791 static void set_cocoa_view_parent(struct macdrv_win_data *data, HWND parent)
793 struct macdrv_win_data *parent_data = get_win_data(parent);
794 macdrv_window cocoa_window = parent_data ? parent_data->cocoa_window : NULL;
795 macdrv_view superview = parent_data ? parent_data->client_cocoa_view : NULL;
797 TRACE("win %p/%p parent %p/%p\n", data->hwnd, data->cocoa_view, parent, cocoa_window ? (void*)cocoa_window : (void*)superview);
799 if (!cocoa_window && !superview)
800 WARN("hwnd %p new parent %p has no Cocoa window or view in this process\n", data->hwnd, parent);
802 macdrv_set_view_superview(data->cocoa_view, superview, cocoa_window, NULL, NULL);
803 release_win_data(parent_data);
807 /***********************************************************************
808 * macdrv_create_win_data
810 * Create a Mac data window structure for an existing window.
812 static struct macdrv_win_data *macdrv_create_win_data(HWND hwnd, const RECT *window_rect,
813 const RECT *client_rect)
815 struct macdrv_win_data *data;
816 HWND parent;
818 if (GetWindowThreadProcessId(hwnd, NULL) != GetCurrentThreadId()) return NULL;
820 if (!(parent = GetAncestor(hwnd, GA_PARENT))) /* desktop */
822 macdrv_init_thread_data();
823 return NULL;
826 /* don't create win data for HWND_MESSAGE windows */
827 if (parent != GetDesktopWindow() && !GetAncestor(parent, GA_PARENT)) return NULL;
829 if (!(data = alloc_win_data(hwnd))) return NULL;
831 data->whole_rect = data->window_rect = *window_rect;
832 data->client_rect = *client_rect;
834 if (parent == GetDesktopWindow())
836 create_cocoa_window(data);
837 TRACE("win %p/%p window %s whole %s client %s\n",
838 hwnd, data->cocoa_window, wine_dbgstr_rect(&data->window_rect),
839 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
841 else
843 create_cocoa_view(data);
844 TRACE("win %p/%p window %s whole %s client %s\n",
845 hwnd, data->cocoa_view, wine_dbgstr_rect(&data->window_rect),
846 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
848 set_cocoa_view_parent(data, parent);
851 return data;
855 /***********************************************************************
856 * set_focus
858 static void set_focus(HWND hwnd)
860 struct macdrv_win_data *data;
862 if (!(hwnd = GetAncestor(hwnd, GA_ROOT))) return;
863 if (!(data = get_win_data(hwnd))) return;
865 if (data->cocoa_window && data->on_screen)
867 BOOL activate = activate_on_focus_time && (GetTickCount() - activate_on_focus_time < 2000);
868 /* Set Mac focus */
869 macdrv_give_cocoa_window_focus(data->cocoa_window, activate);
870 activate_on_focus_time = 0;
873 release_win_data(data);
876 /***********************************************************************
877 * show_window
879 static void show_window(struct macdrv_win_data *data)
881 if (data->cocoa_window)
883 HWND prev = NULL;
884 HWND next = NULL;
885 macdrv_window prev_window = NULL;
886 macdrv_window next_window = NULL;
887 BOOL activate = FALSE;
888 GUITHREADINFO info;
890 /* find window that this one must be after */
891 prev = GetWindow(data->hwnd, GW_HWNDPREV);
892 while (prev && !((GetWindowLongW(prev, GWL_STYLE) & (WS_VISIBLE | WS_MINIMIZE)) == WS_VISIBLE &&
893 (prev_window = macdrv_get_cocoa_window(prev, TRUE))))
894 prev = GetWindow(prev, GW_HWNDPREV);
895 if (!prev_window)
897 /* find window that this one must be before */
898 next = GetWindow(data->hwnd, GW_HWNDNEXT);
899 while (next && !((GetWindowLongW(next, GWL_STYLE) & (WS_VISIBLE | WS_MINIMIZE)) == WS_VISIBLE &&
900 (next_window = macdrv_get_cocoa_window(next, TRUE))))
901 next = GetWindow(next, GW_HWNDNEXT);
904 TRACE("win %p/%p below %p/%p above %p/%p\n",
905 data->hwnd, data->cocoa_window, prev, prev_window, next, next_window);
907 if (!prev_window)
908 activate = activate_on_focus_time && (GetTickCount() - activate_on_focus_time < 2000);
909 macdrv_order_cocoa_window(data->cocoa_window, prev_window, next_window, activate);
910 data->on_screen = TRUE;
912 info.cbSize = sizeof(info);
913 if (GetGUIThreadInfo(GetWindowThreadProcessId(data->hwnd, NULL), &info) && info.hwndFocus &&
914 (data->hwnd == info.hwndFocus || IsChild(data->hwnd, info.hwndFocus)))
915 set_focus(info.hwndFocus);
916 if (activate)
917 activate_on_focus_time = 0;
919 else
921 TRACE("win %p/%p showing view\n", data->hwnd, data->cocoa_view);
923 macdrv_set_view_hidden(data->cocoa_view, FALSE);
924 data->on_screen = TRUE;
929 /***********************************************************************
930 * hide_window
932 static void hide_window(struct macdrv_win_data *data)
934 TRACE("win %p/%p\n", data->hwnd, data->cocoa_window);
936 if (data->cocoa_window)
937 macdrv_hide_cocoa_window(data->cocoa_window);
938 else
939 macdrv_set_view_hidden(data->cocoa_view, TRUE);
940 data->on_screen = FALSE;
944 /***********************************************************************
945 * sync_window_z_order
947 static void sync_window_z_order(struct macdrv_win_data *data)
949 if (data->cocoa_view)
951 HWND parent = GetAncestor(data->hwnd, GA_PARENT);
952 macdrv_view superview = macdrv_get_client_cocoa_view(parent);
953 macdrv_window window = NULL;
954 HWND prev;
955 HWND next = NULL;
956 macdrv_view prev_view = NULL;
957 macdrv_view next_view = NULL;
959 if (!superview)
961 window = macdrv_get_cocoa_window(parent, FALSE);
962 if (!window)
963 WARN("hwnd %p/%p parent %p has no Cocoa window or view in this process\n", data->hwnd, data->cocoa_view, parent);
966 /* find window that this one must be after */
967 prev = GetWindow(data->hwnd, GW_HWNDPREV);
968 while (prev && !(prev_view = macdrv_get_cocoa_view(prev)))
969 prev = GetWindow(prev, GW_HWNDPREV);
970 if (!prev_view)
972 /* find window that this one must be before */
973 next = GetWindow(data->hwnd, GW_HWNDNEXT);
974 while (next && !(next_view = macdrv_get_cocoa_view(next)))
975 next = GetWindow(next, GW_HWNDNEXT);
978 TRACE("win %p/%p below %p/%p above %p/%p\n",
979 data->hwnd, data->cocoa_view, prev, prev_view, next, next_view);
981 macdrv_set_view_superview(data->cocoa_view, superview, window, prev_view, next_view);
983 else if (data->on_screen)
984 show_window(data);
988 /***********************************************************************
989 * get_region_data
991 * Calls GetRegionData on the given region and converts the rectangle
992 * array to CGRect format. The returned buffer must be freed by
993 * caller using HeapFree(GetProcessHeap(),...).
994 * If hdc_lptodp is not 0, the rectangles are converted through LPtoDP.
996 RGNDATA *get_region_data(HRGN hrgn, HDC hdc_lptodp)
998 RGNDATA *data;
999 DWORD size;
1000 int i;
1001 RECT *rect;
1002 CGRect *cgrect;
1004 if (!hrgn || !(size = GetRegionData(hrgn, 0, NULL))) return NULL;
1005 if (sizeof(CGRect) > sizeof(RECT))
1007 /* add extra size for CGRect array */
1008 int count = (size - sizeof(RGNDATAHEADER)) / sizeof(RECT);
1009 size += count * (sizeof(CGRect) - sizeof(RECT));
1011 if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return NULL;
1012 if (!GetRegionData(hrgn, size, data))
1014 HeapFree(GetProcessHeap(), 0, data);
1015 return NULL;
1018 rect = (RECT *)data->Buffer;
1019 cgrect = (CGRect *)data->Buffer;
1020 if (hdc_lptodp) /* map to device coordinates */
1022 LPtoDP(hdc_lptodp, (POINT *)rect, data->rdh.nCount * 2);
1023 for (i = 0; i < data->rdh.nCount; i++)
1025 if (rect[i].right < rect[i].left)
1027 INT tmp = rect[i].right;
1028 rect[i].right = rect[i].left;
1029 rect[i].left = tmp;
1031 if (rect[i].bottom < rect[i].top)
1033 INT tmp = rect[i].bottom;
1034 rect[i].bottom = rect[i].top;
1035 rect[i].top = tmp;
1040 if (sizeof(CGRect) > sizeof(RECT))
1042 /* need to start from the end */
1043 for (i = data->rdh.nCount-1; i >= 0; i--)
1044 cgrect[i] = cgrect_from_rect(rect[i]);
1046 else
1048 for (i = 0; i < data->rdh.nCount; i++)
1049 cgrect[i] = cgrect_from_rect(rect[i]);
1051 return data;
1055 /***********************************************************************
1056 * sync_window_position
1058 * Synchronize the Mac window position with the Windows one
1060 static void sync_window_position(struct macdrv_win_data *data, UINT swp_flags, const RECT *old_window_rect,
1061 const RECT *old_whole_rect)
1063 CGRect frame = cgrect_from_rect(data->whole_rect);
1064 BOOL force_z_order = FALSE;
1066 if (data->cocoa_window)
1068 if (data->minimized) return;
1070 constrain_window_frame(&frame);
1071 if (frame.size.width < 1 || frame.size.height < 1)
1072 frame.size.width = frame.size.height = 1;
1074 macdrv_set_cocoa_window_frame(data->cocoa_window, &frame);
1076 else
1078 BOOL were_equal = (data->cocoa_view == data->client_cocoa_view);
1079 BOOL now_equal = EqualRect(&data->whole_rect, &data->client_rect);
1081 if (were_equal && !now_equal)
1083 data->cocoa_view = macdrv_create_view(frame);
1084 macdrv_set_view_hidden(data->cocoa_view, !data->on_screen);
1085 macdrv_set_view_superview(data->client_cocoa_view, data->cocoa_view, NULL, NULL, NULL);
1086 macdrv_set_view_hidden(data->client_cocoa_view, FALSE);
1087 force_z_order = TRUE;
1089 else if (!were_equal && now_equal)
1091 macdrv_dispose_view(data->cocoa_view);
1092 data->cocoa_view = data->client_cocoa_view;
1093 macdrv_set_view_hidden(data->cocoa_view, !data->on_screen);
1094 macdrv_set_view_frame(data->cocoa_view, frame);
1095 force_z_order = TRUE;
1097 else
1098 macdrv_set_view_frame(data->cocoa_view, frame);
1101 if (data->cocoa_view != data->client_cocoa_view)
1103 RECT rect = data->client_rect;
1104 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
1105 macdrv_set_view_frame(data->client_cocoa_view, cgrect_from_rect(rect));
1106 TRACE("win %p/%p client %s\n", data->hwnd, data->client_cocoa_view, wine_dbgstr_rect(&rect));
1109 if (old_window_rect && old_whole_rect &&
1110 (IsRectEmpty(old_window_rect) != IsRectEmpty(&data->window_rect) ||
1111 old_window_rect->left - old_whole_rect->left != data->window_rect.left - data->whole_rect.left ||
1112 old_window_rect->top - old_whole_rect->top != data->window_rect.top - data->whole_rect.top))
1113 sync_window_region(data, (HRGN)1);
1115 TRACE("win %p/%p whole_rect %s frame %s\n", data->hwnd,
1116 data->cocoa_window ? (void*)data->cocoa_window : (void*)data->cocoa_view,
1117 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_cgrect(frame));
1119 if (force_z_order || !(swp_flags & SWP_NOZORDER) || (swp_flags & SWP_SHOWWINDOW))
1120 sync_window_z_order(data);
1124 /***********************************************************************
1125 * move_window_bits
1127 * Move the window bits when a window is moved.
1129 static void move_window_bits(HWND hwnd, macdrv_window window, const RECT *old_rect, const RECT *new_rect,
1130 const RECT *old_client_rect, const RECT *new_client_rect,
1131 const RECT *new_window_rect)
1133 RECT src_rect = *old_rect;
1134 RECT dst_rect = *new_rect;
1135 HDC hdc_src, hdc_dst;
1136 HRGN rgn;
1137 HWND parent = 0;
1139 if (!window)
1141 OffsetRect(&dst_rect, -new_window_rect->left, -new_window_rect->top);
1142 parent = GetAncestor(hwnd, GA_PARENT);
1143 hdc_src = GetDCEx(parent, 0, DCX_CACHE);
1144 hdc_dst = GetDCEx(hwnd, 0, DCX_CACHE | DCX_WINDOW);
1146 else
1148 OffsetRect(&dst_rect, -new_client_rect->left, -new_client_rect->top);
1149 /* make src rect relative to the old position of the window */
1150 OffsetRect(&src_rect, -old_client_rect->left, -old_client_rect->top);
1151 if (dst_rect.left == src_rect.left && dst_rect.top == src_rect.top) return;
1152 hdc_src = hdc_dst = GetDCEx(hwnd, 0, DCX_CACHE);
1155 rgn = CreateRectRgnIndirect(&dst_rect);
1156 SelectClipRgn(hdc_dst, rgn);
1157 DeleteObject(rgn);
1158 ExcludeUpdateRgn(hdc_dst, hwnd);
1160 TRACE("copying bits for win %p/%p %s -> %s\n", hwnd, window,
1161 wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect));
1162 BitBlt(hdc_dst, dst_rect.left, dst_rect.top,
1163 dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top,
1164 hdc_src, src_rect.left, src_rect.top, SRCCOPY);
1166 ReleaseDC(hwnd, hdc_dst);
1167 if (hdc_src != hdc_dst) ReleaseDC(parent, hdc_src);
1171 /**********************************************************************
1172 * activate_on_following_focus
1174 void activate_on_following_focus(void)
1176 activate_on_focus_time = GetTickCount();
1177 if (!activate_on_focus_time) activate_on_focus_time = 1;
1181 /***********************************************************************
1182 * set_app_icon
1184 static void set_app_icon(void)
1186 CFArrayRef images = create_app_icon_images();
1187 if (images)
1189 macdrv_set_application_icon(images);
1190 CFRelease(images);
1195 /**********************************************************************
1196 * set_capture_window_for_move
1198 static BOOL set_capture_window_for_move(HWND hwnd)
1200 HWND previous = 0;
1201 BOOL ret;
1203 SERVER_START_REQ(set_capture_window)
1205 req->handle = wine_server_user_handle(hwnd);
1206 req->flags = CAPTURE_MOVESIZE;
1207 if ((ret = !wine_server_call_err(req)))
1209 previous = wine_server_ptr_handle(reply->previous);
1210 hwnd = wine_server_ptr_handle(reply->full_handle);
1213 SERVER_END_REQ;
1215 if (ret)
1217 macdrv_SetCapture(hwnd, GUI_INMOVESIZE);
1219 if (previous && previous != hwnd)
1220 SendMessageW(previous, WM_CAPTURECHANGED, 0, (LPARAM)hwnd);
1222 return ret;
1226 /***********************************************************************
1227 * move_window
1229 * Based on user32's WINPOS_SysCommandSizeMove() specialized just for
1230 * moving top-level windows and enforcing Mac-style constraints like
1231 * keeping the top of the window within the work area.
1233 static LRESULT move_window(HWND hwnd, WPARAM wparam)
1235 MSG msg;
1236 RECT origRect, movedRect, desktopRect;
1237 LONG hittest = (LONG)(wparam & 0x0f);
1238 POINT capturePoint;
1239 LONG style = GetWindowLongW(hwnd, GWL_STYLE);
1240 BOOL moved = FALSE;
1241 DWORD dwPoint = GetMessagePos();
1242 INT captionHeight;
1243 HMONITOR mon = 0;
1244 MONITORINFO info;
1246 if ((style & (WS_MINIMIZE | WS_MAXIMIZE)) || !IsWindowVisible(hwnd)) return -1;
1247 if (hittest && hittest != HTCAPTION) return -1;
1249 capturePoint.x = (short)LOWORD(dwPoint);
1250 capturePoint.y = (short)HIWORD(dwPoint);
1251 ClipCursor(NULL);
1253 TRACE("hwnd %p hittest %d, pos %d,%d\n", hwnd, hittest, capturePoint.x, capturePoint.y);
1255 origRect.left = origRect.right = origRect.top = origRect.bottom = 0;
1256 if (AdjustWindowRectEx(&origRect, style, FALSE, GetWindowLongW(hwnd, GWL_EXSTYLE)))
1257 captionHeight = -origRect.top;
1258 else
1259 captionHeight = 0;
1261 GetWindowRect(hwnd, &origRect);
1262 movedRect = origRect;
1264 if (!hittest)
1266 /* Move pointer to the center of the caption */
1267 RECT rect = origRect;
1269 /* Note: to be exactly centered we should take the different types
1270 * of border into account, but it shouldn't make more than a few pixels
1271 * of difference so let's not bother with that */
1272 rect.top += GetSystemMetrics(SM_CYBORDER);
1273 if (style & WS_SYSMENU)
1274 rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
1275 if (style & WS_MINIMIZEBOX)
1276 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1277 if (style & WS_MAXIMIZEBOX)
1278 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1279 capturePoint.x = (rect.right + rect.left) / 2;
1280 capturePoint.y = rect.top + GetSystemMetrics(SM_CYSIZE)/2;
1282 SetCursorPos(capturePoint.x, capturePoint.y);
1283 SendMessageW(hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELONG(HTCAPTION, WM_MOUSEMOVE));
1286 desktopRect = rect_from_cgrect(macdrv_get_desktop_rect());
1287 mon = MonitorFromPoint(capturePoint, MONITOR_DEFAULTTONEAREST);
1288 info.cbSize = sizeof(info);
1289 if (mon && !GetMonitorInfoW(mon, &info))
1290 mon = 0;
1292 /* repaint the window before moving it around */
1293 RedrawWindow(hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
1295 SendMessageW(hwnd, WM_ENTERSIZEMOVE, 0, 0);
1296 set_capture_window_for_move(hwnd);
1298 while(1)
1300 POINT pt;
1301 int dx = 0, dy = 0;
1302 HMONITOR newmon;
1304 if (!GetMessageW(&msg, 0, 0, 0)) break;
1305 if (CallMsgFilterW(&msg, MSGF_SIZE)) continue;
1307 /* Exit on button-up, Return, or Esc */
1308 if (msg.message == WM_LBUTTONUP ||
1309 (msg.message == WM_KEYDOWN && (msg.wParam == VK_RETURN || msg.wParam == VK_ESCAPE)))
1310 break;
1312 if (msg.message != WM_KEYDOWN && msg.message != WM_MOUSEMOVE)
1314 TranslateMessage(&msg);
1315 DispatchMessageW(&msg);
1316 continue; /* We are not interested in other messages */
1319 pt = msg.pt;
1321 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
1323 case VK_UP: pt.y -= 8; break;
1324 case VK_DOWN: pt.y += 8; break;
1325 case VK_LEFT: pt.x -= 8; break;
1326 case VK_RIGHT: pt.x += 8; break;
1329 pt.x = max(pt.x, desktopRect.left);
1330 pt.x = min(pt.x, desktopRect.right - 1);
1331 pt.y = max(pt.y, desktopRect.top);
1332 pt.y = min(pt.y, desktopRect.bottom - 1);
1334 if ((newmon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) && newmon != mon)
1336 if (GetMonitorInfoW(newmon, &info))
1337 mon = newmon;
1338 else
1339 mon = 0;
1342 if (mon)
1344 /* wineserver clips the cursor position to the virtual desktop rect but,
1345 if the display configuration is non-rectangular, that could still
1346 leave the logical cursor position outside of any display. The window
1347 could keep moving as you push the cursor against a display edge, even
1348 though the visible cursor doesn't keep moving. The following keeps
1349 the window movement in sync with the visible cursor. */
1350 pt.x = max(pt.x, info.rcMonitor.left);
1351 pt.x = min(pt.x, info.rcMonitor.right - 1);
1352 pt.y = max(pt.y, info.rcMonitor.top);
1353 pt.y = min(pt.y, info.rcMonitor.bottom - 1);
1355 /* Assuming that dx will be calculated below as pt.x - capturePoint.x,
1356 dy will be pt.y - capturePoint.y, and movedRect will be offset by those,
1357 we want to enforce these constraints:
1358 movedRect.left + dx < info.rcWork.right
1359 movedRect.right + dx > info.rcWork.left
1360 movedRect.top + captionHeight + dy < info.rcWork.bottom
1361 movedRect.bottom + dy > info.rcWork.top
1362 movedRect.top + dy >= info.rcWork.top
1363 The first four keep at least one edge barely in the work area.
1364 The last keeps the top (i.e. the title bar) in the work area.
1365 The fourth is redundant with the last, so can be ignored.
1367 Substituting for dx and dy and rearranging gives us...
1369 pt.x = min(pt.x, info.rcWork.right - 1 + capturePoint.x - movedRect.left);
1370 pt.x = max(pt.x, info.rcWork.left + 1 + capturePoint.x - movedRect.right);
1371 pt.y = min(pt.y, info.rcWork.bottom - 1 + capturePoint.y - movedRect.top - captionHeight);
1372 pt.y = max(pt.y, info.rcWork.top + capturePoint.y - movedRect.top);
1375 dx = pt.x - capturePoint.x;
1376 dy = pt.y - capturePoint.y;
1378 if (dx || dy)
1380 moved = TRUE;
1382 if (msg.message == WM_KEYDOWN) SetCursorPos(pt.x, pt.y);
1383 else
1385 OffsetRect(&movedRect, dx, dy);
1386 capturePoint = pt;
1388 SendMessageW(hwnd, WM_MOVING, 0, (LPARAM)&movedRect);
1389 SetWindowPos(hwnd, 0, movedRect.left, movedRect.top, 0, 0,
1390 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
1395 set_capture_window_for_move(0);
1397 SendMessageW(hwnd, WM_EXITSIZEMOVE, 0, 0);
1398 SendMessageW(hwnd, WM_SETVISIBLE, TRUE, 0L);
1400 /* if the move is canceled, restore the previous position */
1401 if (moved && msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)
1403 SetWindowPos(hwnd, 0, origRect.left, origRect.top, 0, 0,
1404 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
1407 return 0;
1411 /***********************************************************************
1412 * perform_window_command
1414 static void perform_window_command(HWND hwnd, DWORD style_any, DWORD style_none, WORD command, WORD hittest)
1416 DWORD style;
1418 TRACE("win %p style_any 0x%08x style_none 0x%08x command 0x%04x hittest 0x%04x\n",
1419 hwnd, style_any, style_none, command, hittest);
1421 style = GetWindowLongW(hwnd, GWL_STYLE);
1422 if ((style_any && !(style & style_any)) || (style & (WS_DISABLED | style_none)))
1424 TRACE("not changing win %p style 0x%08x\n", hwnd, style);
1425 return;
1428 if (GetActiveWindow() != hwnd)
1430 LRESULT ma = SendMessageW(hwnd, WM_MOUSEACTIVATE, (WPARAM)GetAncestor(hwnd, GA_ROOT),
1431 MAKELPARAM(hittest, WM_NCLBUTTONDOWN));
1432 switch (ma)
1434 case MA_NOACTIVATEANDEAT:
1435 case MA_ACTIVATEANDEAT:
1436 TRACE("not changing win %p mouse-activate result %ld\n", hwnd, ma);
1437 return;
1438 case MA_NOACTIVATE:
1439 break;
1440 case MA_ACTIVATE:
1441 case 0:
1442 SetActiveWindow(hwnd);
1443 break;
1444 default:
1445 WARN("unknown WM_MOUSEACTIVATE code %ld\n", ma);
1446 break;
1450 TRACE("changing win %p\n", hwnd);
1451 PostMessageW(hwnd, WM_SYSCOMMAND, command, 0);
1455 /**********************************************************************
1456 * CreateDesktopWindow (MACDRV.@)
1458 BOOL CDECL macdrv_CreateDesktopWindow(HWND hwnd)
1460 unsigned int width, height;
1462 TRACE("%p\n", hwnd);
1464 /* retrieve the real size of the desktop */
1465 SERVER_START_REQ(get_window_rectangles)
1467 req->handle = wine_server_user_handle(hwnd);
1468 req->relative = COORDS_CLIENT;
1469 wine_server_call(req);
1470 width = reply->window.right;
1471 height = reply->window.bottom;
1473 SERVER_END_REQ;
1475 if (!width && !height) /* not initialized yet */
1477 CGRect rect = macdrv_get_desktop_rect();
1479 SERVER_START_REQ(set_window_pos)
1481 req->handle = wine_server_user_handle(hwnd);
1482 req->previous = 0;
1483 req->swp_flags = SWP_NOZORDER;
1484 req->window.left = CGRectGetMinX(rect);
1485 req->window.top = CGRectGetMinY(rect);
1486 req->window.right = CGRectGetMaxX(rect);
1487 req->window.bottom = CGRectGetMaxY(rect);
1488 req->client = req->window;
1489 wine_server_call(req);
1491 SERVER_END_REQ;
1494 set_app_icon();
1495 return TRUE;
1499 /**********************************************************************
1500 * CreateWindow (MACDRV.@)
1502 BOOL CDECL macdrv_CreateWindow(HWND hwnd)
1504 if (hwnd == GetDesktopWindow())
1505 macdrv_init_clipboard();
1506 return TRUE;
1510 /***********************************************************************
1511 * DestroyWindow (MACDRV.@)
1513 void CDECL macdrv_DestroyWindow(HWND hwnd)
1515 struct macdrv_win_data *data;
1517 TRACE("%p\n", hwnd);
1519 if (!(data = get_win_data(hwnd))) return;
1521 if (hwnd == GetCapture()) macdrv_SetCapture(0, 0);
1523 destroy_cocoa_window(data);
1524 destroy_cocoa_view(data);
1525 if (data->client_cocoa_view) macdrv_dispose_view(data->client_cocoa_view);
1527 CFDictionaryRemoveValue(win_datas, hwnd);
1528 release_win_data(data);
1529 HeapFree(GetProcessHeap(), 0, data);
1533 /*****************************************************************
1534 * SetFocus (MACDRV.@)
1536 * Set the Mac focus.
1538 void CDECL macdrv_SetFocus(HWND hwnd)
1540 struct macdrv_thread_data *thread_data = macdrv_thread_data();
1542 TRACE("%p\n", hwnd);
1544 if (!thread_data) return;
1545 thread_data->dead_key_state = 0;
1546 set_focus(hwnd);
1550 /***********************************************************************
1551 * SetLayeredWindowAttributes (MACDRV.@)
1553 * Set transparency attributes for a layered window.
1555 void CDECL macdrv_SetLayeredWindowAttributes(HWND hwnd, COLORREF key, BYTE alpha, DWORD flags)
1557 struct macdrv_win_data *data = get_win_data(hwnd);
1559 TRACE("hwnd %p key %#08x alpha %#02x flags %x\n", hwnd, key, alpha, flags);
1561 if (data)
1563 data->layered = TRUE;
1564 if (data->cocoa_window)
1566 sync_window_opacity(data, key, alpha, FALSE, flags);
1567 /* since layered attributes are now set, can now show the window */
1568 if ((GetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE) && !data->on_screen)
1569 show_window(data);
1571 release_win_data(data);
1573 else
1574 FIXME("setting layered attributes on window %p of other process not supported\n", hwnd);
1578 /*****************************************************************
1579 * SetParent (MACDRV.@)
1581 void CDECL macdrv_SetParent(HWND hwnd, HWND parent, HWND old_parent)
1583 struct macdrv_win_data *data;
1585 TRACE("%p, %p, %p\n", hwnd, parent, old_parent);
1587 if (parent == old_parent) return;
1588 if (!(data = get_win_data(hwnd))) return;
1590 if (parent != GetDesktopWindow()) /* a child window */
1592 if (old_parent == GetDesktopWindow())
1594 /* destroy the old Mac window */
1595 destroy_cocoa_window(data);
1596 create_cocoa_view(data);
1599 set_cocoa_view_parent(data, parent);
1601 else /* new top level window */
1603 destroy_cocoa_view(data);
1604 create_cocoa_window(data);
1606 release_win_data(data);
1610 /***********************************************************************
1611 * SetWindowRgn (MACDRV.@)
1613 * Assign specified region to window (for non-rectangular windows)
1615 void CDECL macdrv_SetWindowRgn(HWND hwnd, HRGN hrgn, BOOL redraw)
1617 struct macdrv_win_data *data;
1619 TRACE("%p, %p, %d\n", hwnd, hrgn, redraw);
1621 if ((data = get_win_data(hwnd)))
1623 sync_window_region(data, hrgn);
1624 release_win_data(data);
1626 else
1628 DWORD procid;
1630 GetWindowThreadProcessId(hwnd, &procid);
1631 if (procid != GetCurrentProcessId())
1632 SendMessageW(hwnd, WM_MACDRV_SET_WIN_REGION, 0, 0);
1637 /***********************************************************************
1638 * SetWindowStyle (MACDRV.@)
1640 * Update the state of the Cocoa window to reflect a style change
1642 void CDECL macdrv_SetWindowStyle(HWND hwnd, INT offset, STYLESTRUCT *style)
1644 struct macdrv_win_data *data;
1646 TRACE("hwnd %p offset %d styleOld 0x%08x styleNew 0x%08x\n", hwnd, offset, style->styleOld, style->styleNew);
1648 if (hwnd == GetDesktopWindow()) return;
1649 if (!(data = get_win_data(hwnd))) return;
1651 if (data->cocoa_window)
1653 DWORD changed = style->styleNew ^ style->styleOld;
1655 set_cocoa_window_properties(data);
1657 if (offset == GWL_EXSTYLE && (changed & WS_EX_LAYERED)) /* changing WS_EX_LAYERED resets attributes */
1659 data->layered = FALSE;
1660 data->ulw_layered = FALSE;
1661 sync_window_opacity(data, 0, 0, FALSE, 0);
1662 if (data->surface) set_surface_use_alpha(data->surface, FALSE);
1665 if (offset == GWL_EXSTYLE && (changed & WS_EX_LAYOUTRTL))
1666 sync_window_region(data, (HRGN)1);
1669 release_win_data(data);
1673 /*****************************************************************
1674 * SetWindowText (MACDRV.@)
1676 void CDECL macdrv_SetWindowText(HWND hwnd, LPCWSTR text)
1678 macdrv_window win;
1680 TRACE("%p, %s\n", hwnd, debugstr_w(text));
1682 if ((win = macdrv_get_cocoa_window(hwnd, FALSE)))
1683 macdrv_set_cocoa_window_title(win, text, strlenW(text));
1687 /***********************************************************************
1688 * ShowWindow (MACDRV.@)
1690 UINT CDECL macdrv_ShowWindow(HWND hwnd, INT cmd, RECT *rect, UINT swp)
1692 struct macdrv_thread_data *thread_data = macdrv_thread_data();
1693 struct macdrv_win_data *data = get_win_data(hwnd);
1694 CGRect frame;
1696 TRACE("win %p/%p cmd %d at %s flags %08x\n",
1697 hwnd, data ? data->cocoa_window : NULL, cmd, wine_dbgstr_rect(rect), swp);
1699 if (!data || !data->cocoa_window) goto done;
1700 if (IsRectEmpty(rect)) goto done;
1701 if (GetWindowLongW(hwnd, GWL_STYLE) & WS_MINIMIZE)
1703 if (rect->left != -32000 || rect->top != -32000)
1705 OffsetRect(rect, -32000 - rect->left, -32000 - rect->top);
1706 swp &= ~(SWP_NOMOVE | SWP_NOCLIENTMOVE);
1708 goto done;
1710 if (!data->on_screen) goto done;
1712 /* only fetch the new rectangle if the ShowWindow was a result of an external event */
1714 if (!thread_data->current_event || thread_data->current_event->window != data->cocoa_window)
1715 goto done;
1717 if (thread_data->current_event->type != WINDOW_FRAME_CHANGED &&
1718 thread_data->current_event->type != WINDOW_DID_UNMINIMIZE)
1719 goto done;
1721 macdrv_get_cocoa_window_frame(data->cocoa_window, &frame);
1722 *rect = rect_from_cgrect(frame);
1723 macdrv_mac_to_window_rect(data, rect);
1724 TRACE("rect %s -> %s\n", wine_dbgstr_cgrect(frame), wine_dbgstr_rect(rect));
1725 swp &= ~(SWP_NOMOVE | SWP_NOCLIENTMOVE | SWP_NOSIZE | SWP_NOCLIENTSIZE);
1727 done:
1728 release_win_data(data);
1729 return swp;
1733 /***********************************************************************
1734 * SysCommand (MACDRV.@)
1736 * Perform WM_SYSCOMMAND handling.
1738 LRESULT CDECL macdrv_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam)
1740 struct macdrv_win_data *data;
1741 LRESULT ret = -1;
1742 WPARAM command = wparam & 0xfff0;
1744 TRACE("%p, %x, %lx\n", hwnd, (unsigned)wparam, lparam);
1746 if (!(data = get_win_data(hwnd))) goto done;
1747 if (!data->cocoa_window || !data->on_screen) goto done;
1749 /* prevent a simple ALT press+release from activating the system menu,
1750 as that can get confusing */
1751 if (command == SC_KEYMENU && !(WCHAR)lparam && !GetMenu(hwnd) &&
1752 (GetWindowLongW(hwnd, GWL_STYLE) & WS_SYSMENU))
1754 TRACE("ignoring SC_KEYMENU wp %lx lp %lx\n", wparam, lparam);
1755 ret = 0;
1758 if (command == SC_MOVE)
1760 release_win_data(data);
1761 return move_window(hwnd, wparam);
1764 done:
1765 release_win_data(data);
1766 return ret;
1770 /***********************************************************************
1771 * UpdateLayeredWindow (MACDRV.@)
1773 BOOL CDECL macdrv_UpdateLayeredWindow(HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
1774 const RECT *window_rect)
1776 struct window_surface *surface;
1777 struct macdrv_win_data *data;
1778 BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
1779 BYTE alpha;
1780 char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
1781 BITMAPINFO *bmi = (BITMAPINFO *)buffer;
1782 void *src_bits, *dst_bits;
1783 RECT rect;
1784 HDC hdc = 0;
1785 HBITMAP dib;
1786 BOOL ret = FALSE;
1788 if (!(data = get_win_data(hwnd))) return FALSE;
1790 data->layered = TRUE;
1791 data->ulw_layered = TRUE;
1793 rect = *window_rect;
1794 OffsetRect(&rect, -window_rect->left, -window_rect->top);
1796 surface = data->surface;
1797 if (!surface || !EqualRect(&surface->rect, &rect))
1799 data->surface = create_surface(data->cocoa_window, &rect, NULL, TRUE);
1800 set_window_surface(data->cocoa_window, data->surface);
1801 if (surface) window_surface_release(surface);
1802 surface = data->surface;
1803 if (data->unminimized_surface)
1805 window_surface_release(data->unminimized_surface);
1806 data->unminimized_surface = NULL;
1809 else set_surface_use_alpha(surface, TRUE);
1811 if (surface) window_surface_add_ref(surface);
1812 release_win_data(data);
1814 if (!surface) return FALSE;
1815 if (!info->hdcSrc)
1817 window_surface_release(surface);
1818 return TRUE;
1821 if (info->dwFlags & ULW_ALPHA)
1823 /* Apply SourceConstantAlpha via window alpha, not blend. */
1824 alpha = info->pblend->SourceConstantAlpha;
1825 blend = *info->pblend;
1826 blend.SourceConstantAlpha = 0xff;
1828 else
1829 alpha = 0xff;
1831 dst_bits = surface->funcs->get_info(surface, bmi);
1833 if (!(dib = CreateDIBSection(info->hdcDst, bmi, DIB_RGB_COLORS, &src_bits, NULL, 0))) goto done;
1834 if (!(hdc = CreateCompatibleDC(0))) goto done;
1836 SelectObject(hdc, dib);
1837 if (info->prcDirty)
1839 IntersectRect(&rect, &rect, info->prcDirty);
1840 surface->funcs->lock(surface);
1841 memcpy(src_bits, dst_bits, bmi->bmiHeader.biSizeImage);
1842 surface->funcs->unlock(surface);
1843 PatBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, BLACKNESS);
1845 if (!(ret = GdiAlphaBlend(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
1846 info->hdcSrc,
1847 rect.left + (info->pptSrc ? info->pptSrc->x : 0),
1848 rect.top + (info->pptSrc ? info->pptSrc->y : 0),
1849 rect.right - rect.left, rect.bottom - rect.top,
1850 blend)))
1851 goto done;
1853 if ((data = get_win_data(hwnd)))
1855 if (surface == data->surface)
1857 surface->funcs->lock(surface);
1858 memcpy(dst_bits, src_bits, bmi->bmiHeader.biSizeImage);
1859 add_bounds_rect(surface->funcs->get_bounds(surface), &rect);
1860 surface->funcs->unlock(surface);
1861 surface->funcs->flush(surface);
1864 /* The ULW flags are a superset of the LWA flags. */
1865 sync_window_opacity(data, info->crKey, alpha, TRUE, info->dwFlags);
1867 release_win_data(data);
1870 done:
1871 window_surface_release(surface);
1872 if (hdc) DeleteDC(hdc);
1873 if (dib) DeleteObject(dib);
1874 return ret;
1878 /**********************************************************************
1879 * WindowMessage (MACDRV.@)
1881 LRESULT CDECL macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1883 struct macdrv_win_data *data;
1885 TRACE("%p, %u, %u, %lu\n", hwnd, msg, (unsigned)wp, lp);
1887 switch(msg)
1889 case WM_MACDRV_SET_WIN_REGION:
1890 if ((data = get_win_data(hwnd)))
1892 sync_window_region(data, (HRGN)1);
1893 release_win_data(data);
1895 return 0;
1896 case WM_MACDRV_UPDATE_DESKTOP_RECT:
1897 if (hwnd == GetDesktopWindow())
1899 CGRect new_desktop_rect;
1900 RECT current_desktop_rect;
1902 macdrv_reset_device_metrics();
1903 new_desktop_rect = macdrv_get_desktop_rect();
1904 if (!GetWindowRect(hwnd, &current_desktop_rect) ||
1905 !CGRectEqualToRect(cgrect_from_rect(current_desktop_rect), new_desktop_rect))
1907 SendMessageTimeoutW(HWND_BROADCAST, WM_MACDRV_RESET_DEVICE_METRICS, 0, 0,
1908 SMTO_ABORTIFHUNG, 2000, NULL);
1909 SetWindowPos(hwnd, 0, CGRectGetMinX(new_desktop_rect), CGRectGetMinY(new_desktop_rect),
1910 CGRectGetWidth(new_desktop_rect), CGRectGetHeight(new_desktop_rect),
1911 SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE);
1912 SendMessageTimeoutW(HWND_BROADCAST, WM_MACDRV_DISPLAYCHANGE, wp, lp,
1913 SMTO_ABORTIFHUNG, 2000, NULL);
1916 return 0;
1917 case WM_MACDRV_RESET_DEVICE_METRICS:
1918 macdrv_reset_device_metrics();
1919 return 0;
1920 case WM_MACDRV_DISPLAYCHANGE:
1921 macdrv_reassert_window_position(hwnd);
1922 SendMessageW(hwnd, WM_DISPLAYCHANGE, wp, lp);
1923 return 0;
1924 case WM_MACDRV_ACTIVATE_ON_FOLLOWING_FOCUS:
1925 activate_on_following_focus();
1926 TRACE("WM_MACDRV_ACTIVATE_ON_FOLLOWING_FOCUS time %u\n", activate_on_focus_time);
1927 return 0;
1930 FIXME("unrecognized window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, wp, lp);
1931 return 0;
1935 static inline RECT get_surface_rect(const RECT *visible_rect)
1937 RECT rect;
1938 RECT desktop_rect = rect_from_cgrect(macdrv_get_desktop_rect());
1940 IntersectRect(&rect, visible_rect, &desktop_rect);
1941 OffsetRect(&rect, -visible_rect->left, -visible_rect->top);
1942 rect.left &= ~127;
1943 rect.top &= ~127;
1944 rect.right = max(rect.left + 128, (rect.right + 127) & ~127);
1945 rect.bottom = max(rect.top + 128, (rect.bottom + 127) & ~127);
1946 return rect;
1950 /***********************************************************************
1951 * WindowPosChanging (MACDRV.@)
1953 void CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags,
1954 const RECT *window_rect, const RECT *client_rect,
1955 RECT *visible_rect, struct window_surface **surface)
1957 struct macdrv_win_data *data = get_win_data(hwnd);
1958 DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
1959 RECT surface_rect;
1961 TRACE("%p after %p swp %04x window %s client %s visible %s surface %p\n", hwnd, insert_after,
1962 swp_flags, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
1963 wine_dbgstr_rect(visible_rect), surface);
1965 if (!data && !(data = macdrv_create_win_data(hwnd, window_rect, client_rect))) return;
1967 *visible_rect = *window_rect;
1968 macdrv_window_to_mac_rect(data, style, visible_rect);
1969 TRACE("visible_rect %s -> %s\n", wine_dbgstr_rect(window_rect),
1970 wine_dbgstr_rect(visible_rect));
1972 /* create the window surface if necessary */
1973 if (!data->cocoa_window) goto done;
1974 if (swp_flags & SWP_HIDEWINDOW) goto done;
1975 if (data->ulw_layered) goto done;
1977 if (*surface) window_surface_release(*surface);
1978 *surface = NULL;
1980 surface_rect = get_surface_rect(visible_rect);
1981 if (data->surface)
1983 if (EqualRect(&data->surface->rect, &surface_rect))
1985 /* existing surface is good enough */
1986 surface_clip_to_visible_rect(data->surface, visible_rect);
1987 window_surface_add_ref(data->surface);
1988 *surface = data->surface;
1989 goto done;
1992 else if (!(swp_flags & SWP_SHOWWINDOW) && !(style & WS_VISIBLE)) goto done;
1994 *surface = create_surface(data->cocoa_window, &surface_rect, data->surface, FALSE);
1996 done:
1997 release_win_data(data);
2001 /***********************************************************************
2002 * WindowPosChanged (MACDRV.@)
2004 void CDECL macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
2005 const RECT *window_rect, const RECT *client_rect,
2006 const RECT *visible_rect, const RECT *valid_rects,
2007 struct window_surface *surface)
2009 struct macdrv_thread_data *thread_data;
2010 struct macdrv_win_data *data;
2011 DWORD new_style = GetWindowLongW(hwnd, GWL_STYLE);
2012 RECT old_window_rect, old_whole_rect, old_client_rect;
2014 if (!(data = get_win_data(hwnd))) return;
2016 thread_data = macdrv_thread_data();
2018 old_window_rect = data->window_rect;
2019 old_whole_rect = data->whole_rect;
2020 old_client_rect = data->client_rect;
2021 data->window_rect = *window_rect;
2022 data->whole_rect = *visible_rect;
2023 data->client_rect = *client_rect;
2024 if (data->cocoa_window && !data->ulw_layered)
2026 if (surface) window_surface_add_ref(surface);
2027 if (new_style & WS_MINIMIZE)
2029 if (!data->unminimized_surface && data->surface)
2031 data->unminimized_surface = data->surface;
2032 window_surface_add_ref(data->unminimized_surface);
2035 else
2037 set_window_surface(data->cocoa_window, surface);
2038 if (data->unminimized_surface)
2040 window_surface_release(data->unminimized_surface);
2041 data->unminimized_surface = NULL;
2044 if (data->surface) window_surface_release(data->surface);
2045 data->surface = surface;
2048 TRACE("win %p/%p window %s whole %s client %s style %08x flags %08x surface %p\n",
2049 hwnd, data->cocoa_window, wine_dbgstr_rect(window_rect),
2050 wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(client_rect),
2051 new_style, swp_flags, surface);
2053 if (!IsRectEmpty(&valid_rects[0]))
2055 macdrv_window window = data->cocoa_window;
2056 int x_offset = old_whole_rect.left - data->whole_rect.left;
2057 int y_offset = old_whole_rect.top - data->whole_rect.top;
2059 /* if all that happened is that the whole window moved, copy everything */
2060 if (!(swp_flags & SWP_FRAMECHANGED) &&
2061 old_whole_rect.right - data->whole_rect.right == x_offset &&
2062 old_whole_rect.bottom - data->whole_rect.bottom == y_offset &&
2063 old_client_rect.left - data->client_rect.left == x_offset &&
2064 old_client_rect.right - data->client_rect.right == x_offset &&
2065 old_client_rect.top - data->client_rect.top == y_offset &&
2066 old_client_rect.bottom - data->client_rect.bottom == y_offset &&
2067 EqualRect(&valid_rects[0], &data->client_rect))
2069 /* A Cocoa window's bits are moved automatically */
2070 if (!window && (x_offset != 0 || y_offset != 0))
2072 release_win_data(data);
2073 move_window_bits(hwnd, window, &old_whole_rect, visible_rect,
2074 &old_client_rect, client_rect, window_rect);
2075 if (!(data = get_win_data(hwnd))) return;
2078 else
2080 release_win_data(data);
2081 move_window_bits(hwnd, window, &valid_rects[1], &valid_rects[0],
2082 &old_client_rect, client_rect, window_rect);
2083 if (!(data = get_win_data(hwnd))) return;
2087 sync_gl_view(data, &old_whole_rect, &old_client_rect);
2089 if (!data->cocoa_window && !data->cocoa_view) goto done;
2091 if (data->on_screen)
2093 if ((swp_flags & SWP_HIDEWINDOW) && !(new_style & WS_VISIBLE))
2094 hide_window(data);
2097 /* check if we are currently processing an event relevant to this window */
2098 if (!thread_data || !thread_data->current_event ||
2099 !data->cocoa_window || thread_data->current_event->window != data->cocoa_window ||
2100 (thread_data->current_event->type != WINDOW_FRAME_CHANGED &&
2101 thread_data->current_event->type != WINDOW_DID_UNMINIMIZE))
2103 sync_window_position(data, swp_flags, &old_window_rect, &old_whole_rect);
2104 if (data->cocoa_window)
2105 set_cocoa_window_properties(data);
2108 if (new_style & WS_VISIBLE)
2110 if (data->cocoa_window)
2112 if (!data->on_screen || (swp_flags & (SWP_FRAMECHANGED|SWP_STATECHANGED)))
2113 set_cocoa_window_properties(data);
2115 /* layered windows are not shown until their attributes are set */
2116 if (!data->on_screen &&
2117 (data->layered || !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED)))
2118 show_window(data);
2120 else if (!data->on_screen)
2121 show_window(data);
2124 done:
2125 release_win_data(data);
2129 /***********************************************************************
2130 * macdrv_window_close_requested
2132 * Handler for WINDOW_CLOSE_REQUESTED events.
2134 void macdrv_window_close_requested(HWND hwnd)
2136 HMENU sysmenu;
2138 if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
2140 TRACE("not closing win %p class style CS_NOCLOSE\n", hwnd);
2141 return;
2144 sysmenu = GetSystemMenu(hwnd, FALSE);
2145 if (sysmenu)
2147 UINT state = GetMenuState(sysmenu, SC_CLOSE, MF_BYCOMMAND);
2148 if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED)))
2150 TRACE("not closing win %p menu state 0x%08x\n", hwnd, state);
2151 return;
2155 perform_window_command(hwnd, 0, 0, SC_CLOSE, HTCLOSE);
2159 /***********************************************************************
2160 * macdrv_window_frame_changed
2162 * Handler for WINDOW_FRAME_CHANGED events.
2164 void macdrv_window_frame_changed(HWND hwnd, const macdrv_event *event)
2166 struct macdrv_win_data *data;
2167 RECT rect;
2168 HWND parent;
2169 UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
2170 int width, height;
2171 BOOL being_dragged;
2173 if (!hwnd) return;
2174 if (!(data = get_win_data(hwnd))) return;
2175 if (!data->on_screen || data->minimized)
2177 release_win_data(data);
2178 return;
2181 /* Get geometry */
2183 parent = GetAncestor(hwnd, GA_PARENT);
2185 TRACE("win %p/%p new Cocoa frame %s fullscreen %d in_resize %d\n", hwnd, data->cocoa_window,
2186 wine_dbgstr_cgrect(event->window_frame_changed.frame),
2187 event->window_frame_changed.fullscreen, event->window_frame_changed.in_resize);
2189 rect = rect_from_cgrect(event->window_frame_changed.frame);
2190 macdrv_mac_to_window_rect(data, &rect);
2191 MapWindowPoints(0, parent, (POINT *)&rect, 2);
2193 width = rect.right - rect.left;
2194 height = rect.bottom - rect.top;
2196 if (data->window_rect.left == rect.left && data->window_rect.top == rect.top)
2197 flags |= SWP_NOMOVE;
2198 else
2199 TRACE("%p moving from (%d,%d) to (%d,%d)\n", hwnd, data->window_rect.left,
2200 data->window_rect.top, rect.left, rect.top);
2202 if ((data->window_rect.right - data->window_rect.left == width &&
2203 data->window_rect.bottom - data->window_rect.top == height) ||
2204 (IsRectEmpty(&data->window_rect) && width == 1 && height == 1))
2205 flags |= SWP_NOSIZE;
2206 else
2207 TRACE("%p resizing from (%dx%d) to (%dx%d)\n", hwnd, data->window_rect.right - data->window_rect.left,
2208 data->window_rect.bottom - data->window_rect.top, width, height);
2210 being_dragged = data->being_dragged;
2211 release_win_data(data);
2213 if (event->window_frame_changed.fullscreen)
2214 flags |= SWP_NOSENDCHANGING;
2215 if (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE))
2217 if (!event->window_frame_changed.in_resize && !being_dragged)
2218 SendMessageW(hwnd, WM_ENTERSIZEMOVE, 0, 0);
2219 SetWindowPos(hwnd, 0, rect.left, rect.top, width, height, flags);
2220 if (!event->window_frame_changed.in_resize && !being_dragged)
2221 SendMessageW(hwnd, WM_EXITSIZEMOVE, 0, 0);
2226 /***********************************************************************
2227 * macdrv_window_got_focus
2229 * Handler for WINDOW_GOT_FOCUS events.
2231 void macdrv_window_got_focus(HWND hwnd, const macdrv_event *event)
2233 LONG style = GetWindowLongW(hwnd, GWL_STYLE);
2235 if (!hwnd) return;
2237 TRACE("win %p/%p serial %lu enabled %d visible %d style %08x focus %p active %p fg %p\n",
2238 hwnd, event->window, event->window_got_focus.serial, IsWindowEnabled(hwnd),
2239 IsWindowVisible(hwnd), style, GetFocus(), GetActiveWindow(), GetForegroundWindow());
2241 if (can_activate_window(hwnd) && !(style & WS_MINIMIZE))
2243 /* simulate a mouse click on the caption to find out
2244 * whether the window wants to be activated */
2245 LRESULT ma = SendMessageW(hwnd, WM_MOUSEACTIVATE,
2246 (WPARAM)GetAncestor(hwnd, GA_ROOT),
2247 MAKELONG(HTCAPTION,WM_LBUTTONDOWN));
2248 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE)
2250 TRACE("setting foreground window to %p\n", hwnd);
2251 SetForegroundWindow(hwnd);
2252 return;
2256 TRACE("win %p/%p rejecting focus\n", hwnd, event->window);
2257 macdrv_window_rejected_focus(event);
2261 /***********************************************************************
2262 * macdrv_window_lost_focus
2264 * Handler for WINDOW_LOST_FOCUS events.
2266 void macdrv_window_lost_focus(HWND hwnd, const macdrv_event *event)
2268 if (!hwnd) return;
2270 TRACE("win %p/%p fg %p\n", hwnd, event->window, GetForegroundWindow());
2272 if (hwnd == GetForegroundWindow())
2274 SendMessageW(hwnd, WM_CANCELMODE, 0, 0);
2275 if (hwnd == GetForegroundWindow())
2276 SetForegroundWindow(GetDesktopWindow());
2281 /***********************************************************************
2282 * macdrv_app_activated
2284 * Handler for APP_ACTIVATED events.
2286 void macdrv_app_activated(void)
2288 TRACE("\n");
2289 macdrv_UpdateClipboard();
2293 /***********************************************************************
2294 * macdrv_app_deactivated
2296 * Handler for APP_DEACTIVATED events.
2298 void macdrv_app_deactivated(void)
2300 if (GetActiveWindow() == GetForegroundWindow())
2302 TRACE("setting fg to desktop\n");
2303 SetForegroundWindow(GetDesktopWindow());
2308 /***********************************************************************
2309 * macdrv_window_maximize_requested
2311 * Handler for WINDOW_MAXIMIZE_REQUESTED events.
2313 void macdrv_window_maximize_requested(HWND hwnd)
2315 perform_window_command(hwnd, WS_MAXIMIZEBOX, WS_MAXIMIZE, SC_MAXIMIZE, HTMAXBUTTON);
2319 /***********************************************************************
2320 * macdrv_window_minimize_requested
2322 * Handler for WINDOW_MINIMIZE_REQUESTED events.
2324 void macdrv_window_minimize_requested(HWND hwnd)
2326 perform_window_command(hwnd, WS_MINIMIZEBOX, WS_MINIMIZE, SC_MINIMIZE, HTMINBUTTON);
2330 /***********************************************************************
2331 * macdrv_window_did_unminimize
2333 * Handler for WINDOW_DID_UNMINIMIZE events.
2335 void macdrv_window_did_unminimize(HWND hwnd)
2337 struct macdrv_win_data *data;
2338 DWORD style;
2340 TRACE("win %p\n", hwnd);
2342 if (!(data = get_win_data(hwnd))) return;
2343 if (!data->minimized) goto done;
2345 style = GetWindowLongW(hwnd, GWL_STYLE);
2347 data->minimized = FALSE;
2348 if ((style & (WS_MINIMIZE | WS_VISIBLE)) == (WS_MINIMIZE | WS_VISIBLE))
2350 TRACE("restoring win %p/%p\n", hwnd, data->cocoa_window);
2351 release_win_data(data);
2352 SendMessageW(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
2353 return;
2356 TRACE("not restoring win %p/%p style %08x\n", hwnd, data->cocoa_window, style);
2358 done:
2359 release_win_data(data);
2363 /***********************************************************************
2364 * macdrv_window_brought_forward
2366 * Handler for WINDOW_BROUGHT_FORWARD events.
2368 void macdrv_window_brought_forward(HWND hwnd)
2370 TRACE("win %p\n", hwnd);
2371 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
2375 /***********************************************************************
2376 * macdrv_window_resize_ended
2378 * Handler for WINDOW_RESIZE_ENDED events.
2380 void macdrv_window_resize_ended(HWND hwnd)
2382 TRACE("hwnd %p\n", hwnd);
2383 SendMessageW(hwnd, WM_EXITSIZEMOVE, 0, 0);
2387 /***********************************************************************
2388 * macdrv_window_restore_requested
2390 * Handler for WINDOW_RESTORE_REQUESTED events. This is specifically
2391 * for restoring from maximized, not from minimized.
2393 void macdrv_window_restore_requested(HWND hwnd, const macdrv_event *event)
2395 if (event->window_restore_requested.keep_frame && hwnd)
2397 DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
2398 struct macdrv_win_data *data;
2400 if ((style & WS_MAXIMIZE) && (style & WS_VISIBLE) && (data = get_win_data(hwnd)))
2402 RECT rect;
2403 HWND parent = GetAncestor(hwnd, GA_PARENT);
2405 rect = rect_from_cgrect(event->window_restore_requested.frame);
2406 macdrv_mac_to_window_rect(data, &rect);
2407 MapWindowPoints(0, parent, (POINT *)&rect, 2);
2409 release_win_data(data);
2411 SetInternalWindowPos(hwnd, SW_SHOW, &rect, NULL);
2415 perform_window_command(hwnd, WS_MAXIMIZE, 0, SC_RESTORE, HTMAXBUTTON);
2419 /***********************************************************************
2420 * macdrv_window_drag_begin
2422 * Handler for WINDOW_DRAG_BEGIN events.
2424 void macdrv_window_drag_begin(HWND hwnd)
2426 DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
2427 struct macdrv_win_data *data;
2428 MSG msg;
2430 TRACE("win %p\n", hwnd);
2432 if (style & (WS_DISABLED | WS_MAXIMIZE | WS_MINIMIZE)) return;
2433 if (!(style & WS_VISIBLE)) return;
2435 if (!(data = get_win_data(hwnd))) return;
2436 if (data->being_dragged) goto done;
2438 data->being_dragged = TRUE;
2439 release_win_data(data);
2441 ClipCursor(NULL);
2442 SendMessageW(hwnd, WM_ENTERSIZEMOVE, 0, 0);
2443 ReleaseCapture();
2445 while (GetMessageW(&msg, 0, 0, 0))
2447 if (msg.message == WM_EXITSIZEMOVE)
2449 SendMessageW(hwnd, WM_EXITSIZEMOVE, 0, 0);
2450 break;
2453 if (!CallMsgFilterW(&msg, MSGF_SIZE) && msg.message != WM_KEYDOWN &&
2454 msg.message != WM_MOUSEMOVE && msg.message != WM_LBUTTONDOWN && msg.message != WM_LBUTTONUP)
2456 TranslateMessage(&msg);
2457 DispatchMessageW(&msg);
2461 TRACE("done\n");
2463 if ((data = get_win_data(hwnd)))
2464 data->being_dragged = FALSE;
2466 done:
2467 release_win_data(data);
2471 /***********************************************************************
2472 * macdrv_window_drag_end
2474 * Handler for WINDOW_DRAG_END events.
2476 void macdrv_window_drag_end(HWND hwnd)
2478 struct macdrv_win_data *data;
2479 BOOL being_dragged;
2481 TRACE("win %p\n", hwnd);
2483 if (!(data = get_win_data(hwnd))) return;
2484 being_dragged = data->being_dragged;
2485 release_win_data(data);
2487 if (being_dragged)
2489 /* Post this rather than sending it, so that the message loop in
2490 macdrv_window_drag_begin() will see it. */
2491 PostMessageW(hwnd, WM_EXITSIZEMOVE, 0, 0);
2496 /***********************************************************************
2497 * macdrv_reassert_window_position
2499 * Handler for REASSERT_WINDOW_POSITION events.
2501 void macdrv_reassert_window_position(HWND hwnd)
2503 struct macdrv_win_data *data = get_win_data(hwnd);
2504 if (data)
2506 if (data->cocoa_window && data->on_screen)
2507 sync_window_position(data, SWP_NOZORDER | SWP_NOACTIVATE, NULL, NULL);
2508 release_win_data(data);
2513 struct quit_info {
2514 HWND *wins;
2515 UINT capacity;
2516 UINT count;
2517 UINT done;
2518 DWORD flags;
2519 BOOL result;
2520 BOOL replied;
2524 static BOOL CALLBACK get_process_windows(HWND hwnd, LPARAM lp)
2526 struct quit_info *qi = (struct quit_info*)lp;
2527 DWORD pid;
2529 GetWindowThreadProcessId(hwnd, &pid);
2530 if (pid == GetCurrentProcessId())
2532 if (qi->count >= qi->capacity)
2534 UINT new_cap = qi->capacity * 2;
2535 HWND *new_wins = HeapReAlloc(GetProcessHeap(), 0, qi->wins,
2536 new_cap * sizeof(*qi->wins));
2537 if (!new_wins) return FALSE;
2538 qi->wins = new_wins;
2539 qi->capacity = new_cap;
2542 qi->wins[qi->count++] = hwnd;
2545 return TRUE;
2549 static void CALLBACK quit_callback(HWND hwnd, UINT msg, ULONG_PTR data, LRESULT result)
2551 struct quit_info *qi = (struct quit_info*)data;
2553 qi->done++;
2555 if (msg == WM_QUERYENDSESSION)
2557 TRACE("got WM_QUERYENDSESSION result %ld from win %p (%u of %u done)\n", result,
2558 hwnd, qi->done, qi->count);
2560 if (!result && !IsWindow(hwnd))
2562 TRACE("win %p no longer exists; ignoring apparent refusal\n", hwnd);
2563 result = TRUE;
2566 if (!result && qi->result)
2568 qi->result = FALSE;
2570 /* On the first FALSE from WM_QUERYENDSESSION, we already know the
2571 ultimate reply. Might as well tell Cocoa now. */
2572 if (!qi->replied)
2574 qi->replied = TRUE;
2575 TRACE("giving quit reply %d\n", qi->result);
2576 macdrv_quit_reply(qi->result);
2580 if (qi->done >= qi->count)
2582 UINT i;
2584 qi->done = 0;
2585 for (i = 0; i < qi->count; i++)
2587 TRACE("sending WM_ENDSESSION to win %p result %d flags 0x%08x\n", qi->wins[i],
2588 qi->result, qi->flags);
2589 if (!SendMessageCallbackW(qi->wins[i], WM_ENDSESSION, qi->result, qi->flags,
2590 quit_callback, (ULONG_PTR)qi))
2592 WARN("failed to send WM_ENDSESSION to win %p; error 0x%08x\n",
2593 qi->wins[i], GetLastError());
2594 quit_callback(qi->wins[i], WM_ENDSESSION, (ULONG_PTR)qi, 0);
2599 else /* WM_ENDSESSION */
2601 TRACE("finished WM_ENDSESSION for win %p (%u of %u done)\n", hwnd, qi->done, qi->count);
2603 if (qi->done >= qi->count)
2605 if (!qi->replied)
2607 TRACE("giving quit reply %d\n", qi->result);
2608 macdrv_quit_reply(qi->result);
2611 TRACE("%sterminating process\n", qi->result ? "" : "not ");
2612 if (qi->result)
2613 TerminateProcess(GetCurrentProcess(), 0);
2615 HeapFree(GetProcessHeap(), 0, qi->wins);
2616 HeapFree(GetProcessHeap(), 0, qi);
2622 /***********************************************************************
2623 * macdrv_app_quit_requested
2625 * Handler for APP_QUIT_REQUESTED events.
2627 void macdrv_app_quit_requested(const macdrv_event *event)
2629 struct quit_info *qi;
2630 UINT i;
2632 TRACE("reason %d\n", event->app_quit_requested.reason);
2634 qi = HeapAlloc(GetProcessHeap(), 0, sizeof(*qi));
2635 if (!qi)
2636 goto fail;
2638 qi->capacity = 32;
2639 qi->wins = HeapAlloc(GetProcessHeap(), 0, qi->capacity * sizeof(*qi->wins));
2640 qi->count = qi->done = 0;
2642 if (!qi->wins || !EnumWindows(get_process_windows, (LPARAM)qi))
2643 goto fail;
2645 switch (event->app_quit_requested.reason)
2647 case QUIT_REASON_LOGOUT:
2648 default:
2649 qi->flags = ENDSESSION_LOGOFF;
2650 break;
2651 case QUIT_REASON_RESTART:
2652 case QUIT_REASON_SHUTDOWN:
2653 qi->flags = 0;
2654 break;
2657 qi->result = TRUE;
2658 qi->replied = FALSE;
2660 for (i = 0; i < qi->count; i++)
2662 TRACE("sending WM_QUERYENDSESSION to win %p\n", qi->wins[i]);
2663 if (!SendMessageCallbackW(qi->wins[i], WM_QUERYENDSESSION, 0, qi->flags,
2664 quit_callback, (ULONG_PTR)qi))
2666 DWORD error = GetLastError();
2667 BOOL invalid = (error == ERROR_INVALID_WINDOW_HANDLE);
2668 if (invalid)
2669 TRACE("failed to send WM_QUERYENDSESSION to win %p because it's invalid; assuming success\n",
2670 qi->wins[i]);
2671 else
2672 WARN("failed to send WM_QUERYENDSESSION to win %p; error 0x%08x; assuming refusal\n",
2673 qi->wins[i], error);
2674 quit_callback(qi->wins[i], WM_QUERYENDSESSION, (ULONG_PTR)qi, invalid);
2678 /* quit_callback() will clean up qi */
2679 return;
2681 fail:
2682 WARN("failed to allocate window list\n");
2683 if (qi)
2685 HeapFree(GetProcessHeap(), 0, qi->wins);
2686 HeapFree(GetProcessHeap(), 0, qi);
2688 macdrv_quit_reply(FALSE);
2692 /***********************************************************************
2693 * query_resize_size
2695 * Handler for QUERY_RESIZE_SIZE query.
2697 BOOL query_resize_size(HWND hwnd, macdrv_query *query)
2699 struct macdrv_win_data *data = get_win_data(hwnd);
2700 RECT rect = rect_from_cgrect(query->resize_size.rect);
2701 int corner;
2702 BOOL ret = FALSE;
2704 if (!data) return FALSE;
2706 macdrv_mac_to_window_rect(data, &rect);
2708 if (query->resize_size.from_left)
2710 if (query->resize_size.from_top)
2711 corner = WMSZ_TOPLEFT;
2712 else
2713 corner = WMSZ_BOTTOMLEFT;
2715 else if (query->resize_size.from_top)
2716 corner = WMSZ_TOPRIGHT;
2717 else
2718 corner = WMSZ_BOTTOMRIGHT;
2720 if (SendMessageW(hwnd, WM_SIZING, corner, (LPARAM)&rect))
2722 macdrv_window_to_mac_rect(data, GetWindowLongW(hwnd, GWL_STYLE), &rect);
2723 query->resize_size.rect = cgrect_from_rect(rect);
2724 ret = TRUE;
2727 release_win_data(data);
2728 return ret;
2732 /***********************************************************************
2733 * query_resize_start
2735 * Handler for QUERY_RESIZE_START query.
2737 BOOL query_resize_start(HWND hwnd)
2739 TRACE("hwnd %p\n", hwnd);
2741 sync_window_min_max_info(hwnd);
2742 SendMessageW(hwnd, WM_ENTERSIZEMOVE, 0, 0);
2744 return TRUE;
2748 /***********************************************************************
2749 * query_min_max_info
2751 * Handler for QUERY_MIN_MAX_INFO query.
2753 BOOL query_min_max_info(HWND hwnd)
2755 TRACE("hwnd %p\n", hwnd);
2756 sync_window_min_max_info(hwnd);
2757 return TRUE;