dxdiagn: Remove DECLSPEC_HIDDEN usage.
[wine.git] / dlls / winemac.drv / window.c
blob67f45d301df3cc0ead8afd52f5a2356ae5f55bf4
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 #if 0
25 #pragma makedep unix
26 #endif
28 #include "config.h"
30 #include <IOKit/pwr_mgt/IOPMLib.h>
31 #define GetCurrentThread Mac_GetCurrentThread
32 #define LoadResource Mac_LoadResource
33 #include <CoreServices/CoreServices.h>
34 #undef GetCurrentThread
35 #undef LoadResource
37 #include "macdrv.h"
38 #include "wine/server.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
43 static pthread_mutex_t win_data_mutex;
44 static CFMutableDictionaryRef win_datas;
46 static unsigned int activate_on_focus_time;
49 /***********************************************************************
50 * get_cocoa_window_features
52 static void get_cocoa_window_features(struct macdrv_win_data *data,
53 DWORD style, DWORD ex_style,
54 struct macdrv_window_features* wf,
55 const RECT *window_rect,
56 const RECT *client_rect)
58 memset(wf, 0, sizeof(*wf));
60 if (ex_style & WS_EX_NOACTIVATE) wf->prevents_app_activation = TRUE;
62 if (disable_window_decorations) return;
63 if (IsRectEmpty(window_rect)) return;
64 if (EqualRect(window_rect, client_rect)) return;
66 if ((style & WS_CAPTION) == WS_CAPTION && !(ex_style & WS_EX_LAYERED))
68 wf->shadow = TRUE;
69 if (!data->shaped)
71 wf->title_bar = TRUE;
72 if (style & WS_SYSMENU) wf->close_button = TRUE;
73 if (style & WS_MINIMIZEBOX) wf->minimize_button = TRUE;
74 if (style & WS_MAXIMIZEBOX) wf->maximize_button = TRUE;
75 if (ex_style & WS_EX_TOOLWINDOW) wf->utility = TRUE;
78 if (style & WS_THICKFRAME)
80 wf->shadow = TRUE;
81 if (!data->shaped) wf->resizable = TRUE;
83 else if (ex_style & WS_EX_DLGMODALFRAME) wf->shadow = TRUE;
84 else if ((style & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) wf->shadow = TRUE;
88 /*******************************************************************
89 * can_window_become_foreground
91 * Check if the specified window can become the foreground/key
92 * window.
94 static inline BOOL can_window_become_foreground(HWND hwnd)
96 LONG style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
98 if (!(style & WS_VISIBLE)) return FALSE;
99 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
100 if (hwnd == NtUserGetDesktopWindow()) return FALSE;
101 return !(style & WS_DISABLED);
105 /***********************************************************************
106 * get_cocoa_window_state
108 static void get_cocoa_window_state(struct macdrv_win_data *data,
109 DWORD style, DWORD ex_style,
110 struct macdrv_window_state* state)
112 memset(state, 0, sizeof(*state));
113 state->disabled = (style & WS_DISABLED) != 0;
114 state->no_foreground = !can_window_become_foreground(data->hwnd);
115 state->floating = (ex_style & WS_EX_TOPMOST) != 0;
116 state->excluded_by_expose = state->excluded_by_cycle =
117 (!(ex_style & WS_EX_APPWINDOW) &&
118 (NtUserGetWindowRelative(data->hwnd, GW_OWNER) || (ex_style & (WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE))));
119 if (IsRectEmpty(&data->window_rect))
120 state->excluded_by_expose = TRUE;
121 state->minimized = (style & WS_MINIMIZE) != 0;
122 state->minimized_valid = state->minimized != data->minimized;
123 state->maximized = (style & WS_MAXIMIZE) != 0;
127 /***********************************************************************
128 * get_mac_rect_offset
130 * Helper for macdrv_window_to_mac_rect and macdrv_mac_to_window_rect.
132 static void get_mac_rect_offset(struct macdrv_win_data *data, unsigned int style, RECT *rect,
133 const RECT *window_rect, const RECT *client_rect)
135 unsigned int ex_style, style_mask = 0, ex_style_mask = 0;
137 rect->top = rect->bottom = rect->left = rect->right = 0;
139 ex_style = NtUserGetWindowLongW(data->hwnd, GWL_EXSTYLE);
141 if (!data->shaped)
143 struct macdrv_window_features wf;
144 get_cocoa_window_features(data, style, ex_style, &wf, window_rect, client_rect);
146 if (wf.title_bar)
148 style_mask |= WS_CAPTION;
149 ex_style_mask |= WS_EX_TOOLWINDOW;
151 if (wf.shadow)
153 style_mask |= WS_DLGFRAME | WS_THICKFRAME;
154 ex_style_mask |= WS_EX_DLGMODALFRAME;
158 AdjustWindowRectEx(rect, style & style_mask, FALSE, ex_style & ex_style_mask);
160 TRACE("%p/%p style %08x ex_style %08x shaped %d -> %s\n", data->hwnd, data->cocoa_window,
161 style, ex_style, data->shaped, wine_dbgstr_rect(rect));
165 /***********************************************************************
166 * macdrv_window_to_mac_rect
168 * Convert a rect from client to Mac window coordinates
170 static void macdrv_window_to_mac_rect(struct macdrv_win_data *data, DWORD style, RECT *rect,
171 const RECT *window_rect, const RECT *client_rect)
173 RECT rc;
175 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return;
176 if (IsRectEmpty(rect)) return;
178 get_mac_rect_offset(data, style, &rc, window_rect, client_rect);
180 rect->left -= rc.left;
181 rect->right -= rc.right;
182 rect->top -= rc.top;
183 rect->bottom -= rc.bottom;
184 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
185 if (rect->left >= rect->right) rect->right = rect->left + 1;
189 /***********************************************************************
190 * macdrv_mac_to_window_rect
192 * Opposite of macdrv_window_to_mac_rect
194 static void macdrv_mac_to_window_rect(struct macdrv_win_data *data, RECT *rect)
196 RECT rc;
197 DWORD style = NtUserGetWindowLongW(data->hwnd, GWL_STYLE);
199 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return;
200 if (IsRectEmpty(rect)) return;
202 get_mac_rect_offset(data, style, &rc, &data->window_rect, &data->client_rect);
204 rect->left += rc.left;
205 rect->right += rc.right;
206 rect->top += rc.top;
207 rect->bottom += rc.bottom;
208 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
209 if (rect->left >= rect->right) rect->right = rect->left + 1;
213 /***********************************************************************
214 * constrain_window_frame
216 * Alter a window frame rectangle to fit within a) Cocoa's documented
217 * limits, and b) sane sizes, like twice the desktop rect.
219 static void constrain_window_frame(CGPoint* origin, CGSize* size)
221 CGRect desktop_rect = macdrv_get_desktop_rect();
222 int max_width, max_height;
224 max_width = min(32000, 2 * CGRectGetWidth(desktop_rect));
225 max_height = min(32000, 2 * CGRectGetHeight(desktop_rect));
227 if (origin)
229 if (origin->x < -16000) origin->x = -16000;
230 if (origin->y < -16000) origin->y = -16000;
231 if (origin->x > 16000) origin->x = 16000;
232 if (origin->y > 16000) origin->y = 16000;
234 if (size)
236 if (size->width > max_width) size->width = max_width;
237 if (size->height > max_height) size->height = max_height;
242 /***********************************************************************
243 * alloc_win_data
245 static struct macdrv_win_data *alloc_win_data(HWND hwnd)
247 struct macdrv_win_data *data;
249 if ((data = calloc(1, sizeof(*data))))
251 data->hwnd = hwnd;
252 data->color_key = CLR_INVALID;
253 data->swap_interval = 1;
254 pthread_mutex_lock(&win_data_mutex);
255 if (!win_datas)
256 win_datas = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
257 CFDictionarySetValue(win_datas, hwnd, data);
259 return data;
263 /***********************************************************************
264 * get_win_data
266 * Lock and return the data structure associated with a window.
268 struct macdrv_win_data *get_win_data(HWND hwnd)
270 struct macdrv_win_data *data;
272 if (!hwnd) return NULL;
273 pthread_mutex_lock(&win_data_mutex);
274 if (win_datas && (data = (struct macdrv_win_data*)CFDictionaryGetValue(win_datas, hwnd)))
275 return data;
276 pthread_mutex_unlock(&win_data_mutex);
277 return NULL;
281 /***********************************************************************
282 * release_win_data
284 * Release the data returned by get_win_data.
286 void release_win_data(struct macdrv_win_data *data)
288 if (data) pthread_mutex_unlock(&win_data_mutex);
292 /***********************************************************************
293 * macdrv_get_cocoa_window
295 * Return the Mac window associated with the full area of a window
297 macdrv_window macdrv_get_cocoa_window(HWND hwnd, BOOL require_on_screen)
299 struct macdrv_win_data *data = get_win_data(hwnd);
300 macdrv_window ret = NULL;
301 if (data && (data->on_screen || !require_on_screen))
302 ret = data->cocoa_window;
303 release_win_data(data);
304 return ret;
308 /***********************************************************************
309 * macdrv_get_cocoa_view
311 * Return the Cocoa view associated with a window
313 macdrv_view macdrv_get_cocoa_view(HWND hwnd)
315 struct macdrv_win_data *data = get_win_data(hwnd);
316 macdrv_view ret = data ? data->cocoa_view : NULL;
318 release_win_data(data);
319 return ret;
323 /***********************************************************************
324 * macdrv_get_client_cocoa_view
326 * Return the Cocoa view associated with a window's client area
328 macdrv_view macdrv_get_client_cocoa_view(HWND hwnd)
330 struct macdrv_win_data *data = get_win_data(hwnd);
331 macdrv_view ret = data ? data->client_cocoa_view : NULL;
333 release_win_data(data);
334 return ret;
338 /***********************************************************************
339 * set_cocoa_window_properties
341 * Set the window properties for a Cocoa window based on its Windows
342 * properties.
344 static void set_cocoa_window_properties(struct macdrv_win_data *data)
346 DWORD style, ex_style;
347 HWND owner;
348 macdrv_window owner_win;
349 struct macdrv_window_features wf;
350 struct macdrv_window_state state;
352 style = NtUserGetWindowLongW(data->hwnd, GWL_STYLE);
353 ex_style = NtUserGetWindowLongW(data->hwnd, GWL_EXSTYLE);
355 owner = NtUserGetWindowRelative(data->hwnd, GW_OWNER);
356 if (owner)
357 owner = NtUserGetAncestor(owner, GA_ROOT);
358 owner_win = macdrv_get_cocoa_window(owner, TRUE);
359 macdrv_set_cocoa_parent_window(data->cocoa_window, owner_win);
361 get_cocoa_window_features(data, style, ex_style, &wf, &data->window_rect, &data->client_rect);
362 macdrv_set_cocoa_window_features(data->cocoa_window, &wf);
364 get_cocoa_window_state(data, style, ex_style, &state);
365 macdrv_set_cocoa_window_state(data->cocoa_window, &state);
366 if (state.minimized_valid)
367 data->minimized = state.minimized;
371 /***********************************************************************
372 * sync_window_region
374 * Update the window region.
376 static void sync_window_region(struct macdrv_win_data *data, HRGN win_region)
378 HRGN hrgn = win_region;
379 RGNDATA *region_data;
380 const CGRect* rects;
381 int count;
383 if (!data->cocoa_window) return;
384 data->shaped = FALSE;
386 if (IsRectEmpty(&data->window_rect)) /* set an empty shape */
388 TRACE("win %p/%p setting empty shape for zero-sized window\n", data->hwnd, data->cocoa_window);
389 macdrv_set_window_shape(data->cocoa_window, &CGRectZero, 1);
390 return;
393 if (hrgn == (HRGN)1) /* hack: win_region == 1 means retrieve region from server */
395 if (!(hrgn = NtGdiCreateRectRgn(0, 0, 0, 0))) return;
396 if (NtUserGetWindowRgnEx(data->hwnd, hrgn, 0) == ERROR)
398 NtGdiDeleteObjectApp(hrgn);
399 hrgn = 0;
403 if (hrgn && NtUserGetWindowLongW(data->hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
404 NtUserMirrorRgn(data->hwnd, hrgn);
405 if (hrgn)
407 NtGdiOffsetRgn(hrgn, data->window_rect.left - data->whole_rect.left,
408 data->window_rect.top - data->whole_rect.top);
410 region_data = get_region_data(hrgn, 0);
411 if (region_data)
413 rects = (CGRect*)region_data->Buffer;
414 count = region_data->rdh.nCount;
415 /* Special case optimization. If the region entirely encloses the Cocoa
416 window, it's the same as there being no region. It's potentially
417 hard/slow to test this for arbitrary regions, so we just check for
418 very simple regions. */
419 if (count == 1 && CGRectContainsRect(rects[0],
420 CGRectOffset(cgrect_from_rect(data->whole_rect), -data->whole_rect.left, -data->whole_rect.top)))
422 TRACE("optimizing for simple region that contains Cocoa content rect\n");
423 rects = NULL;
424 count = 0;
427 else
429 rects = NULL;
430 count = 0;
433 TRACE("win %p/%p win_region %p rects %p count %d\n", data->hwnd, data->cocoa_window, win_region, rects, count);
434 macdrv_set_window_shape(data->cocoa_window, rects, count);
436 free(region_data);
437 data->shaped = (region_data != NULL);
439 if (hrgn && hrgn != win_region) NtGdiDeleteObjectApp(hrgn);
443 /***********************************************************************
444 * add_bounds_rect
446 static inline void add_bounds_rect(RECT *bounds, const RECT *rect)
448 if (rect->left >= rect->right || rect->top >= rect->bottom) return;
449 bounds->left = min(bounds->left, rect->left);
450 bounds->top = min(bounds->top, rect->top);
451 bounds->right = max(bounds->right, rect->right);
452 bounds->bottom = max(bounds->bottom, rect->bottom);
456 /***********************************************************************
457 * sync_window_opacity
459 static void sync_window_opacity(struct macdrv_win_data *data, COLORREF key, BYTE alpha,
460 BOOL per_pixel_alpha, DWORD flags)
462 CGFloat opacity = 1.0;
463 BOOL needs_flush = FALSE;
465 if (flags & LWA_ALPHA) opacity = alpha / 255.0;
467 TRACE("setting window %p/%p alpha to %g\n", data->hwnd, data->cocoa_window, opacity);
468 macdrv_set_window_alpha(data->cocoa_window, opacity);
470 if (flags & LWA_COLORKEY)
472 /* FIXME: treat PALETTEINDEX and DIBINDEX as black */
473 if ((key & (1 << 24)) || key >> 16 == 0x10ff)
474 key = RGB(0, 0, 0);
476 else
477 key = CLR_INVALID;
479 if (data->color_key != key)
481 if (key == CLR_INVALID)
483 TRACE("clearing color-key for window %p/%p\n", data->hwnd, data->cocoa_window);
484 macdrv_clear_window_color_key(data->cocoa_window);
486 else
488 TRACE("setting color-key for window %p/%p to RGB %d,%d,%d\n", data->hwnd, data->cocoa_window,
489 GetRValue(key), GetGValue(key), GetBValue(key));
490 macdrv_set_window_color_key(data->cocoa_window, GetRValue(key), GetGValue(key), GetBValue(key));
493 data->color_key = key;
494 needs_flush = TRUE;
497 if (!data->per_pixel_alpha != !per_pixel_alpha)
499 TRACE("setting window %p/%p per-pixel-alpha to %d\n", data->hwnd, data->cocoa_window, per_pixel_alpha);
500 macdrv_window_use_per_pixel_alpha(data->cocoa_window, per_pixel_alpha);
501 data->per_pixel_alpha = per_pixel_alpha;
502 needs_flush = TRUE;
505 if (needs_flush && data->surface)
507 RECT *bounds;
508 RECT rect;
510 rect = data->whole_rect;
511 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
512 data->surface->funcs->lock(data->surface);
513 bounds = data->surface->funcs->get_bounds(data->surface);
514 add_bounds_rect(bounds, &rect);
515 data->surface->funcs->unlock(data->surface);
520 /***********************************************************************
521 * sync_window_min_max_info
523 static void sync_window_min_max_info(HWND hwnd)
525 LONG style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
526 LONG exstyle = NtUserGetWindowLongW(hwnd, GWL_EXSTYLE);
527 RECT win_rect, primary_monitor_rect;
528 MINMAXINFO minmax;
529 LONG adjustedStyle;
530 INT xinc, yinc;
531 WINDOWPLACEMENT wpl;
532 HMONITOR monitor;
533 struct macdrv_win_data *data;
535 TRACE("win %p\n", hwnd);
537 if (!macdrv_get_cocoa_window(hwnd, FALSE)) return;
539 NtUserGetWindowRect(hwnd, &win_rect);
540 minmax.ptReserved.x = win_rect.left;
541 minmax.ptReserved.y = win_rect.top;
543 if ((style & WS_CAPTION) == WS_CAPTION)
544 adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
545 else
546 adjustedStyle = style;
548 primary_monitor_rect.left = primary_monitor_rect.top = 0;
549 primary_monitor_rect.right = NtUserGetSystemMetrics(SM_CXSCREEN);
550 primary_monitor_rect.bottom = NtUserGetSystemMetrics(SM_CYSCREEN);
551 AdjustWindowRectEx(&primary_monitor_rect, adjustedStyle,
552 ((style & WS_POPUP) && NtUserGetWindowLongPtrW(hwnd, GWLP_ID)), exstyle);
554 xinc = -primary_monitor_rect.left;
555 yinc = -primary_monitor_rect.top;
557 minmax.ptMaxSize.x = primary_monitor_rect.right - primary_monitor_rect.left;
558 minmax.ptMaxSize.y = primary_monitor_rect.bottom - primary_monitor_rect.top;
559 minmax.ptMaxPosition.x = -xinc;
560 minmax.ptMaxPosition.y = -yinc;
561 if (style & (WS_DLGFRAME | WS_BORDER))
563 minmax.ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK);
564 minmax.ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK);
566 else
568 minmax.ptMinTrackSize.x = 2 * xinc;
569 minmax.ptMinTrackSize.y = 2 * yinc;
571 minmax.ptMaxTrackSize.x = NtUserGetSystemMetrics(SM_CXMAXTRACK);
572 minmax.ptMaxTrackSize.y = NtUserGetSystemMetrics(SM_CYMAXTRACK);
574 wpl.length = sizeof(wpl);
575 if (NtUserGetWindowPlacement(hwnd, &wpl) && (wpl.ptMaxPosition.x != -1 || wpl.ptMaxPosition.y != -1))
577 minmax.ptMaxPosition = wpl.ptMaxPosition;
579 /* Convert from GetWindowPlacement's workspace coordinates to screen coordinates. */
580 minmax.ptMaxPosition.x -= wpl.rcNormalPosition.left - win_rect.left;
581 minmax.ptMaxPosition.y -= wpl.rcNormalPosition.top - win_rect.top;
584 TRACE("initial ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax.ptMaxSize),
585 wine_dbgstr_point(&minmax.ptMaxPosition), wine_dbgstr_point(&minmax.ptMinTrackSize), wine_dbgstr_point(&minmax.ptMaxTrackSize));
587 send_message(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&minmax);
589 TRACE("app's ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax.ptMaxSize),
590 wine_dbgstr_point(&minmax.ptMaxPosition), wine_dbgstr_point(&minmax.ptMinTrackSize), wine_dbgstr_point(&minmax.ptMaxTrackSize));
592 /* if the app didn't change the values, adapt them for the window's monitor */
593 if ((monitor = NtUserMonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY)))
595 MONITORINFO mon_info;
596 RECT monitor_rect;
598 mon_info.cbSize = sizeof(mon_info);
599 NtUserGetMonitorInfo(monitor, &mon_info);
601 if ((style & WS_MAXIMIZEBOX) && ((style & WS_CAPTION) == WS_CAPTION || !(style & WS_POPUP)))
602 monitor_rect = mon_info.rcWork;
603 else
604 monitor_rect = mon_info.rcMonitor;
606 if (minmax.ptMaxSize.x == primary_monitor_rect.right - primary_monitor_rect.left &&
607 minmax.ptMaxSize.y == primary_monitor_rect.bottom - primary_monitor_rect.top)
609 minmax.ptMaxSize.x = (monitor_rect.right - monitor_rect.left) + 2 * xinc;
610 minmax.ptMaxSize.y = (monitor_rect.bottom - monitor_rect.top) + 2 * yinc;
612 if (minmax.ptMaxPosition.x == -xinc && minmax.ptMaxPosition.y == -yinc)
614 minmax.ptMaxPosition.x = monitor_rect.left - xinc;
615 minmax.ptMaxPosition.y = monitor_rect.top - yinc;
619 minmax.ptMaxTrackSize.x = max(minmax.ptMaxTrackSize.x, minmax.ptMinTrackSize.x);
620 minmax.ptMaxTrackSize.y = max(minmax.ptMaxTrackSize.y, minmax.ptMinTrackSize.y);
622 TRACE("adjusted ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax.ptMaxSize),
623 wine_dbgstr_point(&minmax.ptMaxPosition), wine_dbgstr_point(&minmax.ptMinTrackSize), wine_dbgstr_point(&minmax.ptMaxTrackSize));
625 if ((data = get_win_data(hwnd)) && data->cocoa_window)
627 RECT min_rect, max_rect;
628 CGSize min_size, max_size;
630 SetRect(&min_rect, 0, 0, minmax.ptMinTrackSize.x, minmax.ptMinTrackSize.y);
631 macdrv_window_to_mac_rect(data, style, &min_rect, &data->window_rect, &data->client_rect);
632 min_size = CGSizeMake(min_rect.right - min_rect.left, min_rect.bottom - min_rect.top);
634 if (minmax.ptMaxTrackSize.x == NtUserGetSystemMetrics(SM_CXMAXTRACK) &&
635 minmax.ptMaxTrackSize.y == NtUserGetSystemMetrics(SM_CYMAXTRACK))
636 max_size = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX);
637 else
639 SetRect(&max_rect, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y);
640 macdrv_window_to_mac_rect(data, style, &max_rect, &data->window_rect, &data->client_rect);
641 max_size = CGSizeMake(max_rect.right - max_rect.left, max_rect.bottom - max_rect.top);
644 constrain_window_frame(NULL, &max_size);
646 TRACE("min_size (%g,%g) max_size (%g,%g)\n", min_size.width, min_size.height, max_size.width, max_size.height);
647 macdrv_set_window_min_max_sizes(data->cocoa_window, min_size, max_size);
650 release_win_data(data);
654 /**********************************************************************
655 * create_client_cocoa_view
657 * Create the Cocoa view for a window's client area
659 static void create_client_cocoa_view(struct macdrv_win_data *data)
661 RECT rect = data->client_rect;
662 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
664 if (data->client_cocoa_view)
665 macdrv_set_view_frame(data->client_cocoa_view, cgrect_from_rect(rect));
666 else
668 data->client_cocoa_view = macdrv_create_view(cgrect_from_rect(rect));
669 macdrv_set_view_hidden(data->client_cocoa_view, FALSE);
671 macdrv_set_view_superview(data->client_cocoa_view, data->cocoa_view, data->cocoa_window, NULL, NULL);
675 /**********************************************************************
676 * create_cocoa_window
678 * Create the whole Mac window for a given window
680 static void create_cocoa_window(struct macdrv_win_data *data)
682 struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
683 WCHAR text[1024];
684 struct macdrv_window_features wf;
685 CGRect frame;
686 DWORD style, ex_style;
687 HRGN win_rgn;
688 COLORREF key;
689 BYTE alpha;
690 DWORD layered_flags;
692 if ((win_rgn = NtGdiCreateRectRgn(0, 0, 0, 0)) &&
693 NtUserGetWindowRgnEx(data->hwnd, win_rgn, 0) == ERROR)
695 NtGdiDeleteObjectApp(win_rgn);
696 win_rgn = 0;
698 data->shaped = (win_rgn != 0);
700 style = NtUserGetWindowLongW(data->hwnd, GWL_STYLE);
701 ex_style = NtUserGetWindowLongW(data->hwnd, GWL_EXSTYLE);
703 data->whole_rect = data->window_rect;
704 macdrv_window_to_mac_rect(data, style, &data->whole_rect, &data->window_rect, &data->client_rect);
706 get_cocoa_window_features(data, style, ex_style, &wf, &data->window_rect, &data->client_rect);
708 frame = cgrect_from_rect(data->whole_rect);
709 constrain_window_frame(&frame.origin, &frame.size);
710 if (frame.size.width < 1 || frame.size.height < 1)
711 frame.size.width = frame.size.height = 1;
713 TRACE("creating %p window %s whole %s client %s\n", data->hwnd, wine_dbgstr_rect(&data->window_rect),
714 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
716 data->cocoa_window = macdrv_create_cocoa_window(&wf, frame, data->hwnd, thread_data->queue);
717 if (!data->cocoa_window) goto done;
718 create_client_cocoa_view(data);
720 set_cocoa_window_properties(data);
722 /* set the window text */
723 if (!NtUserInternalGetWindowText(data->hwnd, text, ARRAY_SIZE(text))) text[0] = 0;
724 macdrv_set_cocoa_window_title(data->cocoa_window, text, wcslen(text));
726 /* set the window region */
727 if (win_rgn || IsRectEmpty(&data->window_rect)) sync_window_region(data, win_rgn);
729 /* set the window opacity */
730 if (!NtUserGetLayeredWindowAttributes(data->hwnd, &key, &alpha, &layered_flags)) layered_flags = 0;
731 sync_window_opacity(data, key, alpha, FALSE, layered_flags);
733 done:
734 if (win_rgn) NtGdiDeleteObjectApp(win_rgn);
738 /**********************************************************************
739 * destroy_cocoa_window
741 * Destroy the whole Mac window for a given window.
743 static void destroy_cocoa_window(struct macdrv_win_data *data)
745 if (!data->cocoa_window) return;
747 TRACE("win %p Cocoa win %p\n", data->hwnd, data->cocoa_window);
749 macdrv_destroy_cocoa_window(data->cocoa_window);
750 data->cocoa_window = 0;
751 data->on_screen = FALSE;
752 data->color_key = CLR_INVALID;
753 if (data->surface) window_surface_release(data->surface);
754 data->surface = NULL;
755 if (data->unminimized_surface) window_surface_release(data->unminimized_surface);
756 data->unminimized_surface = NULL;
760 /**********************************************************************
761 * create_cocoa_view
763 * Create the Cocoa view for a given Windows child window
765 static void create_cocoa_view(struct macdrv_win_data *data)
767 BOOL equal = EqualRect(&data->window_rect, &data->client_rect);
768 CGRect frame = cgrect_from_rect(data->window_rect);
770 data->shaped = FALSE;
771 data->whole_rect = data->window_rect;
773 TRACE("creating %p window %s whole %s client %s\n", data->hwnd, wine_dbgstr_rect(&data->window_rect),
774 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
776 if (!equal)
777 data->cocoa_view = macdrv_create_view(frame);
778 create_client_cocoa_view(data);
779 if (equal)
781 data->cocoa_view = data->client_cocoa_view;
782 macdrv_set_view_hidden(data->cocoa_view, TRUE);
783 macdrv_set_view_frame(data->cocoa_view, frame);
788 /**********************************************************************
789 * destroy_cocoa_view
791 * Destroy the Cocoa view for a given window.
793 static void destroy_cocoa_view(struct macdrv_win_data *data)
795 if (!data->cocoa_view) return;
797 TRACE("win %p Cocoa view %p\n", data->hwnd, data->cocoa_view);
799 if (data->cocoa_view != data->client_cocoa_view)
800 macdrv_dispose_view(data->cocoa_view);
801 data->cocoa_view = NULL;
802 data->on_screen = FALSE;
806 /***********************************************************************
807 * set_cocoa_view_parent
809 static void set_cocoa_view_parent(struct macdrv_win_data *data, HWND parent)
811 struct macdrv_win_data *parent_data = get_win_data(parent);
812 macdrv_window cocoa_window = parent_data ? parent_data->cocoa_window : NULL;
813 macdrv_view superview = parent_data ? parent_data->client_cocoa_view : NULL;
815 TRACE("win %p/%p parent %p/%p\n", data->hwnd, data->cocoa_view, parent, cocoa_window ? (void*)cocoa_window : (void*)superview);
817 if (!cocoa_window && !superview)
818 WARN("hwnd %p new parent %p has no Cocoa window or view in this process\n", data->hwnd, parent);
820 macdrv_set_view_superview(data->cocoa_view, superview, cocoa_window, NULL, NULL);
821 release_win_data(parent_data);
825 /***********************************************************************
826 * macdrv_create_win_data
828 * Create a Mac data window structure for an existing window.
830 static struct macdrv_win_data *macdrv_create_win_data(HWND hwnd, const RECT *window_rect,
831 const RECT *client_rect)
833 struct macdrv_win_data *data;
834 HWND parent;
836 if (NtUserGetWindowThread(hwnd, NULL) != GetCurrentThreadId()) return NULL;
838 if (!(parent = NtUserGetAncestor(hwnd, GA_PARENT))) /* desktop */
840 macdrv_init_thread_data();
841 return NULL;
844 /* don't create win data for HWND_MESSAGE windows */
845 if (parent != NtUserGetDesktopWindow() && !NtUserGetAncestor(parent, GA_PARENT)) return NULL;
847 if (!(data = alloc_win_data(hwnd))) return NULL;
849 data->whole_rect = data->window_rect = *window_rect;
850 data->client_rect = *client_rect;
852 if (parent == NtUserGetDesktopWindow())
854 create_cocoa_window(data);
855 TRACE("win %p/%p window %s whole %s client %s\n",
856 hwnd, data->cocoa_window, wine_dbgstr_rect(&data->window_rect),
857 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
859 else
861 create_cocoa_view(data);
862 TRACE("win %p/%p window %s whole %s client %s\n",
863 hwnd, data->cocoa_view, wine_dbgstr_rect(&data->window_rect),
864 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
866 set_cocoa_view_parent(data, parent);
869 return data;
873 /**********************************************************************
874 * is_owned_by
876 static BOOL is_owned_by(HWND hwnd, HWND maybe_owner)
878 while (1)
880 HWND hwnd2 = NtUserGetWindowRelative(hwnd, GW_OWNER);
881 if (!hwnd2)
882 hwnd2 = NtUserGetAncestor(hwnd, GA_ROOT);
883 if (!hwnd2 || hwnd2 == hwnd)
884 break;
885 if (hwnd2 == maybe_owner)
886 return TRUE;
887 hwnd = hwnd2;
890 return FALSE;
894 /**********************************************************************
895 * is_all_the_way_front
897 static BOOL is_all_the_way_front(HWND hwnd)
899 BOOL topmost = (NtUserGetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
900 HWND prev = hwnd;
902 while ((prev = NtUserGetWindowRelative(prev, GW_HWNDPREV)))
904 if (!topmost && (NtUserGetWindowLongW(prev, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0)
905 return TRUE;
906 if (!is_owned_by(prev, hwnd))
907 return FALSE;
910 return TRUE;
914 /***********************************************************************
915 * set_focus
917 static void set_focus(HWND hwnd, BOOL raise)
919 struct macdrv_win_data *data;
921 if (!(hwnd = NtUserGetAncestor(hwnd, GA_ROOT))) return;
923 if (raise && hwnd == NtUserGetForegroundWindow() && hwnd != NtUserGetDesktopWindow() &&
924 !is_all_the_way_front(hwnd))
925 NtUserSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
926 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
928 if (!(data = get_win_data(hwnd))) return;
930 if (data->cocoa_window && data->on_screen)
932 BOOL activate = activate_on_focus_time && (NtGetTickCount() - activate_on_focus_time < 2000);
933 /* Set Mac focus */
934 macdrv_give_cocoa_window_focus(data->cocoa_window, activate);
935 activate_on_focus_time = 0;
938 release_win_data(data);
941 /***********************************************************************
942 * show_window
944 static void show_window(struct macdrv_win_data *data)
946 if (data->cocoa_window)
948 HWND prev = NULL;
949 HWND next = NULL;
950 macdrv_window prev_window = NULL;
951 macdrv_window next_window = NULL;
952 BOOL activate = FALSE;
953 GUITHREADINFO info;
955 /* find window that this one must be after */
956 prev = NtUserGetWindowRelative(data->hwnd, GW_HWNDPREV);
957 while (prev && !((NtUserGetWindowLongW(prev, GWL_STYLE) & (WS_VISIBLE | WS_MINIMIZE)) == WS_VISIBLE &&
958 (prev_window = macdrv_get_cocoa_window(prev, TRUE))))
959 prev = NtUserGetWindowRelative(prev, GW_HWNDPREV);
960 if (!prev_window)
962 /* find window that this one must be before */
963 next = NtUserGetWindowRelative(data->hwnd, GW_HWNDNEXT);
964 while (next && !((NtUserGetWindowLongW(next, GWL_STYLE) & (WS_VISIBLE | WS_MINIMIZE)) == WS_VISIBLE &&
965 (next_window = macdrv_get_cocoa_window(next, TRUE))))
966 next = NtUserGetWindowRelative(next, GW_HWNDNEXT);
969 TRACE("win %p/%p below %p/%p above %p/%p\n",
970 data->hwnd, data->cocoa_window, prev, prev_window, next, next_window);
972 if (!prev_window)
973 activate = activate_on_focus_time && (NtGetTickCount() - activate_on_focus_time < 2000);
974 macdrv_order_cocoa_window(data->cocoa_window, prev_window, next_window, activate);
975 data->on_screen = TRUE;
977 info.cbSize = sizeof(info);
978 if (NtUserGetGUIThreadInfo(NtUserGetWindowThread(data->hwnd, NULL), &info) && info.hwndFocus &&
979 (data->hwnd == info.hwndFocus || NtUserIsChild(data->hwnd, info.hwndFocus)))
980 set_focus(info.hwndFocus, FALSE);
981 if (activate)
982 activate_on_focus_time = 0;
984 else
986 TRACE("win %p/%p showing view\n", data->hwnd, data->cocoa_view);
988 macdrv_set_view_hidden(data->cocoa_view, FALSE);
989 data->on_screen = TRUE;
994 /***********************************************************************
995 * hide_window
997 static void hide_window(struct macdrv_win_data *data)
999 TRACE("win %p/%p\n", data->hwnd, data->cocoa_window);
1001 if (data->cocoa_window)
1002 macdrv_hide_cocoa_window(data->cocoa_window);
1003 else
1004 macdrv_set_view_hidden(data->cocoa_view, TRUE);
1005 data->on_screen = FALSE;
1009 /***********************************************************************
1010 * sync_window_z_order
1012 static void sync_window_z_order(struct macdrv_win_data *data)
1014 if (data->cocoa_view)
1016 HWND parent = NtUserGetAncestor(data->hwnd, GA_PARENT);
1017 macdrv_view superview = macdrv_get_client_cocoa_view(parent);
1018 macdrv_window window = NULL;
1019 HWND prev;
1020 HWND next = NULL;
1021 macdrv_view prev_view = NULL;
1022 macdrv_view next_view = NULL;
1024 if (!superview)
1026 window = macdrv_get_cocoa_window(parent, FALSE);
1027 if (!window)
1028 WARN("hwnd %p/%p parent %p has no Cocoa window or view in this process\n", data->hwnd, data->cocoa_view, parent);
1031 /* find window that this one must be after */
1032 prev = NtUserGetWindowRelative(data->hwnd, GW_HWNDPREV);
1033 while (prev && !(prev_view = macdrv_get_cocoa_view(prev)))
1034 prev = NtUserGetWindowRelative(prev, GW_HWNDPREV);
1035 if (!prev_view)
1037 /* find window that this one must be before */
1038 next = NtUserGetWindowRelative(data->hwnd, GW_HWNDNEXT);
1039 while (next && !(next_view = macdrv_get_cocoa_view(next)))
1040 next = NtUserGetWindowRelative(next, GW_HWNDNEXT);
1043 TRACE("win %p/%p below %p/%p above %p/%p\n",
1044 data->hwnd, data->cocoa_view, prev, prev_view, next, next_view);
1046 macdrv_set_view_superview(data->cocoa_view, superview, window, prev_view, next_view);
1048 else if (data->on_screen)
1049 show_window(data);
1053 /***********************************************************************
1054 * get_region_data
1056 * Calls GetRegionData on the given region and converts the rectangle
1057 * array to CGRect format. The returned buffer must be freed by caller.
1058 * If hdc_lptodp is not 0, the rectangles are converted through LPtoDP.
1060 RGNDATA *get_region_data(HRGN hrgn, HDC hdc_lptodp)
1062 RGNDATA *data;
1063 DWORD size;
1064 int i;
1065 RECT *rect;
1066 CGRect *cgrect;
1068 if (!hrgn || !(size = NtGdiGetRegionData(hrgn, 0, NULL))) return NULL;
1069 if (sizeof(CGRect) > sizeof(RECT))
1071 /* add extra size for CGRect array */
1072 int count = (size - sizeof(RGNDATAHEADER)) / sizeof(RECT);
1073 size += count * (sizeof(CGRect) - sizeof(RECT));
1075 if (!(data = malloc(size))) return NULL;
1076 if (!NtGdiGetRegionData(hrgn, size, data))
1078 free(data);
1079 return NULL;
1082 rect = (RECT *)data->Buffer;
1083 cgrect = (CGRect *)data->Buffer;
1084 if (hdc_lptodp) /* map to device coordinates */
1086 NtGdiTransformPoints(hdc_lptodp, (POINT *)rect, (POINT *)rect,
1087 data->rdh.nCount * 2, NtGdiLPtoDP);
1088 for (i = 0; i < data->rdh.nCount; i++)
1090 if (rect[i].right < rect[i].left)
1092 INT tmp = rect[i].right;
1093 rect[i].right = rect[i].left;
1094 rect[i].left = tmp;
1096 if (rect[i].bottom < rect[i].top)
1098 INT tmp = rect[i].bottom;
1099 rect[i].bottom = rect[i].top;
1100 rect[i].top = tmp;
1105 if (sizeof(CGRect) > sizeof(RECT))
1107 /* need to start from the end */
1108 for (i = data->rdh.nCount-1; i >= 0; i--)
1109 cgrect[i] = cgrect_from_rect(rect[i]);
1111 else
1113 for (i = 0; i < data->rdh.nCount; i++)
1114 cgrect[i] = cgrect_from_rect(rect[i]);
1116 return data;
1120 /***********************************************************************
1121 * sync_client_view_position
1123 static void sync_client_view_position(struct macdrv_win_data *data)
1125 if (data->cocoa_view != data->client_cocoa_view)
1127 RECT rect = data->client_rect;
1128 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
1129 macdrv_set_view_frame(data->client_cocoa_view, cgrect_from_rect(rect));
1130 TRACE("win %p/%p client %s\n", data->hwnd, data->client_cocoa_view, wine_dbgstr_rect(&rect));
1135 /***********************************************************************
1136 * sync_window_position
1138 * Synchronize the Mac window position with the Windows one
1140 static void sync_window_position(struct macdrv_win_data *data, UINT swp_flags, const RECT *old_window_rect,
1141 const RECT *old_whole_rect)
1143 CGRect frame = cgrect_from_rect(data->whole_rect);
1144 BOOL force_z_order = FALSE;
1146 if (data->cocoa_window)
1148 if (data->minimized) return;
1150 constrain_window_frame(&frame.origin, &frame.size);
1151 if (frame.size.width < 1 || frame.size.height < 1)
1152 frame.size.width = frame.size.height = 1;
1154 macdrv_set_cocoa_window_frame(data->cocoa_window, &frame);
1156 else
1158 BOOL were_equal = (data->cocoa_view == data->client_cocoa_view);
1159 BOOL now_equal = EqualRect(&data->whole_rect, &data->client_rect);
1161 if (were_equal && !now_equal)
1163 data->cocoa_view = macdrv_create_view(frame);
1164 macdrv_set_view_hidden(data->cocoa_view, !data->on_screen);
1165 macdrv_set_view_superview(data->client_cocoa_view, data->cocoa_view, NULL, NULL, NULL);
1166 macdrv_set_view_hidden(data->client_cocoa_view, FALSE);
1167 force_z_order = TRUE;
1169 else if (!were_equal && now_equal)
1171 macdrv_dispose_view(data->cocoa_view);
1172 data->cocoa_view = data->client_cocoa_view;
1173 macdrv_set_view_hidden(data->cocoa_view, !data->on_screen);
1174 macdrv_set_view_frame(data->cocoa_view, frame);
1175 force_z_order = TRUE;
1177 else if (!EqualRect(&data->whole_rect, old_whole_rect))
1178 macdrv_set_view_frame(data->cocoa_view, frame);
1181 sync_client_view_position(data);
1183 if (old_window_rect && old_whole_rect &&
1184 (IsRectEmpty(old_window_rect) != IsRectEmpty(&data->window_rect) ||
1185 old_window_rect->left - old_whole_rect->left != data->window_rect.left - data->whole_rect.left ||
1186 old_window_rect->top - old_whole_rect->top != data->window_rect.top - data->whole_rect.top))
1187 sync_window_region(data, (HRGN)1);
1189 TRACE("win %p/%p whole_rect %s frame %s\n", data->hwnd,
1190 data->cocoa_window ? (void*)data->cocoa_window : (void*)data->cocoa_view,
1191 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_cgrect(frame));
1193 if (force_z_order || !(swp_flags & SWP_NOZORDER) || (swp_flags & SWP_SHOWWINDOW))
1194 sync_window_z_order(data);
1198 /***********************************************************************
1199 * move_window_bits
1201 * Move the window bits when a window is moved.
1203 static void move_window_bits(HWND hwnd, macdrv_window window, const RECT *old_rect, const RECT *new_rect,
1204 const RECT *old_client_rect, const RECT *new_client_rect,
1205 const RECT *new_window_rect)
1207 RECT src_rect = *old_rect;
1208 RECT dst_rect = *new_rect;
1209 HDC hdc_src, hdc_dst;
1210 HRGN rgn;
1211 HWND parent = 0;
1213 if (!window)
1215 OffsetRect(&dst_rect, -new_window_rect->left, -new_window_rect->top);
1216 parent = NtUserGetAncestor(hwnd, GA_PARENT);
1217 hdc_src = NtUserGetDCEx(parent, 0, DCX_CACHE);
1218 hdc_dst = NtUserGetDCEx(hwnd, 0, DCX_CACHE | DCX_WINDOW);
1220 else
1222 OffsetRect(&dst_rect, -new_client_rect->left, -new_client_rect->top);
1223 /* make src rect relative to the old position of the window */
1224 OffsetRect(&src_rect, -old_client_rect->left, -old_client_rect->top);
1225 if (dst_rect.left == src_rect.left && dst_rect.top == src_rect.top) return;
1226 hdc_src = hdc_dst = NtUserGetDCEx(hwnd, 0, DCX_CACHE);
1229 rgn = NtGdiCreateRectRgn(dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom);
1230 NtGdiExtSelectClipRgn(hdc_dst, rgn, RGN_COPY);
1231 NtGdiDeleteObjectApp(rgn);
1232 NtUserExcludeUpdateRgn(hdc_dst, hwnd);
1234 TRACE("copying bits for win %p/%p %s -> %s\n", hwnd, window,
1235 wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect));
1236 NtGdiBitBlt(hdc_dst, dst_rect.left, dst_rect.top,
1237 dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top,
1238 hdc_src, src_rect.left, src_rect.top, SRCCOPY, 0, 0);
1240 NtUserReleaseDC(hwnd, hdc_dst);
1241 if (hdc_src != hdc_dst) NtUserReleaseDC(parent, hdc_src);
1245 /**********************************************************************
1246 * activate_on_following_focus
1248 void activate_on_following_focus(void)
1250 activate_on_focus_time = NtGetTickCount();
1251 if (!activate_on_focus_time) activate_on_focus_time = 1;
1255 /***********************************************************************
1256 * set_app_icon
1258 static void set_app_icon(void)
1260 CFArrayRef images = create_app_icon_images();
1261 if (images)
1263 macdrv_set_application_icon(images);
1264 CFRelease(images);
1269 /**********************************************************************
1270 * set_capture_window_for_move
1272 static BOOL set_capture_window_for_move(HWND hwnd)
1274 HWND previous = 0;
1275 BOOL ret;
1277 SERVER_START_REQ(set_capture_window)
1279 req->handle = wine_server_user_handle(hwnd);
1280 req->flags = CAPTURE_MOVESIZE;
1281 if ((ret = !wine_server_call_err(req)))
1283 previous = wine_server_ptr_handle(reply->previous);
1284 hwnd = wine_server_ptr_handle(reply->full_handle);
1287 SERVER_END_REQ;
1289 if (ret)
1291 macdrv_SetCapture(hwnd, GUI_INMOVESIZE);
1293 if (previous && previous != hwnd)
1294 send_message(previous, WM_CAPTURECHANGED, 0, (LPARAM)hwnd);
1296 return ret;
1300 static HMONITOR monitor_from_point(POINT pt, UINT flags)
1302 RECT rect;
1304 SetRect(&rect, pt.x, pt.y, pt.x + 1, pt.y + 1);
1305 return NtUserMonitorFromRect(&rect, flags);
1309 /***********************************************************************
1310 * move_window
1312 * Based on user32's WINPOS_SysCommandSizeMove() specialized just for
1313 * moving top-level windows and enforcing Mac-style constraints like
1314 * keeping the top of the window within the work area.
1316 static LRESULT move_window(HWND hwnd, WPARAM wparam)
1318 MSG msg;
1319 RECT origRect, movedRect, desktopRect;
1320 int hittest = (int)(wparam & 0x0f);
1321 POINT capturePoint;
1322 LONG style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
1323 BOOL moved = FALSE;
1324 DWORD dwPoint = NtUserGetThreadInfo()->message_pos;
1325 INT captionHeight;
1326 HMONITOR mon = 0;
1327 MONITORINFO info;
1329 if ((style & (WS_MINIMIZE | WS_MAXIMIZE)) || !IsWindowVisible(hwnd)) return -1;
1330 if (hittest && hittest != HTCAPTION) return -1;
1332 capturePoint.x = (short)LOWORD(dwPoint);
1333 capturePoint.y = (short)HIWORD(dwPoint);
1334 NtUserClipCursor(NULL);
1336 TRACE("hwnd %p hittest %d, pos %d,%d\n", hwnd, hittest, (int)capturePoint.x, (int)capturePoint.y);
1338 origRect.left = origRect.right = origRect.top = origRect.bottom = 0;
1339 if (AdjustWindowRectEx(&origRect, style, FALSE, NtUserGetWindowLongW(hwnd, GWL_EXSTYLE)))
1340 captionHeight = -origRect.top;
1341 else
1342 captionHeight = 0;
1344 NtUserGetWindowRect(hwnd, &origRect);
1345 movedRect = origRect;
1347 if (!hittest)
1349 /* Move pointer to the center of the caption */
1350 RECT rect = origRect;
1352 /* Note: to be exactly centered we should take the different types
1353 * of border into account, but it shouldn't make more than a few pixels
1354 * of difference so let's not bother with that */
1355 rect.top += NtUserGetSystemMetrics(SM_CYBORDER);
1356 if (style & WS_SYSMENU)
1357 rect.left += NtUserGetSystemMetrics(SM_CXSIZE) + 1;
1358 if (style & WS_MINIMIZEBOX)
1359 rect.right -= NtUserGetSystemMetrics(SM_CXSIZE) + 1;
1360 if (style & WS_MAXIMIZEBOX)
1361 rect.right -= NtUserGetSystemMetrics(SM_CXSIZE) + 1;
1362 capturePoint.x = (rect.right + rect.left) / 2;
1363 capturePoint.y = rect.top + NtUserGetSystemMetrics(SM_CYSIZE)/2;
1365 NtUserSetCursorPos(capturePoint.x, capturePoint.y);
1366 send_message(hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELONG(HTCAPTION, WM_MOUSEMOVE));
1369 desktopRect = rect_from_cgrect(macdrv_get_desktop_rect());
1370 mon = monitor_from_point(capturePoint, MONITOR_DEFAULTTONEAREST);
1371 info.cbSize = sizeof(info);
1372 if (mon && !NtUserGetMonitorInfo(mon, &info))
1373 mon = 0;
1375 /* repaint the window before moving it around */
1376 NtUserRedrawWindow(hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
1378 send_message(hwnd, WM_ENTERSIZEMOVE, 0, 0);
1379 set_capture_window_for_move(hwnd);
1381 while(1)
1383 POINT pt;
1384 int dx = 0, dy = 0;
1385 HMONITOR newmon;
1387 if (!NtUserGetMessage(&msg, 0, 0, 0)) break;
1388 if (NtUserCallMsgFilter(&msg, MSGF_SIZE)) continue;
1390 /* Exit on button-up, Return, or Esc */
1391 if (msg.message == WM_LBUTTONUP ||
1392 (msg.message == WM_KEYDOWN && (msg.wParam == VK_RETURN || msg.wParam == VK_ESCAPE)))
1393 break;
1395 if (msg.message != WM_KEYDOWN && msg.message != WM_MOUSEMOVE)
1397 NtUserTranslateMessage(&msg, 0);
1398 NtUserDispatchMessage(&msg);
1399 continue; /* We are not interested in other messages */
1402 pt = msg.pt;
1404 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
1406 case VK_UP: pt.y -= 8; break;
1407 case VK_DOWN: pt.y += 8; break;
1408 case VK_LEFT: pt.x -= 8; break;
1409 case VK_RIGHT: pt.x += 8; break;
1412 pt.x = max(pt.x, desktopRect.left);
1413 pt.x = min(pt.x, desktopRect.right - 1);
1414 pt.y = max(pt.y, desktopRect.top);
1415 pt.y = min(pt.y, desktopRect.bottom - 1);
1417 if ((newmon = monitor_from_point(pt, MONITOR_DEFAULTTONULL)) && newmon != mon)
1419 if (NtUserGetMonitorInfo(newmon, &info))
1420 mon = newmon;
1421 else
1422 mon = 0;
1425 if (mon)
1427 /* wineserver clips the cursor position to the virtual desktop rect but,
1428 if the display configuration is non-rectangular, that could still
1429 leave the logical cursor position outside of any display. The window
1430 could keep moving as you push the cursor against a display edge, even
1431 though the visible cursor doesn't keep moving. The following keeps
1432 the window movement in sync with the visible cursor. */
1433 pt.x = max(pt.x, info.rcMonitor.left);
1434 pt.x = min(pt.x, info.rcMonitor.right - 1);
1435 pt.y = max(pt.y, info.rcMonitor.top);
1436 pt.y = min(pt.y, info.rcMonitor.bottom - 1);
1438 /* Assuming that dx will be calculated below as pt.x - capturePoint.x,
1439 dy will be pt.y - capturePoint.y, and movedRect will be offset by those,
1440 we want to enforce these constraints:
1441 movedRect.left + dx < info.rcWork.right
1442 movedRect.right + dx > info.rcWork.left
1443 movedRect.top + captionHeight + dy < info.rcWork.bottom
1444 movedRect.bottom + dy > info.rcWork.top
1445 movedRect.top + dy >= info.rcWork.top
1446 The first four keep at least one edge barely in the work area.
1447 The last keeps the top (i.e. the title bar) in the work area.
1448 The fourth is redundant with the last, so can be ignored.
1450 Substituting for dx and dy and rearranging gives us...
1452 pt.x = min(pt.x, info.rcWork.right - 1 + capturePoint.x - movedRect.left);
1453 pt.x = max(pt.x, info.rcWork.left + 1 + capturePoint.x - movedRect.right);
1454 pt.y = min(pt.y, info.rcWork.bottom - 1 + capturePoint.y - movedRect.top - captionHeight);
1455 pt.y = max(pt.y, info.rcWork.top + capturePoint.y - movedRect.top);
1458 dx = pt.x - capturePoint.x;
1459 dy = pt.y - capturePoint.y;
1461 if (dx || dy)
1463 moved = TRUE;
1465 if (msg.message == WM_KEYDOWN) NtUserSetCursorPos(pt.x, pt.y);
1466 else
1468 OffsetRect(&movedRect, dx, dy);
1469 capturePoint = pt;
1471 send_message(hwnd, WM_MOVING, 0, (LPARAM)&movedRect);
1472 NtUserSetWindowPos(hwnd, 0, movedRect.left, movedRect.top, 0, 0,
1473 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
1478 set_capture_window_for_move(0);
1480 send_message(hwnd, WM_EXITSIZEMOVE, 0, 0);
1481 send_message(hwnd, WM_SETVISIBLE, TRUE, 0L);
1483 /* if the move is canceled, restore the previous position */
1484 if (moved && msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)
1486 NtUserSetWindowPos(hwnd, 0, origRect.left, origRect.top, 0, 0,
1487 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
1490 return 0;
1494 /***********************************************************************
1495 * perform_window_command
1497 static void perform_window_command(HWND hwnd, unsigned int style_any, unsigned int style_none, WORD command, WORD hittest)
1499 unsigned int style;
1501 TRACE("win %p style_any 0x%08x style_none 0x%08x command 0x%04x hittest 0x%04x\n",
1502 hwnd, style_any, style_none, command, hittest);
1504 style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
1505 if ((style_any && !(style & style_any)) || (style & (WS_DISABLED | style_none)))
1507 TRACE("not changing win %p style 0x%08x\n", hwnd, style);
1508 return;
1511 if (get_active_window() != hwnd)
1513 LRESULT ma = send_message(hwnd, WM_MOUSEACTIVATE, (WPARAM)NtUserGetAncestor(hwnd, GA_ROOT),
1514 MAKELPARAM(hittest, WM_NCLBUTTONDOWN));
1515 switch (ma)
1517 case MA_NOACTIVATEANDEAT:
1518 case MA_ACTIVATEANDEAT:
1519 TRACE("not changing win %p mouse-activate result %ld\n", hwnd, ma);
1520 return;
1521 case MA_NOACTIVATE:
1522 break;
1523 case MA_ACTIVATE:
1524 case 0:
1525 NtUserSetActiveWindow(hwnd);
1526 break;
1527 default:
1528 WARN("unknown WM_MOUSEACTIVATE code %ld\n", ma);
1529 break;
1533 TRACE("changing win %p\n", hwnd);
1534 NtUserPostMessage(hwnd, WM_SYSCOMMAND, command, 0);
1538 /**********************************************************************
1539 * SetDesktopWindow (MACDRV.@)
1541 void macdrv_SetDesktopWindow(HWND hwnd)
1543 unsigned int width, height;
1545 TRACE("%p\n", hwnd);
1547 /* retrieve the real size of the desktop */
1548 SERVER_START_REQ(get_window_rectangles)
1550 req->handle = wine_server_user_handle(hwnd);
1551 req->relative = COORDS_CLIENT;
1552 wine_server_call(req);
1553 width = reply->window.right;
1554 height = reply->window.bottom;
1556 SERVER_END_REQ;
1558 if (!width && !height) /* not initialized yet */
1560 CGRect rect = macdrv_get_desktop_rect();
1562 SERVER_START_REQ(set_window_pos)
1564 req->handle = wine_server_user_handle(hwnd);
1565 req->previous = 0;
1566 req->swp_flags = SWP_NOZORDER;
1567 req->window.left = CGRectGetMinX(rect);
1568 req->window.top = CGRectGetMinY(rect);
1569 req->window.right = CGRectGetMaxX(rect);
1570 req->window.bottom = CGRectGetMaxY(rect);
1571 req->client = req->window;
1572 wine_server_call(req);
1574 SERVER_END_REQ;
1577 set_app_icon();
1580 void macdrv_resize_desktop(void)
1582 HWND hwnd = NtUserGetDesktopWindow();
1583 CGRect new_desktop_rect;
1584 RECT current_desktop_rect;
1586 macdrv_reset_device_metrics();
1587 new_desktop_rect = macdrv_get_desktop_rect();
1588 if (!NtUserGetWindowRect(hwnd, &current_desktop_rect) ||
1589 !CGRectEqualToRect(cgrect_from_rect(current_desktop_rect), new_desktop_rect))
1591 send_message_timeout(HWND_BROADCAST, WM_MACDRV_RESET_DEVICE_METRICS, 0, 0,
1592 SMTO_ABORTIFHUNG, 2000, NULL);
1593 NtUserSetWindowPos(hwnd, 0, CGRectGetMinX(new_desktop_rect), CGRectGetMinY(new_desktop_rect),
1594 CGRectGetWidth(new_desktop_rect), CGRectGetHeight(new_desktop_rect),
1595 SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE);
1596 send_message_timeout(HWND_BROADCAST, WM_MACDRV_DISPLAYCHANGE, 0, 0,
1597 SMTO_ABORTIFHUNG, 2000, NULL);
1601 #define WM_WINE_NOTIFY_ACTIVITY WM_USER
1603 LRESULT macdrv_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1605 switch (msg)
1607 case WM_WINE_NOTIFY_ACTIVITY:
1609 /* This wakes from display sleep, but doesn't affect the screen saver. */
1610 static IOPMAssertionID assertion;
1611 IOPMAssertionDeclareUserActivity(CFSTR("Wine user input"), kIOPMUserActiveLocal, &assertion);
1613 /* This prevents the screen saver, but doesn't wake from display sleep. */
1614 /* It's deprecated, but there's no better alternative. */
1615 #pragma clang diagnostic push
1616 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1617 UpdateSystemActivity(UsrActivity);
1618 #pragma clang diagnostic pop
1619 break;
1621 case WM_DISPLAYCHANGE:
1622 macdrv_resize_desktop();
1623 break;
1625 return NtUserMessageCall(hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE);
1628 /***********************************************************************
1629 * DestroyWindow (MACDRV.@)
1631 void macdrv_DestroyWindow(HWND hwnd)
1633 struct macdrv_win_data *data;
1635 TRACE("%p\n", hwnd);
1637 if (!(data = get_win_data(hwnd))) return;
1639 if (hwnd == get_capture()) macdrv_SetCapture(0, 0);
1640 if (data->drag_event) NtSetEvent(data->drag_event, NULL);
1642 destroy_cocoa_window(data);
1643 destroy_cocoa_view(data);
1644 if (data->client_cocoa_view) macdrv_dispose_view(data->client_cocoa_view);
1646 CFDictionaryRemoveValue(win_datas, hwnd);
1647 release_win_data(data);
1648 free(data);
1652 /*****************************************************************
1653 * SetFocus (MACDRV.@)
1655 * Set the Mac focus.
1657 void macdrv_SetFocus(HWND hwnd)
1659 struct macdrv_thread_data *thread_data = macdrv_thread_data();
1661 TRACE("%p\n", hwnd);
1663 if (!thread_data) return;
1664 thread_data->dead_key_state = 0;
1665 set_focus(hwnd, TRUE);
1669 /***********************************************************************
1670 * SetLayeredWindowAttributes (MACDRV.@)
1672 * Set transparency attributes for a layered window.
1674 void macdrv_SetLayeredWindowAttributes(HWND hwnd, COLORREF key, BYTE alpha, DWORD flags)
1676 struct macdrv_win_data *data = get_win_data(hwnd);
1678 TRACE("hwnd %p key %#08x alpha %#02x flags %x\n", hwnd, (unsigned int)key, alpha, (unsigned int)flags);
1680 if (data)
1682 data->layered = TRUE;
1683 data->ulw_layered = FALSE;
1684 if (data->surface) set_surface_use_alpha(data->surface, FALSE);
1685 if (data->cocoa_window)
1687 sync_window_opacity(data, key, alpha, FALSE, flags);
1688 /* since layered attributes are now set, can now show the window */
1689 if ((NtUserGetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE) && !data->on_screen)
1690 show_window(data);
1692 release_win_data(data);
1694 else
1695 FIXME("setting layered attributes on window %p of other process not supported\n", hwnd);
1699 /*****************************************************************
1700 * SetParent (MACDRV.@)
1702 void macdrv_SetParent(HWND hwnd, HWND parent, HWND old_parent)
1704 struct macdrv_win_data *data;
1706 TRACE("%p, %p, %p\n", hwnd, parent, old_parent);
1708 if (parent == old_parent) return;
1709 if (!(data = get_win_data(hwnd))) return;
1711 if (parent != NtUserGetDesktopWindow()) /* a child window */
1713 if (old_parent == NtUserGetDesktopWindow())
1715 /* destroy the old Mac window */
1716 destroy_cocoa_window(data);
1717 create_cocoa_view(data);
1720 set_cocoa_view_parent(data, parent);
1722 else /* new top level window */
1724 destroy_cocoa_view(data);
1725 create_cocoa_window(data);
1727 release_win_data(data);
1731 /***********************************************************************
1732 * SetWindowRgn (MACDRV.@)
1734 * Assign specified region to window (for non-rectangular windows)
1736 void macdrv_SetWindowRgn(HWND hwnd, HRGN hrgn, BOOL redraw)
1738 struct macdrv_win_data *data;
1740 TRACE("%p, %p, %d\n", hwnd, hrgn, redraw);
1742 if ((data = get_win_data(hwnd)))
1744 sync_window_region(data, hrgn);
1745 release_win_data(data);
1747 else
1749 DWORD procid;
1751 NtUserGetWindowThread(hwnd, &procid);
1752 if (procid != GetCurrentProcessId())
1753 send_message(hwnd, WM_MACDRV_SET_WIN_REGION, 0, 0);
1758 /***********************************************************************
1759 * SetWindowStyle (MACDRV.@)
1761 * Update the state of the Cocoa window to reflect a style change
1763 void macdrv_SetWindowStyle(HWND hwnd, INT offset, STYLESTRUCT *style)
1765 struct macdrv_win_data *data;
1767 TRACE("hwnd %p offset %d styleOld 0x%08x styleNew 0x%08x\n", hwnd, offset, (unsigned int)style->styleOld, (unsigned int)style->styleNew);
1769 if (hwnd == NtUserGetDesktopWindow()) return;
1770 if (!(data = get_win_data(hwnd))) return;
1772 if (data->cocoa_window)
1774 DWORD changed = style->styleNew ^ style->styleOld;
1776 set_cocoa_window_properties(data);
1778 if (offset == GWL_EXSTYLE && (changed & WS_EX_LAYERED)) /* changing WS_EX_LAYERED resets attributes */
1780 data->layered = FALSE;
1781 data->ulw_layered = FALSE;
1782 sync_window_opacity(data, 0, 0, FALSE, 0);
1783 if (data->surface) set_surface_use_alpha(data->surface, FALSE);
1786 if (offset == GWL_EXSTYLE && (changed & WS_EX_LAYOUTRTL))
1787 sync_window_region(data, (HRGN)1);
1790 release_win_data(data);
1794 /*****************************************************************
1795 * SetWindowText (MACDRV.@)
1797 void macdrv_SetWindowText(HWND hwnd, LPCWSTR text)
1799 macdrv_window win;
1801 TRACE("%p, %s\n", hwnd, debugstr_w(text));
1803 if ((win = macdrv_get_cocoa_window(hwnd, FALSE)))
1804 macdrv_set_cocoa_window_title(win, text, wcslen(text));
1808 /***********************************************************************
1809 * ShowWindow (MACDRV.@)
1811 UINT macdrv_ShowWindow(HWND hwnd, INT cmd, RECT *rect, UINT swp)
1813 struct macdrv_thread_data *thread_data = macdrv_thread_data();
1814 struct macdrv_win_data *data = get_win_data(hwnd);
1815 CGRect frame;
1817 TRACE("win %p/%p cmd %d at %s flags %08x\n",
1818 hwnd, data ? data->cocoa_window : NULL, cmd, wine_dbgstr_rect(rect), swp);
1820 if (!data || !data->cocoa_window) goto done;
1821 if (NtUserGetWindowLongW(hwnd, GWL_STYLE) & WS_MINIMIZE)
1823 if (rect->left != -32000 || rect->top != -32000)
1825 OffsetRect(rect, -32000 - rect->left, -32000 - rect->top);
1826 swp &= ~(SWP_NOMOVE | SWP_NOCLIENTMOVE);
1828 goto done;
1830 if (!data->on_screen) goto done;
1832 /* only fetch the new rectangle if the ShowWindow was a result of an external event */
1834 if (!thread_data->current_event || thread_data->current_event->window != data->cocoa_window)
1835 goto done;
1837 if (thread_data->current_event->type != WINDOW_FRAME_CHANGED &&
1838 thread_data->current_event->type != WINDOW_DID_UNMINIMIZE)
1839 goto done;
1841 macdrv_get_cocoa_window_frame(data->cocoa_window, &frame);
1842 *rect = rect_from_cgrect(frame);
1843 macdrv_mac_to_window_rect(data, rect);
1844 TRACE("rect %s -> %s\n", wine_dbgstr_cgrect(frame), wine_dbgstr_rect(rect));
1845 swp &= ~(SWP_NOMOVE | SWP_NOCLIENTMOVE | SWP_NOSIZE | SWP_NOCLIENTSIZE);
1847 done:
1848 release_win_data(data);
1849 return swp;
1853 /***********************************************************************
1854 * SysCommand (MACDRV.@)
1856 * Perform WM_SYSCOMMAND handling.
1858 LRESULT macdrv_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam)
1860 struct macdrv_win_data *data;
1861 LRESULT ret = -1;
1862 WPARAM command = wparam & 0xfff0;
1864 TRACE("%p, %x, %lx\n", hwnd, (unsigned)wparam, lparam);
1866 if (!(data = get_win_data(hwnd))) goto done;
1867 if (!data->cocoa_window || !data->on_screen) goto done;
1869 /* prevent a simple ALT press+release from activating the system menu,
1870 as that can get confusing */
1871 if (command == SC_KEYMENU && !(WCHAR)lparam &&
1872 !NtUserGetWindowLongPtrW(hwnd, GWLP_ID) &&
1873 (NtUserGetWindowLongW(hwnd, GWL_STYLE) & WS_SYSMENU))
1875 TRACE("ignoring SC_KEYMENU wp %lx lp %lx\n", (unsigned long)wparam, lparam);
1876 ret = 0;
1879 if (command == SC_MOVE)
1881 release_win_data(data);
1882 return move_window(hwnd, wparam);
1885 done:
1886 release_win_data(data);
1887 return ret;
1891 /***********************************************************************
1892 * UpdateLayeredWindow (MACDRV.@)
1894 BOOL macdrv_UpdateLayeredWindow(HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
1895 const RECT *window_rect)
1897 struct window_surface *surface;
1898 struct macdrv_win_data *data;
1899 BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
1900 BYTE alpha;
1901 char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
1902 BITMAPINFO *bmi = (BITMAPINFO *)buffer;
1903 void *src_bits, *dst_bits;
1904 RECT rect, src_rect;
1905 HDC hdc = 0;
1906 HBITMAP dib;
1907 BOOL ret = FALSE;
1909 if (!(data = get_win_data(hwnd))) return FALSE;
1911 data->layered = TRUE;
1912 data->ulw_layered = TRUE;
1914 rect = *window_rect;
1915 OffsetRect(&rect, -window_rect->left, -window_rect->top);
1917 surface = data->surface;
1918 if (!surface || !EqualRect(&surface->rect, &rect))
1920 data->surface = create_surface(data->cocoa_window, &rect, NULL, TRUE);
1921 set_window_surface(data->cocoa_window, data->surface);
1922 if (surface) window_surface_release(surface);
1923 surface = data->surface;
1924 if (data->unminimized_surface)
1926 window_surface_release(data->unminimized_surface);
1927 data->unminimized_surface = NULL;
1930 else set_surface_use_alpha(surface, TRUE);
1932 if (surface) window_surface_add_ref(surface);
1933 release_win_data(data);
1935 if (!surface) return FALSE;
1936 if (!info->hdcSrc)
1938 window_surface_release(surface);
1939 return TRUE;
1942 if (info->dwFlags & ULW_ALPHA)
1944 /* Apply SourceConstantAlpha via window alpha, not blend. */
1945 alpha = info->pblend->SourceConstantAlpha;
1946 blend = *info->pblend;
1947 blend.SourceConstantAlpha = 0xff;
1949 else
1950 alpha = 0xff;
1952 dst_bits = surface->funcs->get_info(surface, bmi);
1954 if (!(dib = NtGdiCreateDIBSection(info->hdcDst, NULL, 0, bmi, DIB_RGB_COLORS,
1955 0, 0, 0, &src_bits))) goto done;
1956 if (!(hdc = NtGdiCreateCompatibleDC(0))) goto done;
1958 NtGdiSelectBitmap(hdc, dib);
1959 if (info->prcDirty)
1961 intersect_rect(&rect, &rect, info->prcDirty);
1962 surface->funcs->lock(surface);
1963 memcpy(src_bits, dst_bits, bmi->bmiHeader.biSizeImage);
1964 surface->funcs->unlock(surface);
1965 NtGdiPatBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, BLACKNESS);
1967 src_rect = rect;
1968 if (info->pptSrc) OffsetRect( &src_rect, info->pptSrc->x, info->pptSrc->y );
1969 NtGdiTransformPoints(info->hdcSrc, (POINT *)&src_rect, (POINT *)&src_rect, 2, NtGdiDPtoLP);
1971 if (!(ret = NtGdiAlphaBlend(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
1972 info->hdcSrc, src_rect.left, src_rect.top,
1973 src_rect.right - src_rect.left, src_rect.bottom - src_rect.top,
1974 *(DWORD *)&blend, 0)))
1975 goto done;
1977 if ((data = get_win_data(hwnd)))
1979 if (surface == data->surface)
1981 surface->funcs->lock(surface);
1982 memcpy(dst_bits, src_bits, bmi->bmiHeader.biSizeImage);
1983 add_bounds_rect(surface->funcs->get_bounds(surface), &rect);
1984 surface->funcs->unlock(surface);
1985 surface->funcs->flush(surface);
1988 /* The ULW flags are a superset of the LWA flags. */
1989 sync_window_opacity(data, info->crKey, alpha, TRUE, info->dwFlags);
1991 release_win_data(data);
1994 done:
1995 window_surface_release(surface);
1996 if (hdc) NtGdiDeleteObjectApp(hdc);
1997 if (dib) NtGdiDeleteObjectApp(dib);
1998 return ret;
2002 /**********************************************************************
2003 * WindowMessage (MACDRV.@)
2005 LRESULT macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
2007 struct macdrv_win_data *data;
2009 TRACE("%p, %u, %u, %lu\n", hwnd, msg, (unsigned)wp, lp);
2011 switch(msg)
2013 case WM_MACDRV_SET_WIN_REGION:
2014 if ((data = get_win_data(hwnd)))
2016 sync_window_region(data, (HRGN)1);
2017 release_win_data(data);
2019 return 0;
2020 case WM_MACDRV_RESET_DEVICE_METRICS:
2021 macdrv_reset_device_metrics();
2022 return 0;
2023 case WM_MACDRV_DISPLAYCHANGE:
2024 macdrv_reassert_window_position(hwnd);
2025 return 0;
2026 case WM_MACDRV_ACTIVATE_ON_FOLLOWING_FOCUS:
2027 activate_on_following_focus();
2028 TRACE("WM_MACDRV_ACTIVATE_ON_FOLLOWING_FOCUS time %u\n", activate_on_focus_time);
2029 return 0;
2032 FIXME("unrecognized window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, (unsigned long)wp, lp);
2033 return 0;
2037 static inline RECT get_surface_rect(const RECT *visible_rect)
2039 RECT rect = *visible_rect;
2041 OffsetRect(&rect, -visible_rect->left, -visible_rect->top);
2042 rect.left &= ~127;
2043 rect.top &= ~127;
2044 rect.right = max(rect.left + 128, (rect.right + 127) & ~127);
2045 rect.bottom = max(rect.top + 128, (rect.bottom + 127) & ~127);
2046 return rect;
2050 /***********************************************************************
2051 * WindowPosChanging (MACDRV.@)
2053 BOOL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags,
2054 const RECT *window_rect, const RECT *client_rect,
2055 RECT *visible_rect, struct window_surface **surface)
2057 struct macdrv_win_data *data = get_win_data(hwnd);
2058 DWORD style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
2059 RECT surface_rect;
2061 TRACE("%p after %p swp %04x window %s client %s visible %s surface %p\n", hwnd, insert_after,
2062 swp_flags, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
2063 wine_dbgstr_rect(visible_rect), surface);
2065 if (!data && !(data = macdrv_create_win_data(hwnd, window_rect, client_rect))) return TRUE;
2067 *visible_rect = *window_rect;
2068 macdrv_window_to_mac_rect(data, style, visible_rect, window_rect, client_rect);
2069 TRACE("visible_rect %s -> %s\n", wine_dbgstr_rect(window_rect),
2070 wine_dbgstr_rect(visible_rect));
2072 /* create the window surface if necessary */
2073 if (!data->cocoa_window) goto done;
2074 if (swp_flags & SWP_HIDEWINDOW) goto done;
2075 if (data->ulw_layered) goto done;
2077 if (*surface) window_surface_release(*surface);
2078 *surface = NULL;
2080 surface_rect = get_surface_rect(visible_rect);
2081 if (data->surface)
2083 if (EqualRect(&data->surface->rect, &surface_rect))
2085 /* existing surface is good enough */
2086 surface_clip_to_visible_rect(data->surface, visible_rect);
2087 window_surface_add_ref(data->surface);
2088 *surface = data->surface;
2089 goto done;
2092 else if (!(swp_flags & SWP_SHOWWINDOW) && !(style & WS_VISIBLE)) goto done;
2094 *surface = create_surface(data->cocoa_window, &surface_rect, data->surface, FALSE);
2096 done:
2097 release_win_data(data);
2098 return TRUE;
2102 /***********************************************************************
2103 * WindowPosChanged (MACDRV.@)
2105 void macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
2106 const RECT *window_rect, const RECT *client_rect,
2107 const RECT *visible_rect, const RECT *valid_rects,
2108 struct window_surface *surface)
2110 struct macdrv_thread_data *thread_data;
2111 struct macdrv_win_data *data;
2112 unsigned int new_style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
2113 RECT old_window_rect, old_whole_rect, old_client_rect;
2115 if (!(data = get_win_data(hwnd))) return;
2117 thread_data = macdrv_thread_data();
2119 old_window_rect = data->window_rect;
2120 old_whole_rect = data->whole_rect;
2121 old_client_rect = data->client_rect;
2122 data->window_rect = *window_rect;
2123 data->whole_rect = *visible_rect;
2124 data->client_rect = *client_rect;
2125 if (data->cocoa_window && !data->ulw_layered)
2127 if (surface) window_surface_add_ref(surface);
2128 if (new_style & WS_MINIMIZE)
2130 if (!data->unminimized_surface && data->surface)
2132 data->unminimized_surface = data->surface;
2133 window_surface_add_ref(data->unminimized_surface);
2136 else
2138 set_window_surface(data->cocoa_window, surface);
2139 if (data->unminimized_surface)
2141 window_surface_release(data->unminimized_surface);
2142 data->unminimized_surface = NULL;
2145 if (data->surface) window_surface_release(data->surface);
2146 data->surface = surface;
2149 TRACE("win %p/%p window %s whole %s client %s style %08x flags %08x surface %p\n",
2150 hwnd, data->cocoa_window, wine_dbgstr_rect(window_rect),
2151 wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(client_rect),
2152 new_style, swp_flags, surface);
2154 if (!IsRectEmpty(&valid_rects[0]))
2156 macdrv_window window = data->cocoa_window;
2157 int x_offset = old_whole_rect.left - data->whole_rect.left;
2158 int y_offset = old_whole_rect.top - data->whole_rect.top;
2160 /* if all that happened is that the whole window moved, copy everything */
2161 if (!(swp_flags & SWP_FRAMECHANGED) &&
2162 old_whole_rect.right - data->whole_rect.right == x_offset &&
2163 old_whole_rect.bottom - data->whole_rect.bottom == y_offset &&
2164 old_client_rect.left - data->client_rect.left == x_offset &&
2165 old_client_rect.right - data->client_rect.right == x_offset &&
2166 old_client_rect.top - data->client_rect.top == y_offset &&
2167 old_client_rect.bottom - data->client_rect.bottom == y_offset &&
2168 EqualRect(&valid_rects[0], &data->client_rect))
2170 /* A Cocoa window's bits are moved automatically */
2171 if (!window && (x_offset != 0 || y_offset != 0))
2173 release_win_data(data);
2174 move_window_bits(hwnd, window, &old_whole_rect, visible_rect,
2175 &old_client_rect, client_rect, window_rect);
2176 if (!(data = get_win_data(hwnd))) return;
2179 else
2181 release_win_data(data);
2182 move_window_bits(hwnd, window, &valid_rects[1], &valid_rects[0],
2183 &old_client_rect, client_rect, window_rect);
2184 if (!(data = get_win_data(hwnd))) return;
2188 sync_gl_view(data, &old_whole_rect, &old_client_rect);
2190 if (!data->cocoa_window && !data->cocoa_view) goto done;
2192 if (data->on_screen)
2194 if ((swp_flags & SWP_HIDEWINDOW) && !(new_style & WS_VISIBLE))
2195 hide_window(data);
2198 /* check if we are currently processing an event relevant to this window */
2199 if (thread_data && thread_data->current_event &&
2200 data->cocoa_window && thread_data->current_event->window == data->cocoa_window &&
2201 (thread_data->current_event->type == WINDOW_FRAME_CHANGED ||
2202 thread_data->current_event->type == WINDOW_DID_UNMINIMIZE))
2204 if (thread_data->current_event->type == WINDOW_FRAME_CHANGED)
2205 sync_client_view_position(data);
2207 else
2209 sync_window_position(data, swp_flags, &old_window_rect, &old_whole_rect);
2210 if (data->cocoa_window)
2211 set_cocoa_window_properties(data);
2214 if (new_style & WS_VISIBLE)
2216 if (data->cocoa_window)
2218 if (!data->on_screen || (swp_flags & (SWP_FRAMECHANGED|SWP_STATECHANGED)))
2219 set_cocoa_window_properties(data);
2221 /* layered windows are not shown until their attributes are set */
2222 if (!data->on_screen &&
2223 (data->layered || !(NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED)))
2224 show_window(data);
2226 else if (!data->on_screen)
2227 show_window(data);
2230 done:
2231 release_win_data(data);
2235 /***********************************************************************
2236 * macdrv_window_close_requested
2238 * Handler for WINDOW_CLOSE_REQUESTED events.
2240 void macdrv_window_close_requested(HWND hwnd)
2242 HMENU sysmenu;
2244 if (NtUserGetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
2246 TRACE("not closing win %p class style CS_NOCLOSE\n", hwnd);
2247 return;
2250 sysmenu = NtUserGetSystemMenu(hwnd, FALSE);
2251 if (sysmenu)
2253 UINT state = NtUserThunkedMenuItemInfo(sysmenu, SC_CLOSE, MF_BYCOMMAND,
2254 NtUserGetMenuState, NULL, NULL);
2255 if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED)))
2257 TRACE("not closing win %p menu state 0x%08x\n", hwnd, state);
2258 return;
2262 perform_window_command(hwnd, 0, 0, SC_CLOSE, HTCLOSE);
2266 /***********************************************************************
2267 * macdrv_window_frame_changed
2269 * Handler for WINDOW_FRAME_CHANGED events.
2271 void macdrv_window_frame_changed(HWND hwnd, const macdrv_event *event)
2273 struct macdrv_win_data *data;
2274 RECT rect;
2275 HWND parent;
2276 UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
2277 int width, height;
2278 BOOL being_dragged;
2280 if (!hwnd) return;
2281 if (!(data = get_win_data(hwnd))) return;
2282 if (!data->on_screen || data->minimized)
2284 release_win_data(data);
2285 return;
2288 /* Get geometry */
2290 parent = NtUserGetAncestor(hwnd, GA_PARENT);
2292 TRACE("win %p/%p new Cocoa frame %s fullscreen %d in_resize %d\n", hwnd, data->cocoa_window,
2293 wine_dbgstr_cgrect(event->window_frame_changed.frame),
2294 event->window_frame_changed.fullscreen, event->window_frame_changed.in_resize);
2296 rect = rect_from_cgrect(event->window_frame_changed.frame);
2297 macdrv_mac_to_window_rect(data, &rect);
2298 NtUserMapWindowPoints(0, parent, (POINT *)&rect, 2);
2300 width = rect.right - rect.left;
2301 height = rect.bottom - rect.top;
2303 if (data->window_rect.left == rect.left && data->window_rect.top == rect.top)
2304 flags |= SWP_NOMOVE;
2305 else
2306 TRACE("%p moving from (%d,%d) to (%d,%d)\n", hwnd, (int)data->window_rect.left,
2307 (int)data->window_rect.top, (int)rect.left, (int)rect.top);
2309 if ((data->window_rect.right - data->window_rect.left == width &&
2310 data->window_rect.bottom - data->window_rect.top == height) ||
2311 (IsRectEmpty(&data->window_rect) && width == 1 && height == 1))
2312 flags |= SWP_NOSIZE;
2313 else
2314 TRACE("%p resizing from (%dx%d) to (%dx%d)\n", hwnd, (int)(data->window_rect.right - data->window_rect.left),
2315 (int)(data->window_rect.bottom - data->window_rect.top), width, height);
2317 being_dragged = data->drag_event != NULL;
2318 release_win_data(data);
2320 if (event->window_frame_changed.fullscreen)
2321 flags |= SWP_NOSENDCHANGING;
2322 if (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE))
2324 int send_sizemove = !event->window_frame_changed.in_resize && !being_dragged && !event->window_frame_changed.skip_size_move_loop;
2325 if (send_sizemove)
2326 send_message(hwnd, WM_ENTERSIZEMOVE, 0, 0);
2327 NtUserSetWindowPos(hwnd, 0, rect.left, rect.top, width, height, flags);
2328 if (send_sizemove)
2329 send_message(hwnd, WM_EXITSIZEMOVE, 0, 0);
2334 /***********************************************************************
2335 * macdrv_window_got_focus
2337 * Handler for WINDOW_GOT_FOCUS events.
2339 void macdrv_window_got_focus(HWND hwnd, const macdrv_event *event)
2341 unsigned int style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
2343 if (!hwnd) return;
2345 TRACE("win %p/%p serial %lu enabled %d visible %d style %08x focus %p active %p fg %p\n",
2346 hwnd, event->window, event->window_got_focus.serial, NtUserIsWindowEnabled(hwnd),
2347 NtUserIsWindowVisible(hwnd), style, get_focus(), get_active_window(), NtUserGetForegroundWindow());
2349 if (can_window_become_foreground(hwnd) && !(style & WS_MINIMIZE))
2351 /* simulate a mouse click on the menu to find out
2352 * whether the window wants to be activated */
2353 LRESULT ma = send_message(hwnd, WM_MOUSEACTIVATE,
2354 (WPARAM)NtUserGetAncestor(hwnd, GA_ROOT),
2355 MAKELONG(HTMENU, WM_LBUTTONDOWN));
2356 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE)
2358 TRACE("setting foreground window to %p\n", hwnd);
2359 NtUserSetForegroundWindow(hwnd);
2360 return;
2364 TRACE("win %p/%p rejecting focus\n", hwnd, event->window);
2365 macdrv_window_rejected_focus(event);
2369 /***********************************************************************
2370 * macdrv_window_lost_focus
2372 * Handler for WINDOW_LOST_FOCUS events.
2374 void macdrv_window_lost_focus(HWND hwnd, const macdrv_event *event)
2376 if (!hwnd) return;
2378 TRACE("win %p/%p fg %p\n", hwnd, event->window, NtUserGetForegroundWindow());
2380 if (hwnd == NtUserGetForegroundWindow())
2382 send_message(hwnd, WM_CANCELMODE, 0, 0);
2383 if (hwnd == NtUserGetForegroundWindow())
2384 NtUserSetForegroundWindow(NtUserGetDesktopWindow());
2389 /***********************************************************************
2390 * macdrv_app_activated
2392 * Handler for APP_ACTIVATED events.
2394 void macdrv_app_activated(void)
2396 TRACE("\n");
2397 macdrv_UpdateClipboard();
2401 /***********************************************************************
2402 * macdrv_app_deactivated
2404 * Handler for APP_DEACTIVATED events.
2406 void macdrv_app_deactivated(void)
2408 NtUserClipCursor(NULL);
2410 if (get_active_window() == NtUserGetForegroundWindow())
2412 TRACE("setting fg to desktop\n");
2413 NtUserSetForegroundWindow(NtUserGetDesktopWindow());
2418 /***********************************************************************
2419 * macdrv_window_maximize_requested
2421 * Handler for WINDOW_MAXIMIZE_REQUESTED events.
2423 void macdrv_window_maximize_requested(HWND hwnd)
2425 perform_window_command(hwnd, WS_MAXIMIZEBOX, WS_MAXIMIZE, SC_MAXIMIZE, HTMAXBUTTON);
2429 /***********************************************************************
2430 * macdrv_window_minimize_requested
2432 * Handler for WINDOW_MINIMIZE_REQUESTED events.
2434 void macdrv_window_minimize_requested(HWND hwnd)
2436 perform_window_command(hwnd, WS_MINIMIZEBOX, WS_MINIMIZE, SC_MINIMIZE, HTMINBUTTON);
2440 /***********************************************************************
2441 * macdrv_window_did_minimize
2443 * Handler for WINDOW_DID_MINIMIZE events.
2445 void macdrv_window_did_minimize(HWND hwnd)
2447 TRACE("win %p\n", hwnd);
2449 /* If all our windows are minimized, disable cursor clipping. */
2450 if (!macdrv_is_any_wine_window_visible())
2451 NtUserClipCursor(NULL);
2455 /***********************************************************************
2456 * macdrv_window_did_unminimize
2458 * Handler for WINDOW_DID_UNMINIMIZE events.
2460 void macdrv_window_did_unminimize(HWND hwnd)
2462 struct macdrv_win_data *data;
2463 unsigned int style;
2465 TRACE("win %p\n", hwnd);
2467 if (!(data = get_win_data(hwnd))) return;
2468 if (!data->minimized) goto done;
2470 style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
2472 data->minimized = FALSE;
2473 if ((style & (WS_MINIMIZE | WS_VISIBLE)) == (WS_MINIMIZE | WS_VISIBLE))
2475 TRACE("restoring win %p/%p\n", hwnd, data->cocoa_window);
2476 release_win_data(data);
2477 NtUserSetActiveWindow(hwnd);
2478 send_message(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
2479 return;
2482 TRACE("not restoring win %p/%p style %08x\n", hwnd, data->cocoa_window, style);
2484 done:
2485 release_win_data(data);
2489 /***********************************************************************
2490 * macdrv_window_brought_forward
2492 * Handler for WINDOW_BROUGHT_FORWARD events.
2494 void macdrv_window_brought_forward(HWND hwnd)
2496 TRACE("win %p\n", hwnd);
2497 NtUserSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
2501 /***********************************************************************
2502 * macdrv_window_resize_ended
2504 * Handler for WINDOW_RESIZE_ENDED events.
2506 void macdrv_window_resize_ended(HWND hwnd)
2508 TRACE("hwnd %p\n", hwnd);
2509 send_message(hwnd, WM_EXITSIZEMOVE, 0, 0);
2513 /***********************************************************************
2514 * macdrv_window_restore_requested
2516 * Handler for WINDOW_RESTORE_REQUESTED events. This is specifically
2517 * for restoring from maximized, not from minimized.
2519 void macdrv_window_restore_requested(HWND hwnd, const macdrv_event *event)
2521 if (event->window_restore_requested.keep_frame && hwnd)
2523 DWORD style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
2524 struct macdrv_win_data *data;
2526 if ((style & WS_MAXIMIZE) && (style & WS_VISIBLE) && (data = get_win_data(hwnd)))
2528 RECT rect;
2529 HWND parent = NtUserGetAncestor(hwnd, GA_PARENT);
2531 rect = rect_from_cgrect(event->window_restore_requested.frame);
2532 macdrv_mac_to_window_rect(data, &rect);
2533 NtUserMapWindowPoints(0, parent, (POINT *)&rect, 2);
2535 release_win_data(data);
2537 NtUserSetInternalWindowPos(hwnd, SW_SHOW, &rect, NULL);
2541 perform_window_command(hwnd, WS_MAXIMIZE, 0, SC_RESTORE, HTMAXBUTTON);
2545 /***********************************************************************
2546 * macdrv_window_drag_begin
2548 * Handler for WINDOW_DRAG_BEGIN events.
2550 void macdrv_window_drag_begin(HWND hwnd, const macdrv_event *event)
2552 DWORD style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
2553 struct macdrv_win_data *data;
2554 HANDLE drag_event = NULL;
2555 OBJECT_ATTRIBUTES attr;
2556 BOOL loop = TRUE;
2557 MSG msg;
2559 TRACE("win %p\n", hwnd);
2561 if (style & (WS_DISABLED | WS_MAXIMIZE | WS_MINIMIZE)) return;
2562 if (!(style & WS_VISIBLE)) return;
2564 if (!(data = get_win_data(hwnd))) return;
2565 if (data->drag_event) goto done;
2567 InitializeObjectAttributes(&attr, NULL, OBJ_OPENIF, NULL, NULL);
2568 if (NtCreateEvent(&drag_event, EVENT_ALL_ACCESS, &attr, NotificationEvent, FALSE)) goto done;
2570 data->drag_event = drag_event;
2571 release_win_data(data);
2573 if (!event->window_drag_begin.no_activate && can_window_become_foreground(hwnd) &&
2574 NtUserGetForegroundWindow() != hwnd)
2576 /* ask whether the window wants to be activated */
2577 LRESULT ma = send_message(hwnd, WM_MOUSEACTIVATE, (WPARAM)NtUserGetAncestor(hwnd, GA_ROOT),
2578 MAKELONG(HTCAPTION, WM_LBUTTONDOWN));
2579 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE)
2581 TRACE("setting foreground window to %p\n", hwnd);
2582 NtUserSetForegroundWindow(hwnd);
2586 NtUserClipCursor(NULL);
2587 send_message(hwnd, WM_ENTERSIZEMOVE, 0, 0);
2588 NtUserReleaseCapture();
2590 while (loop)
2592 while (!NtUserPeekMessage(&msg, 0, 0, 0, PM_REMOVE))
2594 DWORD result = NtUserMsgWaitForMultipleObjectsEx(1, &drag_event, INFINITE, QS_ALLINPUT,
2595 MWMO_INPUTAVAILABLE);
2596 if (result == WAIT_OBJECT_0)
2598 loop = FALSE;
2599 break;
2602 if (!loop)
2603 break;
2605 if (msg.message == WM_QUIT)
2606 break;
2608 if (!NtUserCallMsgFilter(&msg, MSGF_SIZE) && msg.message != WM_KEYDOWN &&
2609 msg.message != WM_MOUSEMOVE && msg.message != WM_LBUTTONDOWN && msg.message != WM_LBUTTONUP)
2611 NtUserTranslateMessage(&msg, 0);
2612 NtUserDispatchMessage(&msg);
2616 send_message(hwnd, WM_EXITSIZEMOVE, 0, 0);
2618 TRACE("done\n");
2620 if ((data = get_win_data(hwnd)))
2621 data->drag_event = NULL;
2623 done:
2624 release_win_data(data);
2625 if (drag_event) NtClose(drag_event);
2629 /***********************************************************************
2630 * macdrv_window_drag_end
2632 * Handler for WINDOW_DRAG_END events.
2634 void macdrv_window_drag_end(HWND hwnd)
2636 struct macdrv_win_data *data;
2638 TRACE("win %p\n", hwnd);
2640 if (!(data = get_win_data(hwnd))) return;
2641 if (data->drag_event)
2642 NtSetEvent(data->drag_event, NULL);
2643 release_win_data(data);
2647 /***********************************************************************
2648 * macdrv_reassert_window_position
2650 * Handler for REASSERT_WINDOW_POSITION events.
2652 void macdrv_reassert_window_position(HWND hwnd)
2654 struct macdrv_win_data *data = get_win_data(hwnd);
2655 if (data)
2657 if (data->cocoa_window && data->on_screen)
2658 sync_window_position(data, SWP_NOZORDER | SWP_NOACTIVATE, NULL, NULL);
2659 release_win_data(data);
2664 /***********************************************************************
2665 * macdrv_app_quit_requested
2667 * Handler for APP_QUIT_REQUESTED events.
2669 void macdrv_app_quit_requested(const macdrv_event *event)
2671 struct app_quit_request_params params = { .flags = 0 };
2673 TRACE("reason %d\n", event->app_quit_requested.reason);
2675 if (event->app_quit_requested.reason == QUIT_REASON_LOGOUT)
2676 params.flags = ENDSESSION_LOGOFF;
2678 macdrv_client_func(client_func_app_quit_request, &params, sizeof(params));
2682 /***********************************************************************
2683 * query_resize_size
2685 * Handler for QUERY_RESIZE_SIZE query.
2687 BOOL query_resize_size(HWND hwnd, macdrv_query *query)
2689 struct macdrv_win_data *data = get_win_data(hwnd);
2690 RECT rect = rect_from_cgrect(query->resize_size.rect);
2691 int corner;
2692 BOOL ret = FALSE;
2694 if (!data) return FALSE;
2696 macdrv_mac_to_window_rect(data, &rect);
2698 if (query->resize_size.from_left)
2700 if (query->resize_size.from_top)
2701 corner = WMSZ_TOPLEFT;
2702 else
2703 corner = WMSZ_BOTTOMLEFT;
2705 else if (query->resize_size.from_top)
2706 corner = WMSZ_TOPRIGHT;
2707 else
2708 corner = WMSZ_BOTTOMRIGHT;
2710 if (send_message(hwnd, WM_SIZING, corner, (LPARAM)&rect))
2712 macdrv_window_to_mac_rect(data, NtUserGetWindowLongW(hwnd, GWL_STYLE), &rect,
2713 &data->window_rect, &data->client_rect);
2714 query->resize_size.rect = cgrect_from_rect(rect);
2715 ret = TRUE;
2718 release_win_data(data);
2719 return ret;
2723 /***********************************************************************
2724 * query_resize_start
2726 * Handler for QUERY_RESIZE_START query.
2728 BOOL query_resize_start(HWND hwnd)
2730 TRACE("hwnd %p\n", hwnd);
2732 NtUserClipCursor(NULL);
2734 sync_window_min_max_info(hwnd);
2735 send_message(hwnd, WM_ENTERSIZEMOVE, 0, 0);
2737 return TRUE;
2741 /***********************************************************************
2742 * query_min_max_info
2744 * Handler for QUERY_MIN_MAX_INFO query.
2746 BOOL query_min_max_info(HWND hwnd)
2748 TRACE("hwnd %p\n", hwnd);
2749 sync_window_min_max_info(hwnd);
2750 return TRUE;
2754 /***********************************************************************
2755 * init_win_context
2757 void init_win_context(void)
2759 pthread_mutexattr_t attr;
2761 pthread_mutexattr_init(&attr);
2762 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
2763 pthread_mutex_init(&win_data_mutex, &attr);
2764 pthread_mutexattr_destroy(&attr);