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
26 #include <IOKit/pwr_mgt/IOPMLib.h>
27 #define GetCurrentThread Mac_GetCurrentThread
28 #define LoadResource Mac_LoadResource
29 #include <CoreServices/CoreServices.h>
30 #undef GetCurrentThread
35 #include "wine/unicode.h"
36 #include "wine/server.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(macdrv
);
41 static CRITICAL_SECTION win_data_section
;
42 static CRITICAL_SECTION_DEBUG critsect_debug
=
44 0, 0, &win_data_section
,
45 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
46 0, 0, { (DWORD_PTR
)(__FILE__
": win_data_section") }
48 static CRITICAL_SECTION win_data_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
50 static CFMutableDictionaryRef win_datas
;
52 static DWORD activate_on_focus_time
;
55 /***********************************************************************
56 * get_cocoa_window_features
58 static void get_cocoa_window_features(struct macdrv_win_data
*data
,
59 DWORD style
, DWORD ex_style
,
60 struct macdrv_window_features
* wf
,
61 const RECT
*window_rect
,
62 const RECT
*client_rect
)
64 memset(wf
, 0, sizeof(*wf
));
66 if (disable_window_decorations
) return;
67 if (IsRectEmpty(window_rect
)) return;
68 if (EqualRect(window_rect
, client_rect
)) return;
70 if ((style
& WS_CAPTION
) == WS_CAPTION
&& !(ex_style
& WS_EX_LAYERED
))
76 if (style
& WS_SYSMENU
) wf
->close_button
= TRUE
;
77 if (style
& WS_MINIMIZEBOX
) wf
->minimize_button
= TRUE
;
78 if (style
& WS_MAXIMIZEBOX
) wf
->maximize_button
= TRUE
;
79 if (ex_style
& WS_EX_TOOLWINDOW
) wf
->utility
= TRUE
;
82 if (style
& WS_THICKFRAME
)
85 if (!data
->shaped
) wf
->resizable
= TRUE
;
87 else if (ex_style
& WS_EX_DLGMODALFRAME
) wf
->shadow
= TRUE
;
88 else if ((style
& (WS_DLGFRAME
|WS_BORDER
)) == WS_DLGFRAME
) wf
->shadow
= TRUE
;
92 /*******************************************************************
93 * can_window_become_foreground
95 * Check if the specified window can become the foreground/key
98 static inline BOOL
can_window_become_foreground(HWND hwnd
)
100 LONG style
= GetWindowLongW(hwnd
, GWL_STYLE
);
102 if (!(style
& WS_VISIBLE
)) return FALSE
;
103 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
104 if (hwnd
== GetDesktopWindow()) return FALSE
;
105 return !(style
& WS_DISABLED
);
109 /***********************************************************************
110 * get_cocoa_window_state
112 static void get_cocoa_window_state(struct macdrv_win_data
*data
,
113 DWORD style
, DWORD ex_style
,
114 struct macdrv_window_state
* state
)
116 memset(state
, 0, sizeof(*state
));
117 state
->disabled
= (style
& WS_DISABLED
) != 0;
118 state
->no_foreground
= !can_window_become_foreground(data
->hwnd
);
119 state
->floating
= (ex_style
& WS_EX_TOPMOST
) != 0;
120 state
->excluded_by_expose
= state
->excluded_by_cycle
=
121 (!(ex_style
& WS_EX_APPWINDOW
) &&
122 (GetWindow(data
->hwnd
, GW_OWNER
) || (ex_style
& (WS_EX_TOOLWINDOW
| WS_EX_NOACTIVATE
))));
123 if (IsRectEmpty(&data
->window_rect
))
124 state
->excluded_by_expose
= TRUE
;
125 state
->minimized
= (style
& WS_MINIMIZE
) != 0;
126 state
->minimized_valid
= state
->minimized
!= data
->minimized
;
127 state
->maximized
= (style
& WS_MAXIMIZE
) != 0;
131 /***********************************************************************
132 * get_mac_rect_offset
134 * Helper for macdrv_window_to_mac_rect and macdrv_mac_to_window_rect.
136 static void get_mac_rect_offset(struct macdrv_win_data
*data
, DWORD style
, RECT
*rect
,
137 const RECT
*window_rect
, const RECT
*client_rect
)
139 DWORD ex_style
, style_mask
= 0, ex_style_mask
= 0;
141 rect
->top
= rect
->bottom
= rect
->left
= rect
->right
= 0;
143 ex_style
= GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
);
147 struct macdrv_window_features wf
;
148 get_cocoa_window_features(data
, style
, ex_style
, &wf
, window_rect
, client_rect
);
152 style_mask
|= WS_CAPTION
;
153 ex_style_mask
|= WS_EX_TOOLWINDOW
;
157 style_mask
|= WS_DLGFRAME
| WS_THICKFRAME
;
158 ex_style_mask
|= WS_EX_DLGMODALFRAME
;
162 AdjustWindowRectEx(rect
, style
& style_mask
, FALSE
, ex_style
& ex_style_mask
);
164 TRACE("%p/%p style %08x ex_style %08x shaped %d -> %s\n", data
->hwnd
, data
->cocoa_window
,
165 style
, ex_style
, data
->shaped
, wine_dbgstr_rect(rect
));
169 /***********************************************************************
170 * macdrv_window_to_mac_rect
172 * Convert a rect from client to Mac window coordinates
174 static void macdrv_window_to_mac_rect(struct macdrv_win_data
*data
, DWORD style
, RECT
*rect
,
175 const RECT
*window_rect
, const RECT
*client_rect
)
179 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return;
180 if (IsRectEmpty(rect
)) return;
182 get_mac_rect_offset(data
, style
, &rc
, window_rect
, client_rect
);
184 rect
->left
-= rc
.left
;
185 rect
->right
-= rc
.right
;
187 rect
->bottom
-= rc
.bottom
;
188 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
189 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
193 /***********************************************************************
194 * macdrv_mac_to_window_rect
196 * Opposite of macdrv_window_to_mac_rect
198 static void macdrv_mac_to_window_rect(struct macdrv_win_data
*data
, RECT
*rect
)
201 DWORD style
= GetWindowLongW(data
->hwnd
, GWL_STYLE
);
203 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return;
204 if (IsRectEmpty(rect
)) return;
206 get_mac_rect_offset(data
, style
, &rc
, &data
->window_rect
, &data
->client_rect
);
208 rect
->left
+= rc
.left
;
209 rect
->right
+= rc
.right
;
211 rect
->bottom
+= rc
.bottom
;
212 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
213 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
217 /***********************************************************************
218 * constrain_window_frame
220 * Alter a window frame rectangle to fit within a) Cocoa's documented
221 * limits, and b) sane sizes, like twice the desktop rect.
223 static void constrain_window_frame(CGRect
* frame
)
225 CGRect desktop_rect
= macdrv_get_desktop_rect();
226 int max_width
, max_height
;
228 max_width
= min(32000, 2 * CGRectGetWidth(desktop_rect
));
229 max_height
= min(32000, 2 * CGRectGetHeight(desktop_rect
));
231 if (frame
->origin
.x
< -16000) frame
->origin
.x
= -16000;
232 if (frame
->origin
.y
< -16000) frame
->origin
.y
= -16000;
233 if (frame
->origin
.x
> 16000) frame
->origin
.x
= 16000;
234 if (frame
->origin
.y
> 16000) frame
->origin
.y
= 16000;
235 if (frame
->size
.width
> max_width
) frame
->size
.width
= max_width
;
236 if (frame
->size
.height
> max_height
) frame
->size
.height
= max_height
;
240 /***********************************************************************
243 static struct macdrv_win_data
*alloc_win_data(HWND hwnd
)
245 struct macdrv_win_data
*data
;
247 if ((data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
))))
250 data
->color_key
= CLR_INVALID
;
251 data
->swap_interval
= 1;
252 EnterCriticalSection(&win_data_section
);
254 win_datas
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
255 CFDictionarySetValue(win_datas
, hwnd
, data
);
261 /***********************************************************************
264 * Lock and return the data structure associated with a window.
266 struct macdrv_win_data
*get_win_data(HWND hwnd
)
268 struct macdrv_win_data
*data
;
270 if (!hwnd
) return NULL
;
271 EnterCriticalSection(&win_data_section
);
272 if (win_datas
&& (data
= (struct macdrv_win_data
*)CFDictionaryGetValue(win_datas
, hwnd
)))
274 LeaveCriticalSection(&win_data_section
);
279 /***********************************************************************
282 * Release the data returned by get_win_data.
284 void release_win_data(struct macdrv_win_data
*data
)
286 if (data
) LeaveCriticalSection(&win_data_section
);
290 /***********************************************************************
291 * macdrv_get_cocoa_window
293 * Return the Mac window associated with the full area of a window
295 macdrv_window
macdrv_get_cocoa_window(HWND hwnd
, BOOL require_on_screen
)
297 struct macdrv_win_data
*data
= get_win_data(hwnd
);
298 macdrv_window ret
= NULL
;
299 if (data
&& (data
->on_screen
|| !require_on_screen
))
300 ret
= data
->cocoa_window
;
301 release_win_data(data
);
306 /***********************************************************************
307 * macdrv_get_cocoa_view
309 * Return the Cocoa view associated with a window
311 macdrv_view
macdrv_get_cocoa_view(HWND hwnd
)
313 struct macdrv_win_data
*data
= get_win_data(hwnd
);
314 macdrv_view ret
= data
? data
->cocoa_view
: NULL
;
316 release_win_data(data
);
321 /***********************************************************************
322 * macdrv_get_client_cocoa_view
324 * Return the Cocoa view associated with a window's client area
326 macdrv_view
macdrv_get_client_cocoa_view(HWND hwnd
)
328 struct macdrv_win_data
*data
= get_win_data(hwnd
);
329 macdrv_view ret
= data
? data
->client_cocoa_view
: NULL
;
331 release_win_data(data
);
336 /***********************************************************************
337 * set_cocoa_window_properties
339 * Set the window properties for a Cocoa window based on its Windows
342 static void set_cocoa_window_properties(struct macdrv_win_data
*data
)
344 DWORD style
, ex_style
;
346 macdrv_window owner_win
;
347 struct macdrv_window_features wf
;
348 struct macdrv_window_state state
;
350 style
= GetWindowLongW(data
->hwnd
, GWL_STYLE
);
351 ex_style
= GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
);
353 owner
= GetWindow(data
->hwnd
, GW_OWNER
);
355 owner
= GetAncestor(owner
, GA_ROOT
);
356 owner_win
= macdrv_get_cocoa_window(owner
, TRUE
);
357 macdrv_set_cocoa_parent_window(data
->cocoa_window
, owner_win
);
359 get_cocoa_window_features(data
, style
, ex_style
, &wf
, &data
->window_rect
, &data
->client_rect
);
360 macdrv_set_cocoa_window_features(data
->cocoa_window
, &wf
);
362 get_cocoa_window_state(data
, style
, ex_style
, &state
);
363 macdrv_set_cocoa_window_state(data
->cocoa_window
, &state
);
364 if (state
.minimized_valid
)
365 data
->minimized
= state
.minimized
;
369 /***********************************************************************
372 * Update the window region.
374 static void sync_window_region(struct macdrv_win_data
*data
, HRGN win_region
)
376 HRGN hrgn
= win_region
;
377 RGNDATA
*region_data
;
381 if (!data
->cocoa_window
) return;
382 data
->shaped
= FALSE
;
384 if (IsRectEmpty(&data
->window_rect
)) /* set an empty shape */
386 TRACE("win %p/%p setting empty shape for zero-sized window\n", data
->hwnd
, data
->cocoa_window
);
387 macdrv_set_window_shape(data
->cocoa_window
, &CGRectZero
, 1);
391 if (hrgn
== (HRGN
)1) /* hack: win_region == 1 means retrieve region from server */
393 if (!(hrgn
= CreateRectRgn(0, 0, 0, 0))) return;
394 if (GetWindowRgn(data
->hwnd
, hrgn
) == ERROR
)
401 if (hrgn
&& GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
)
402 MirrorRgn(data
->hwnd
, hrgn
);
405 OffsetRgn(hrgn
, data
->window_rect
.left
- data
->whole_rect
.left
,
406 data
->window_rect
.top
- data
->whole_rect
.top
);
408 region_data
= get_region_data(hrgn
, 0);
411 rects
= (CGRect
*)region_data
->Buffer
;
412 count
= region_data
->rdh
.nCount
;
413 /* Special case optimization. If the region entirely encloses the Cocoa
414 window, it's the same as there being no region. It's potentially
415 hard/slow to test this for arbitrary regions, so we just check for
416 very simple regions. */
417 if (count
== 1 && CGRectContainsRect(rects
[0],
418 CGRectOffset(cgrect_from_rect(data
->whole_rect
), -data
->whole_rect
.left
, -data
->whole_rect
.top
)))
420 TRACE("optimizing for simple region that contains Cocoa content rect\n");
431 TRACE("win %p/%p win_region %p rects %p count %d\n", data
->hwnd
, data
->cocoa_window
, win_region
, rects
, count
);
432 macdrv_set_window_shape(data
->cocoa_window
, rects
, count
);
434 HeapFree(GetProcessHeap(), 0, region_data
);
435 data
->shaped
= (region_data
!= NULL
);
437 if (hrgn
&& hrgn
!= win_region
) DeleteObject(hrgn
);
441 /***********************************************************************
444 static inline void add_bounds_rect(RECT
*bounds
, const RECT
*rect
)
446 if (rect
->left
>= rect
->right
|| rect
->top
>= rect
->bottom
) return;
447 bounds
->left
= min(bounds
->left
, rect
->left
);
448 bounds
->top
= min(bounds
->top
, rect
->top
);
449 bounds
->right
= max(bounds
->right
, rect
->right
);
450 bounds
->bottom
= max(bounds
->bottom
, rect
->bottom
);
454 /***********************************************************************
455 * sync_window_opacity
457 static void sync_window_opacity(struct macdrv_win_data
*data
, COLORREF key
, BYTE alpha
,
458 BOOL per_pixel_alpha
, DWORD flags
)
460 CGFloat opacity
= 1.0;
461 BOOL needs_flush
= FALSE
;
463 if (flags
& LWA_ALPHA
) opacity
= alpha
/ 255.0;
465 TRACE("setting window %p/%p alpha to %g\n", data
->hwnd
, data
->cocoa_window
, opacity
);
466 macdrv_set_window_alpha(data
->cocoa_window
, opacity
);
468 if (flags
& LWA_COLORKEY
)
470 /* FIXME: treat PALETTEINDEX and DIBINDEX as black */
471 if ((key
& (1 << 24)) || key
>> 16 == 0x10ff)
477 if (data
->color_key
!= key
)
479 if (key
== CLR_INVALID
)
481 TRACE("clearing color-key for window %p/%p\n", data
->hwnd
, data
->cocoa_window
);
482 macdrv_clear_window_color_key(data
->cocoa_window
);
486 TRACE("setting color-key for window %p/%p to RGB %d,%d,%d\n", data
->hwnd
, data
->cocoa_window
,
487 GetRValue(key
), GetGValue(key
), GetBValue(key
));
488 macdrv_set_window_color_key(data
->cocoa_window
, GetRValue(key
), GetGValue(key
), GetBValue(key
));
491 data
->color_key
= key
;
495 if (!data
->per_pixel_alpha
!= !per_pixel_alpha
)
497 TRACE("setting window %p/%p per-pixel-alpha to %d\n", data
->hwnd
, data
->cocoa_window
, per_pixel_alpha
);
498 macdrv_window_use_per_pixel_alpha(data
->cocoa_window
, per_pixel_alpha
);
499 data
->per_pixel_alpha
= per_pixel_alpha
;
503 if (needs_flush
&& data
->surface
)
508 rect
= data
->whole_rect
;
509 OffsetRect(&rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
510 data
->surface
->funcs
->lock(data
->surface
);
511 bounds
= data
->surface
->funcs
->get_bounds(data
->surface
);
512 add_bounds_rect(bounds
, &rect
);
513 data
->surface
->funcs
->unlock(data
->surface
);
518 /***********************************************************************
519 * sync_window_min_max_info
521 static void sync_window_min_max_info(HWND hwnd
)
523 LONG style
= GetWindowLongW(hwnd
, GWL_STYLE
);
524 LONG exstyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
525 RECT win_rect
, primary_monitor_rect
;
531 struct macdrv_win_data
*data
;
533 TRACE("win %p\n", hwnd
);
535 if (!macdrv_get_cocoa_window(hwnd
, FALSE
)) return;
537 GetWindowRect(hwnd
, &win_rect
);
538 minmax
.ptReserved
.x
= win_rect
.left
;
539 minmax
.ptReserved
.y
= win_rect
.top
;
541 if ((style
& WS_CAPTION
) == WS_CAPTION
)
542 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
544 adjustedStyle
= style
;
546 primary_monitor_rect
.left
= primary_monitor_rect
.top
= 0;
547 primary_monitor_rect
.right
= GetSystemMetrics(SM_CXSCREEN
);
548 primary_monitor_rect
.bottom
= GetSystemMetrics(SM_CYSCREEN
);
549 AdjustWindowRectEx(&primary_monitor_rect
, adjustedStyle
, ((style
& WS_POPUP
) && GetMenu(hwnd
)), exstyle
);
551 xinc
= -primary_monitor_rect
.left
;
552 yinc
= -primary_monitor_rect
.top
;
554 minmax
.ptMaxSize
.x
= primary_monitor_rect
.right
- primary_monitor_rect
.left
;
555 minmax
.ptMaxSize
.y
= primary_monitor_rect
.bottom
- primary_monitor_rect
.top
;
556 minmax
.ptMaxPosition
.x
= -xinc
;
557 minmax
.ptMaxPosition
.y
= -yinc
;
558 if (style
& (WS_DLGFRAME
| WS_BORDER
))
560 minmax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
561 minmax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
565 minmax
.ptMinTrackSize
.x
= 2 * xinc
;
566 minmax
.ptMinTrackSize
.y
= 2 * yinc
;
568 minmax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXMAXTRACK
);
569 minmax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYMAXTRACK
);
571 wpl
.length
= sizeof(wpl
);
572 if (GetWindowPlacement(hwnd
, &wpl
) && (wpl
.ptMaxPosition
.x
!= -1 || wpl
.ptMaxPosition
.y
!= -1))
574 minmax
.ptMaxPosition
= wpl
.ptMaxPosition
;
576 /* Convert from GetWindowPlacement's workspace coordinates to screen coordinates. */
577 minmax
.ptMaxPosition
.x
-= wpl
.rcNormalPosition
.left
- win_rect
.left
;
578 minmax
.ptMaxPosition
.y
-= wpl
.rcNormalPosition
.top
- win_rect
.top
;
581 TRACE("initial ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax
.ptMaxSize
),
582 wine_dbgstr_point(&minmax
.ptMaxPosition
), wine_dbgstr_point(&minmax
.ptMinTrackSize
), wine_dbgstr_point(&minmax
.ptMaxTrackSize
));
584 SendMessageW(hwnd
, WM_GETMINMAXINFO
, 0, (LPARAM
)&minmax
);
586 TRACE("app's ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax
.ptMaxSize
),
587 wine_dbgstr_point(&minmax
.ptMaxPosition
), wine_dbgstr_point(&minmax
.ptMinTrackSize
), wine_dbgstr_point(&minmax
.ptMaxTrackSize
));
589 /* if the app didn't change the values, adapt them for the window's monitor */
590 if ((monitor
= MonitorFromWindow(hwnd
, MONITOR_DEFAULTTOPRIMARY
)))
592 MONITORINFO mon_info
;
595 mon_info
.cbSize
= sizeof(mon_info
);
596 GetMonitorInfoW(monitor
, &mon_info
);
598 if ((style
& WS_MAXIMIZEBOX
) && ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& WS_POPUP
)))
599 monitor_rect
= mon_info
.rcWork
;
601 monitor_rect
= mon_info
.rcMonitor
;
603 if (minmax
.ptMaxSize
.x
== primary_monitor_rect
.right
- primary_monitor_rect
.left
&&
604 minmax
.ptMaxSize
.y
== primary_monitor_rect
.bottom
- primary_monitor_rect
.top
)
606 minmax
.ptMaxSize
.x
= (monitor_rect
.right
- monitor_rect
.left
) + 2 * xinc
;
607 minmax
.ptMaxSize
.y
= (monitor_rect
.bottom
- monitor_rect
.top
) + 2 * yinc
;
609 if (minmax
.ptMaxPosition
.x
== -xinc
&& minmax
.ptMaxPosition
.y
== -yinc
)
611 minmax
.ptMaxPosition
.x
= monitor_rect
.left
- xinc
;
612 minmax
.ptMaxPosition
.y
= monitor_rect
.top
- yinc
;
616 minmax
.ptMaxTrackSize
.x
= max(minmax
.ptMaxTrackSize
.x
, minmax
.ptMinTrackSize
.x
);
617 minmax
.ptMaxTrackSize
.y
= max(minmax
.ptMaxTrackSize
.y
, minmax
.ptMinTrackSize
.y
);
619 TRACE("adjusted ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax
.ptMaxSize
),
620 wine_dbgstr_point(&minmax
.ptMaxPosition
), wine_dbgstr_point(&minmax
.ptMinTrackSize
), wine_dbgstr_point(&minmax
.ptMaxTrackSize
));
622 if ((data
= get_win_data(hwnd
)) && data
->cocoa_window
)
624 RECT min_rect
, max_rect
;
625 CGSize min_size
, max_size
;
627 SetRect(&min_rect
, 0, 0, minmax
.ptMinTrackSize
.x
, minmax
.ptMinTrackSize
.y
);
628 macdrv_window_to_mac_rect(data
, style
, &min_rect
, &data
->window_rect
, &data
->client_rect
);
629 min_size
= CGSizeMake(min_rect
.right
- min_rect
.left
, min_rect
.bottom
- min_rect
.top
);
631 if (minmax
.ptMaxTrackSize
.x
== GetSystemMetrics(SM_CXMAXTRACK
) &&
632 minmax
.ptMaxTrackSize
.y
== GetSystemMetrics(SM_CYMAXTRACK
))
633 max_size
= CGSizeMake(CGFLOAT_MAX
, CGFLOAT_MAX
);
636 SetRect(&max_rect
, 0, 0, minmax
.ptMaxTrackSize
.x
, minmax
.ptMaxTrackSize
.y
);
637 macdrv_window_to_mac_rect(data
, style
, &max_rect
, &data
->window_rect
, &data
->client_rect
);
638 max_size
= CGSizeMake(max_rect
.right
- max_rect
.left
, max_rect
.bottom
- max_rect
.top
);
641 TRACE("min_size (%g,%g) max_size (%g,%g)\n", min_size
.width
, min_size
.height
, max_size
.width
, max_size
.height
);
642 macdrv_set_window_min_max_sizes(data
->cocoa_window
, min_size
, max_size
);
645 release_win_data(data
);
649 /**********************************************************************
650 * create_client_cocoa_view
652 * Create the Cocoa view for a window's client area
654 static void create_client_cocoa_view(struct macdrv_win_data
*data
)
656 RECT rect
= data
->client_rect
;
657 OffsetRect(&rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
659 if (data
->client_cocoa_view
)
660 macdrv_set_view_frame(data
->client_cocoa_view
, cgrect_from_rect(rect
));
663 data
->client_cocoa_view
= macdrv_create_view(cgrect_from_rect(rect
));
664 macdrv_set_view_hidden(data
->client_cocoa_view
, FALSE
);
666 macdrv_set_view_superview(data
->client_cocoa_view
, data
->cocoa_view
, data
->cocoa_window
, NULL
, NULL
);
670 /**********************************************************************
671 * create_cocoa_window
673 * Create the whole Mac window for a given window
675 static void create_cocoa_window(struct macdrv_win_data
*data
)
677 struct macdrv_thread_data
*thread_data
= macdrv_init_thread_data();
679 struct macdrv_window_features wf
;
681 DWORD style
, ex_style
;
687 if ((win_rgn
= CreateRectRgn(0, 0, 0, 0)) &&
688 GetWindowRgn(data
->hwnd
, win_rgn
) == ERROR
)
690 DeleteObject(win_rgn
);
693 data
->shaped
= (win_rgn
!= 0);
695 style
= GetWindowLongW(data
->hwnd
, GWL_STYLE
);
696 ex_style
= GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
);
698 data
->whole_rect
= data
->window_rect
;
699 macdrv_window_to_mac_rect(data
, style
, &data
->whole_rect
, &data
->window_rect
, &data
->client_rect
);
701 get_cocoa_window_features(data
, style
, ex_style
, &wf
, &data
->window_rect
, &data
->client_rect
);
703 frame
= cgrect_from_rect(data
->whole_rect
);
704 constrain_window_frame(&frame
);
705 if (frame
.size
.width
< 1 || frame
.size
.height
< 1)
706 frame
.size
.width
= frame
.size
.height
= 1;
708 TRACE("creating %p window %s whole %s client %s\n", data
->hwnd
, wine_dbgstr_rect(&data
->window_rect
),
709 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_rect(&data
->client_rect
));
711 data
->cocoa_window
= macdrv_create_cocoa_window(&wf
, frame
, data
->hwnd
, thread_data
->queue
);
712 if (!data
->cocoa_window
) goto done
;
713 create_client_cocoa_view(data
);
715 set_cocoa_window_properties(data
);
717 /* set the window text */
718 if (!InternalGetWindowText(data
->hwnd
, text
, ARRAY_SIZE(text
))) text
[0] = 0;
719 macdrv_set_cocoa_window_title(data
->cocoa_window
, text
, strlenW(text
));
721 /* set the window region */
722 if (win_rgn
|| IsRectEmpty(&data
->window_rect
)) sync_window_region(data
, win_rgn
);
724 /* set the window opacity */
725 if (!GetLayeredWindowAttributes(data
->hwnd
, &key
, &alpha
, &layered_flags
)) layered_flags
= 0;
726 sync_window_opacity(data
, key
, alpha
, FALSE
, layered_flags
);
729 if (win_rgn
) DeleteObject(win_rgn
);
733 /**********************************************************************
734 * destroy_cocoa_window
736 * Destroy the whole Mac window for a given window.
738 static void destroy_cocoa_window(struct macdrv_win_data
*data
)
740 if (!data
->cocoa_window
) return;
742 TRACE("win %p Cocoa win %p\n", data
->hwnd
, data
->cocoa_window
);
744 macdrv_destroy_cocoa_window(data
->cocoa_window
);
745 data
->cocoa_window
= 0;
746 data
->on_screen
= FALSE
;
747 data
->color_key
= CLR_INVALID
;
748 if (data
->surface
) window_surface_release(data
->surface
);
749 data
->surface
= NULL
;
750 if (data
->unminimized_surface
) window_surface_release(data
->unminimized_surface
);
751 data
->unminimized_surface
= NULL
;
755 /**********************************************************************
758 * Create the Cocoa view for a given Windows child window
760 static void create_cocoa_view(struct macdrv_win_data
*data
)
762 BOOL equal
= EqualRect(&data
->window_rect
, &data
->client_rect
);
763 CGRect frame
= cgrect_from_rect(data
->window_rect
);
765 data
->shaped
= FALSE
;
766 data
->whole_rect
= data
->window_rect
;
768 TRACE("creating %p window %s whole %s client %s\n", data
->hwnd
, wine_dbgstr_rect(&data
->window_rect
),
769 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_rect(&data
->client_rect
));
772 data
->cocoa_view
= macdrv_create_view(frame
);
773 create_client_cocoa_view(data
);
776 data
->cocoa_view
= data
->client_cocoa_view
;
777 macdrv_set_view_hidden(data
->cocoa_view
, TRUE
);
778 macdrv_set_view_frame(data
->cocoa_view
, frame
);
783 /**********************************************************************
786 * Destroy the Cocoa view for a given window.
788 static void destroy_cocoa_view(struct macdrv_win_data
*data
)
790 if (!data
->cocoa_view
) return;
792 TRACE("win %p Cocoa view %p\n", data
->hwnd
, data
->cocoa_view
);
794 if (data
->cocoa_view
!= data
->client_cocoa_view
)
795 macdrv_dispose_view(data
->cocoa_view
);
796 data
->cocoa_view
= NULL
;
797 data
->on_screen
= FALSE
;
801 /***********************************************************************
802 * set_cocoa_view_parent
804 static void set_cocoa_view_parent(struct macdrv_win_data
*data
, HWND parent
)
806 struct macdrv_win_data
*parent_data
= get_win_data(parent
);
807 macdrv_window cocoa_window
= parent_data
? parent_data
->cocoa_window
: NULL
;
808 macdrv_view superview
= parent_data
? parent_data
->client_cocoa_view
: NULL
;
810 TRACE("win %p/%p parent %p/%p\n", data
->hwnd
, data
->cocoa_view
, parent
, cocoa_window
? (void*)cocoa_window
: (void*)superview
);
812 if (!cocoa_window
&& !superview
)
813 WARN("hwnd %p new parent %p has no Cocoa window or view in this process\n", data
->hwnd
, parent
);
815 macdrv_set_view_superview(data
->cocoa_view
, superview
, cocoa_window
, NULL
, NULL
);
816 release_win_data(parent_data
);
820 /***********************************************************************
821 * macdrv_create_win_data
823 * Create a Mac data window structure for an existing window.
825 static struct macdrv_win_data
*macdrv_create_win_data(HWND hwnd
, const RECT
*window_rect
,
826 const RECT
*client_rect
)
828 struct macdrv_win_data
*data
;
831 if (GetWindowThreadProcessId(hwnd
, NULL
) != GetCurrentThreadId()) return NULL
;
833 if (!(parent
= GetAncestor(hwnd
, GA_PARENT
))) /* desktop */
835 macdrv_init_thread_data();
839 /* don't create win data for HWND_MESSAGE windows */
840 if (parent
!= GetDesktopWindow() && !GetAncestor(parent
, GA_PARENT
)) return NULL
;
842 if (!(data
= alloc_win_data(hwnd
))) return NULL
;
844 data
->whole_rect
= data
->window_rect
= *window_rect
;
845 data
->client_rect
= *client_rect
;
847 if (parent
== GetDesktopWindow())
849 create_cocoa_window(data
);
850 TRACE("win %p/%p window %s whole %s client %s\n",
851 hwnd
, data
->cocoa_window
, wine_dbgstr_rect(&data
->window_rect
),
852 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_rect(&data
->client_rect
));
856 create_cocoa_view(data
);
857 TRACE("win %p/%p window %s whole %s client %s\n",
858 hwnd
, data
->cocoa_view
, wine_dbgstr_rect(&data
->window_rect
),
859 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_rect(&data
->client_rect
));
861 set_cocoa_view_parent(data
, parent
);
868 /**********************************************************************
871 static BOOL
is_owned_by(HWND hwnd
, HWND maybe_owner
)
875 HWND hwnd2
= GetWindow(hwnd
, GW_OWNER
);
877 hwnd2
= GetAncestor(hwnd
, GA_ROOT
);
878 if (!hwnd2
|| hwnd2
== hwnd
)
880 if (hwnd2
== maybe_owner
)
889 /**********************************************************************
890 * is_all_the_way_front
892 static BOOL
is_all_the_way_front(HWND hwnd
)
894 BOOL topmost
= (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_TOPMOST
) != 0;
897 while ((prev
= GetWindow(prev
, GW_HWNDPREV
)))
899 if (!topmost
&& (GetWindowLongW(prev
, GWL_EXSTYLE
) & WS_EX_TOPMOST
) != 0)
901 if (!is_owned_by(prev
, hwnd
))
909 /***********************************************************************
912 static void set_focus(HWND hwnd
, BOOL raise
)
914 struct macdrv_win_data
*data
;
916 if (!(hwnd
= GetAncestor(hwnd
, GA_ROOT
))) return;
918 if (raise
&& hwnd
== GetForegroundWindow() && hwnd
!= GetDesktopWindow() && !is_all_the_way_front(hwnd
))
919 SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOOWNERZORDER
);
921 if (!(data
= get_win_data(hwnd
))) return;
923 if (data
->cocoa_window
&& data
->on_screen
)
925 BOOL activate
= activate_on_focus_time
&& (GetTickCount() - activate_on_focus_time
< 2000);
927 macdrv_give_cocoa_window_focus(data
->cocoa_window
, activate
);
928 activate_on_focus_time
= 0;
931 release_win_data(data
);
934 /***********************************************************************
937 static void show_window(struct macdrv_win_data
*data
)
939 if (data
->cocoa_window
)
943 macdrv_window prev_window
= NULL
;
944 macdrv_window next_window
= NULL
;
945 BOOL activate
= FALSE
;
948 /* find window that this one must be after */
949 prev
= GetWindow(data
->hwnd
, GW_HWNDPREV
);
950 while (prev
&& !((GetWindowLongW(prev
, GWL_STYLE
) & (WS_VISIBLE
| WS_MINIMIZE
)) == WS_VISIBLE
&&
951 (prev_window
= macdrv_get_cocoa_window(prev
, TRUE
))))
952 prev
= GetWindow(prev
, GW_HWNDPREV
);
955 /* find window that this one must be before */
956 next
= GetWindow(data
->hwnd
, GW_HWNDNEXT
);
957 while (next
&& !((GetWindowLongW(next
, GWL_STYLE
) & (WS_VISIBLE
| WS_MINIMIZE
)) == WS_VISIBLE
&&
958 (next_window
= macdrv_get_cocoa_window(next
, TRUE
))))
959 next
= GetWindow(next
, GW_HWNDNEXT
);
962 TRACE("win %p/%p below %p/%p above %p/%p\n",
963 data
->hwnd
, data
->cocoa_window
, prev
, prev_window
, next
, next_window
);
966 activate
= activate_on_focus_time
&& (GetTickCount() - activate_on_focus_time
< 2000);
967 macdrv_order_cocoa_window(data
->cocoa_window
, prev_window
, next_window
, activate
);
968 data
->on_screen
= TRUE
;
970 info
.cbSize
= sizeof(info
);
971 if (GetGUIThreadInfo(GetWindowThreadProcessId(data
->hwnd
, NULL
), &info
) && info
.hwndFocus
&&
972 (data
->hwnd
== info
.hwndFocus
|| IsChild(data
->hwnd
, info
.hwndFocus
)))
973 set_focus(info
.hwndFocus
, FALSE
);
975 activate_on_focus_time
= 0;
979 TRACE("win %p/%p showing view\n", data
->hwnd
, data
->cocoa_view
);
981 macdrv_set_view_hidden(data
->cocoa_view
, FALSE
);
982 data
->on_screen
= TRUE
;
987 /***********************************************************************
990 static void hide_window(struct macdrv_win_data
*data
)
992 TRACE("win %p/%p\n", data
->hwnd
, data
->cocoa_window
);
994 if (data
->cocoa_window
)
995 macdrv_hide_cocoa_window(data
->cocoa_window
);
997 macdrv_set_view_hidden(data
->cocoa_view
, TRUE
);
998 data
->on_screen
= FALSE
;
1002 /***********************************************************************
1003 * sync_window_z_order
1005 static void sync_window_z_order(struct macdrv_win_data
*data
)
1007 if (data
->cocoa_view
)
1009 HWND parent
= GetAncestor(data
->hwnd
, GA_PARENT
);
1010 macdrv_view superview
= macdrv_get_client_cocoa_view(parent
);
1011 macdrv_window window
= NULL
;
1014 macdrv_view prev_view
= NULL
;
1015 macdrv_view next_view
= NULL
;
1019 window
= macdrv_get_cocoa_window(parent
, FALSE
);
1021 WARN("hwnd %p/%p parent %p has no Cocoa window or view in this process\n", data
->hwnd
, data
->cocoa_view
, parent
);
1024 /* find window that this one must be after */
1025 prev
= GetWindow(data
->hwnd
, GW_HWNDPREV
);
1026 while (prev
&& !(prev_view
= macdrv_get_cocoa_view(prev
)))
1027 prev
= GetWindow(prev
, GW_HWNDPREV
);
1030 /* find window that this one must be before */
1031 next
= GetWindow(data
->hwnd
, GW_HWNDNEXT
);
1032 while (next
&& !(next_view
= macdrv_get_cocoa_view(next
)))
1033 next
= GetWindow(next
, GW_HWNDNEXT
);
1036 TRACE("win %p/%p below %p/%p above %p/%p\n",
1037 data
->hwnd
, data
->cocoa_view
, prev
, prev_view
, next
, next_view
);
1039 macdrv_set_view_superview(data
->cocoa_view
, superview
, window
, prev_view
, next_view
);
1041 else if (data
->on_screen
)
1046 /***********************************************************************
1049 * Calls GetRegionData on the given region and converts the rectangle
1050 * array to CGRect format. The returned buffer must be freed by
1051 * caller using HeapFree(GetProcessHeap(),...).
1052 * If hdc_lptodp is not 0, the rectangles are converted through LPtoDP.
1054 RGNDATA
*get_region_data(HRGN hrgn
, HDC hdc_lptodp
)
1062 if (!hrgn
|| !(size
= GetRegionData(hrgn
, 0, NULL
))) return NULL
;
1063 if (sizeof(CGRect
) > sizeof(RECT
))
1065 /* add extra size for CGRect array */
1066 int count
= (size
- sizeof(RGNDATAHEADER
)) / sizeof(RECT
);
1067 size
+= count
* (sizeof(CGRect
) - sizeof(RECT
));
1069 if (!(data
= HeapAlloc(GetProcessHeap(), 0, size
))) return NULL
;
1070 if (!GetRegionData(hrgn
, size
, data
))
1072 HeapFree(GetProcessHeap(), 0, data
);
1076 rect
= (RECT
*)data
->Buffer
;
1077 cgrect
= (CGRect
*)data
->Buffer
;
1078 if (hdc_lptodp
) /* map to device coordinates */
1080 LPtoDP(hdc_lptodp
, (POINT
*)rect
, data
->rdh
.nCount
* 2);
1081 for (i
= 0; i
< data
->rdh
.nCount
; i
++)
1083 if (rect
[i
].right
< rect
[i
].left
)
1085 INT tmp
= rect
[i
].right
;
1086 rect
[i
].right
= rect
[i
].left
;
1089 if (rect
[i
].bottom
< rect
[i
].top
)
1091 INT tmp
= rect
[i
].bottom
;
1092 rect
[i
].bottom
= rect
[i
].top
;
1098 if (sizeof(CGRect
) > sizeof(RECT
))
1100 /* need to start from the end */
1101 for (i
= data
->rdh
.nCount
-1; i
>= 0; i
--)
1102 cgrect
[i
] = cgrect_from_rect(rect
[i
]);
1106 for (i
= 0; i
< data
->rdh
.nCount
; i
++)
1107 cgrect
[i
] = cgrect_from_rect(rect
[i
]);
1113 /***********************************************************************
1114 * sync_client_view_position
1116 static void sync_client_view_position(struct macdrv_win_data
*data
)
1118 if (data
->cocoa_view
!= data
->client_cocoa_view
)
1120 RECT rect
= data
->client_rect
;
1121 OffsetRect(&rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
1122 macdrv_set_view_frame(data
->client_cocoa_view
, cgrect_from_rect(rect
));
1123 TRACE("win %p/%p client %s\n", data
->hwnd
, data
->client_cocoa_view
, wine_dbgstr_rect(&rect
));
1128 /***********************************************************************
1129 * sync_window_position
1131 * Synchronize the Mac window position with the Windows one
1133 static void sync_window_position(struct macdrv_win_data
*data
, UINT swp_flags
, const RECT
*old_window_rect
,
1134 const RECT
*old_whole_rect
)
1136 CGRect frame
= cgrect_from_rect(data
->whole_rect
);
1137 BOOL force_z_order
= FALSE
;
1139 if (data
->cocoa_window
)
1141 if (data
->minimized
) return;
1143 constrain_window_frame(&frame
);
1144 if (frame
.size
.width
< 1 || frame
.size
.height
< 1)
1145 frame
.size
.width
= frame
.size
.height
= 1;
1147 macdrv_set_cocoa_window_frame(data
->cocoa_window
, &frame
);
1151 BOOL were_equal
= (data
->cocoa_view
== data
->client_cocoa_view
);
1152 BOOL now_equal
= EqualRect(&data
->whole_rect
, &data
->client_rect
);
1154 if (were_equal
&& !now_equal
)
1156 data
->cocoa_view
= macdrv_create_view(frame
);
1157 macdrv_set_view_hidden(data
->cocoa_view
, !data
->on_screen
);
1158 macdrv_set_view_superview(data
->client_cocoa_view
, data
->cocoa_view
, NULL
, NULL
, NULL
);
1159 macdrv_set_view_hidden(data
->client_cocoa_view
, FALSE
);
1160 force_z_order
= TRUE
;
1162 else if (!were_equal
&& now_equal
)
1164 macdrv_dispose_view(data
->cocoa_view
);
1165 data
->cocoa_view
= data
->client_cocoa_view
;
1166 macdrv_set_view_hidden(data
->cocoa_view
, !data
->on_screen
);
1167 macdrv_set_view_frame(data
->cocoa_view
, frame
);
1168 force_z_order
= TRUE
;
1170 else if (!EqualRect(&data
->whole_rect
, old_whole_rect
))
1171 macdrv_set_view_frame(data
->cocoa_view
, frame
);
1174 sync_client_view_position(data
);
1176 if (old_window_rect
&& old_whole_rect
&&
1177 (IsRectEmpty(old_window_rect
) != IsRectEmpty(&data
->window_rect
) ||
1178 old_window_rect
->left
- old_whole_rect
->left
!= data
->window_rect
.left
- data
->whole_rect
.left
||
1179 old_window_rect
->top
- old_whole_rect
->top
!= data
->window_rect
.top
- data
->whole_rect
.top
))
1180 sync_window_region(data
, (HRGN
)1);
1182 TRACE("win %p/%p whole_rect %s frame %s\n", data
->hwnd
,
1183 data
->cocoa_window
? (void*)data
->cocoa_window
: (void*)data
->cocoa_view
,
1184 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_cgrect(frame
));
1186 if (force_z_order
|| !(swp_flags
& SWP_NOZORDER
) || (swp_flags
& SWP_SHOWWINDOW
))
1187 sync_window_z_order(data
);
1191 /***********************************************************************
1194 * Move the window bits when a window is moved.
1196 static void move_window_bits(HWND hwnd
, macdrv_window window
, const RECT
*old_rect
, const RECT
*new_rect
,
1197 const RECT
*old_client_rect
, const RECT
*new_client_rect
,
1198 const RECT
*new_window_rect
)
1200 RECT src_rect
= *old_rect
;
1201 RECT dst_rect
= *new_rect
;
1202 HDC hdc_src
, hdc_dst
;
1208 OffsetRect(&dst_rect
, -new_window_rect
->left
, -new_window_rect
->top
);
1209 parent
= GetAncestor(hwnd
, GA_PARENT
);
1210 hdc_src
= GetDCEx(parent
, 0, DCX_CACHE
);
1211 hdc_dst
= GetDCEx(hwnd
, 0, DCX_CACHE
| DCX_WINDOW
);
1215 OffsetRect(&dst_rect
, -new_client_rect
->left
, -new_client_rect
->top
);
1216 /* make src rect relative to the old position of the window */
1217 OffsetRect(&src_rect
, -old_client_rect
->left
, -old_client_rect
->top
);
1218 if (dst_rect
.left
== src_rect
.left
&& dst_rect
.top
== src_rect
.top
) return;
1219 hdc_src
= hdc_dst
= GetDCEx(hwnd
, 0, DCX_CACHE
);
1222 rgn
= CreateRectRgnIndirect(&dst_rect
);
1223 SelectClipRgn(hdc_dst
, rgn
);
1225 ExcludeUpdateRgn(hdc_dst
, hwnd
);
1227 TRACE("copying bits for win %p/%p %s -> %s\n", hwnd
, window
,
1228 wine_dbgstr_rect(&src_rect
), wine_dbgstr_rect(&dst_rect
));
1229 BitBlt(hdc_dst
, dst_rect
.left
, dst_rect
.top
,
1230 dst_rect
.right
- dst_rect
.left
, dst_rect
.bottom
- dst_rect
.top
,
1231 hdc_src
, src_rect
.left
, src_rect
.top
, SRCCOPY
);
1233 ReleaseDC(hwnd
, hdc_dst
);
1234 if (hdc_src
!= hdc_dst
) ReleaseDC(parent
, hdc_src
);
1238 /**********************************************************************
1239 * activate_on_following_focus
1241 void activate_on_following_focus(void)
1243 activate_on_focus_time
= GetTickCount();
1244 if (!activate_on_focus_time
) activate_on_focus_time
= 1;
1248 /***********************************************************************
1251 static void set_app_icon(void)
1253 CFArrayRef images
= create_app_icon_images();
1256 macdrv_set_application_icon(images
);
1262 /**********************************************************************
1263 * set_capture_window_for_move
1265 static BOOL
set_capture_window_for_move(HWND hwnd
)
1270 SERVER_START_REQ(set_capture_window
)
1272 req
->handle
= wine_server_user_handle(hwnd
);
1273 req
->flags
= CAPTURE_MOVESIZE
;
1274 if ((ret
= !wine_server_call_err(req
)))
1276 previous
= wine_server_ptr_handle(reply
->previous
);
1277 hwnd
= wine_server_ptr_handle(reply
->full_handle
);
1284 macdrv_SetCapture(hwnd
, GUI_INMOVESIZE
);
1286 if (previous
&& previous
!= hwnd
)
1287 SendMessageW(previous
, WM_CAPTURECHANGED
, 0, (LPARAM
)hwnd
);
1293 /***********************************************************************
1296 * Based on user32's WINPOS_SysCommandSizeMove() specialized just for
1297 * moving top-level windows and enforcing Mac-style constraints like
1298 * keeping the top of the window within the work area.
1300 static LRESULT
move_window(HWND hwnd
, WPARAM wparam
)
1303 RECT origRect
, movedRect
, desktopRect
;
1304 LONG hittest
= (LONG
)(wparam
& 0x0f);
1306 LONG style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1308 DWORD dwPoint
= GetMessagePos();
1313 if ((style
& (WS_MINIMIZE
| WS_MAXIMIZE
)) || !IsWindowVisible(hwnd
)) return -1;
1314 if (hittest
&& hittest
!= HTCAPTION
) return -1;
1316 capturePoint
.x
= (short)LOWORD(dwPoint
);
1317 capturePoint
.y
= (short)HIWORD(dwPoint
);
1320 TRACE("hwnd %p hittest %d, pos %d,%d\n", hwnd
, hittest
, capturePoint
.x
, capturePoint
.y
);
1322 origRect
.left
= origRect
.right
= origRect
.top
= origRect
.bottom
= 0;
1323 if (AdjustWindowRectEx(&origRect
, style
, FALSE
, GetWindowLongW(hwnd
, GWL_EXSTYLE
)))
1324 captionHeight
= -origRect
.top
;
1328 GetWindowRect(hwnd
, &origRect
);
1329 movedRect
= origRect
;
1333 /* Move pointer to the center of the caption */
1334 RECT rect
= origRect
;
1336 /* Note: to be exactly centered we should take the different types
1337 * of border into account, but it shouldn't make more than a few pixels
1338 * of difference so let's not bother with that */
1339 rect
.top
+= GetSystemMetrics(SM_CYBORDER
);
1340 if (style
& WS_SYSMENU
)
1341 rect
.left
+= GetSystemMetrics(SM_CXSIZE
) + 1;
1342 if (style
& WS_MINIMIZEBOX
)
1343 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
1344 if (style
& WS_MAXIMIZEBOX
)
1345 rect
.right
-= GetSystemMetrics(SM_CXSIZE
) + 1;
1346 capturePoint
.x
= (rect
.right
+ rect
.left
) / 2;
1347 capturePoint
.y
= rect
.top
+ GetSystemMetrics(SM_CYSIZE
)/2;
1349 SetCursorPos(capturePoint
.x
, capturePoint
.y
);
1350 SendMessageW(hwnd
, WM_SETCURSOR
, (WPARAM
)hwnd
, MAKELONG(HTCAPTION
, WM_MOUSEMOVE
));
1353 desktopRect
= rect_from_cgrect(macdrv_get_desktop_rect());
1354 mon
= MonitorFromPoint(capturePoint
, MONITOR_DEFAULTTONEAREST
);
1355 info
.cbSize
= sizeof(info
);
1356 if (mon
&& !GetMonitorInfoW(mon
, &info
))
1359 /* repaint the window before moving it around */
1360 RedrawWindow(hwnd
, NULL
, 0, RDW_UPDATENOW
| RDW_ALLCHILDREN
);
1362 SendMessageW(hwnd
, WM_ENTERSIZEMOVE
, 0, 0);
1363 set_capture_window_for_move(hwnd
);
1371 if (!GetMessageW(&msg
, 0, 0, 0)) break;
1372 if (CallMsgFilterW(&msg
, MSGF_SIZE
)) continue;
1374 /* Exit on button-up, Return, or Esc */
1375 if (msg
.message
== WM_LBUTTONUP
||
1376 (msg
.message
== WM_KEYDOWN
&& (msg
.wParam
== VK_RETURN
|| msg
.wParam
== VK_ESCAPE
)))
1379 if (msg
.message
!= WM_KEYDOWN
&& msg
.message
!= WM_MOUSEMOVE
)
1381 TranslateMessage(&msg
);
1382 DispatchMessageW(&msg
);
1383 continue; /* We are not interested in other messages */
1388 if (msg
.message
== WM_KEYDOWN
) switch(msg
.wParam
)
1390 case VK_UP
: pt
.y
-= 8; break;
1391 case VK_DOWN
: pt
.y
+= 8; break;
1392 case VK_LEFT
: pt
.x
-= 8; break;
1393 case VK_RIGHT
: pt
.x
+= 8; break;
1396 pt
.x
= max(pt
.x
, desktopRect
.left
);
1397 pt
.x
= min(pt
.x
, desktopRect
.right
- 1);
1398 pt
.y
= max(pt
.y
, desktopRect
.top
);
1399 pt
.y
= min(pt
.y
, desktopRect
.bottom
- 1);
1401 if ((newmon
= MonitorFromPoint(pt
, MONITOR_DEFAULTTONULL
)) && newmon
!= mon
)
1403 if (GetMonitorInfoW(newmon
, &info
))
1411 /* wineserver clips the cursor position to the virtual desktop rect but,
1412 if the display configuration is non-rectangular, that could still
1413 leave the logical cursor position outside of any display. The window
1414 could keep moving as you push the cursor against a display edge, even
1415 though the visible cursor doesn't keep moving. The following keeps
1416 the window movement in sync with the visible cursor. */
1417 pt
.x
= max(pt
.x
, info
.rcMonitor
.left
);
1418 pt
.x
= min(pt
.x
, info
.rcMonitor
.right
- 1);
1419 pt
.y
= max(pt
.y
, info
.rcMonitor
.top
);
1420 pt
.y
= min(pt
.y
, info
.rcMonitor
.bottom
- 1);
1422 /* Assuming that dx will be calculated below as pt.x - capturePoint.x,
1423 dy will be pt.y - capturePoint.y, and movedRect will be offset by those,
1424 we want to enforce these constraints:
1425 movedRect.left + dx < info.rcWork.right
1426 movedRect.right + dx > info.rcWork.left
1427 movedRect.top + captionHeight + dy < info.rcWork.bottom
1428 movedRect.bottom + dy > info.rcWork.top
1429 movedRect.top + dy >= info.rcWork.top
1430 The first four keep at least one edge barely in the work area.
1431 The last keeps the top (i.e. the title bar) in the work area.
1432 The fourth is redundant with the last, so can be ignored.
1434 Substituting for dx and dy and rearranging gives us...
1436 pt
.x
= min(pt
.x
, info
.rcWork
.right
- 1 + capturePoint
.x
- movedRect
.left
);
1437 pt
.x
= max(pt
.x
, info
.rcWork
.left
+ 1 + capturePoint
.x
- movedRect
.right
);
1438 pt
.y
= min(pt
.y
, info
.rcWork
.bottom
- 1 + capturePoint
.y
- movedRect
.top
- captionHeight
);
1439 pt
.y
= max(pt
.y
, info
.rcWork
.top
+ capturePoint
.y
- movedRect
.top
);
1442 dx
= pt
.x
- capturePoint
.x
;
1443 dy
= pt
.y
- capturePoint
.y
;
1449 if (msg
.message
== WM_KEYDOWN
) SetCursorPos(pt
.x
, pt
.y
);
1452 OffsetRect(&movedRect
, dx
, dy
);
1455 SendMessageW(hwnd
, WM_MOVING
, 0, (LPARAM
)&movedRect
);
1456 SetWindowPos(hwnd
, 0, movedRect
.left
, movedRect
.top
, 0, 0,
1457 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOZORDER
);
1462 set_capture_window_for_move(0);
1464 SendMessageW(hwnd
, WM_EXITSIZEMOVE
, 0, 0);
1465 SendMessageW(hwnd
, WM_SETVISIBLE
, TRUE
, 0L);
1467 /* if the move is canceled, restore the previous position */
1468 if (moved
&& msg
.message
== WM_KEYDOWN
&& msg
.wParam
== VK_ESCAPE
)
1470 SetWindowPos(hwnd
, 0, origRect
.left
, origRect
.top
, 0, 0,
1471 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOZORDER
);
1478 /***********************************************************************
1479 * perform_window_command
1481 static void perform_window_command(HWND hwnd
, DWORD style_any
, DWORD style_none
, WORD command
, WORD hittest
)
1485 TRACE("win %p style_any 0x%08x style_none 0x%08x command 0x%04x hittest 0x%04x\n",
1486 hwnd
, style_any
, style_none
, command
, hittest
);
1488 style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1489 if ((style_any
&& !(style
& style_any
)) || (style
& (WS_DISABLED
| style_none
)))
1491 TRACE("not changing win %p style 0x%08x\n", hwnd
, style
);
1495 if (GetActiveWindow() != hwnd
)
1497 LRESULT ma
= SendMessageW(hwnd
, WM_MOUSEACTIVATE
, (WPARAM
)GetAncestor(hwnd
, GA_ROOT
),
1498 MAKELPARAM(hittest
, WM_NCLBUTTONDOWN
));
1501 case MA_NOACTIVATEANDEAT
:
1502 case MA_ACTIVATEANDEAT
:
1503 TRACE("not changing win %p mouse-activate result %ld\n", hwnd
, ma
);
1509 SetActiveWindow(hwnd
);
1512 WARN("unknown WM_MOUSEACTIVATE code %ld\n", ma
);
1517 TRACE("changing win %p\n", hwnd
);
1518 PostMessageW(hwnd
, WM_SYSCOMMAND
, command
, 0);
1522 /**********************************************************************
1523 * CreateDesktopWindow (MACDRV.@)
1525 BOOL CDECL
macdrv_CreateDesktopWindow(HWND hwnd
)
1527 unsigned int width
, height
;
1529 TRACE("%p\n", hwnd
);
1531 /* retrieve the real size of the desktop */
1532 SERVER_START_REQ(get_window_rectangles
)
1534 req
->handle
= wine_server_user_handle(hwnd
);
1535 req
->relative
= COORDS_CLIENT
;
1536 wine_server_call(req
);
1537 width
= reply
->window
.right
;
1538 height
= reply
->window
.bottom
;
1542 if (!width
&& !height
) /* not initialized yet */
1544 CGRect rect
= macdrv_get_desktop_rect();
1546 SERVER_START_REQ(set_window_pos
)
1548 req
->handle
= wine_server_user_handle(hwnd
);
1550 req
->swp_flags
= SWP_NOZORDER
;
1551 req
->window
.left
= CGRectGetMinX(rect
);
1552 req
->window
.top
= CGRectGetMinY(rect
);
1553 req
->window
.right
= CGRectGetMaxX(rect
);
1554 req
->window
.bottom
= CGRectGetMaxY(rect
);
1555 req
->client
= req
->window
;
1556 wine_server_call(req
);
1566 static WNDPROC desktop_orig_wndproc
;
1568 #define WM_WINE_NOTIFY_ACTIVITY WM_USER
1570 static LRESULT CALLBACK
desktop_wndproc_wrapper( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1574 case WM_WINE_NOTIFY_ACTIVITY
:
1576 /* This wakes from display sleep, but doesn't affect the screen saver. */
1577 static IOPMAssertionID assertion
;
1578 IOPMAssertionDeclareUserActivity(CFSTR("Wine user input"), kIOPMUserActiveLocal
, &assertion
);
1580 /* This prevents the screen saver, but doesn't wake from display sleep. */
1581 /* It's deprecated, but there's no better alternative. */
1582 #pragma clang diagnostic push
1583 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1584 UpdateSystemActivity(UsrActivity
);
1585 #pragma clang diagnostic pop
1589 return desktop_orig_wndproc( hwnd
, msg
, wp
, lp
);
1592 /**********************************************************************
1593 * CreateWindow (MACDRV.@)
1595 BOOL CDECL
macdrv_CreateWindow(HWND hwnd
)
1597 if (hwnd
== GetDesktopWindow())
1599 desktop_orig_wndproc
= (WNDPROC
)SetWindowLongPtrW( GetDesktopWindow(),
1600 GWLP_WNDPROC
, (LONG_PTR
)desktop_wndproc_wrapper
);
1602 macdrv_init_clipboard();
1608 /***********************************************************************
1609 * DestroyWindow (MACDRV.@)
1611 void CDECL
macdrv_DestroyWindow(HWND hwnd
)
1613 struct macdrv_win_data
*data
;
1615 TRACE("%p\n", hwnd
);
1617 if (!(data
= get_win_data(hwnd
))) return;
1619 if (hwnd
== GetCapture()) macdrv_SetCapture(0, 0);
1620 if (data
->drag_event
) SetEvent(data
->drag_event
);
1622 destroy_cocoa_window(data
);
1623 destroy_cocoa_view(data
);
1624 if (data
->client_cocoa_view
) macdrv_dispose_view(data
->client_cocoa_view
);
1626 CFDictionaryRemoveValue(win_datas
, hwnd
);
1627 release_win_data(data
);
1628 HeapFree(GetProcessHeap(), 0, data
);
1632 /*****************************************************************
1633 * SetFocus (MACDRV.@)
1635 * Set the Mac focus.
1637 void CDECL
macdrv_SetFocus(HWND hwnd
)
1639 struct macdrv_thread_data
*thread_data
= macdrv_thread_data();
1641 TRACE("%p\n", hwnd
);
1643 if (!thread_data
) return;
1644 thread_data
->dead_key_state
= 0;
1645 set_focus(hwnd
, TRUE
);
1649 /***********************************************************************
1650 * SetLayeredWindowAttributes (MACDRV.@)
1652 * Set transparency attributes for a layered window.
1654 void CDECL
macdrv_SetLayeredWindowAttributes(HWND hwnd
, COLORREF key
, BYTE alpha
, DWORD flags
)
1656 struct macdrv_win_data
*data
= get_win_data(hwnd
);
1658 TRACE("hwnd %p key %#08x alpha %#02x flags %x\n", hwnd
, key
, alpha
, flags
);
1662 data
->layered
= TRUE
;
1663 data
->ulw_layered
= FALSE
;
1664 if (data
->surface
) set_surface_use_alpha(data
->surface
, FALSE
);
1665 if (data
->cocoa_window
)
1667 sync_window_opacity(data
, key
, alpha
, FALSE
, flags
);
1668 /* since layered attributes are now set, can now show the window */
1669 if ((GetWindowLongW(hwnd
, GWL_STYLE
) & WS_VISIBLE
) && !data
->on_screen
)
1672 release_win_data(data
);
1675 FIXME("setting layered attributes on window %p of other process not supported\n", hwnd
);
1679 /*****************************************************************
1680 * SetParent (MACDRV.@)
1682 void CDECL
macdrv_SetParent(HWND hwnd
, HWND parent
, HWND old_parent
)
1684 struct macdrv_win_data
*data
;
1686 TRACE("%p, %p, %p\n", hwnd
, parent
, old_parent
);
1688 if (parent
== old_parent
) return;
1689 if (!(data
= get_win_data(hwnd
))) return;
1691 if (parent
!= GetDesktopWindow()) /* a child window */
1693 if (old_parent
== GetDesktopWindow())
1695 /* destroy the old Mac window */
1696 destroy_cocoa_window(data
);
1697 create_cocoa_view(data
);
1700 set_cocoa_view_parent(data
, parent
);
1702 else /* new top level window */
1704 destroy_cocoa_view(data
);
1705 create_cocoa_window(data
);
1707 release_win_data(data
);
1711 /***********************************************************************
1712 * SetWindowRgn (MACDRV.@)
1714 * Assign specified region to window (for non-rectangular windows)
1716 void CDECL
macdrv_SetWindowRgn(HWND hwnd
, HRGN hrgn
, BOOL redraw
)
1718 struct macdrv_win_data
*data
;
1720 TRACE("%p, %p, %d\n", hwnd
, hrgn
, redraw
);
1722 if ((data
= get_win_data(hwnd
)))
1724 sync_window_region(data
, hrgn
);
1725 release_win_data(data
);
1731 GetWindowThreadProcessId(hwnd
, &procid
);
1732 if (procid
!= GetCurrentProcessId())
1733 SendMessageW(hwnd
, WM_MACDRV_SET_WIN_REGION
, 0, 0);
1738 /***********************************************************************
1739 * SetWindowStyle (MACDRV.@)
1741 * Update the state of the Cocoa window to reflect a style change
1743 void CDECL
macdrv_SetWindowStyle(HWND hwnd
, INT offset
, STYLESTRUCT
*style
)
1745 struct macdrv_win_data
*data
;
1747 TRACE("hwnd %p offset %d styleOld 0x%08x styleNew 0x%08x\n", hwnd
, offset
, style
->styleOld
, style
->styleNew
);
1749 if (hwnd
== GetDesktopWindow()) return;
1750 if (!(data
= get_win_data(hwnd
))) return;
1752 if (data
->cocoa_window
)
1754 DWORD changed
= style
->styleNew
^ style
->styleOld
;
1756 set_cocoa_window_properties(data
);
1758 if (offset
== GWL_EXSTYLE
&& (changed
& WS_EX_LAYERED
)) /* changing WS_EX_LAYERED resets attributes */
1760 data
->layered
= FALSE
;
1761 data
->ulw_layered
= FALSE
;
1762 sync_window_opacity(data
, 0, 0, FALSE
, 0);
1763 if (data
->surface
) set_surface_use_alpha(data
->surface
, FALSE
);
1766 if (offset
== GWL_EXSTYLE
&& (changed
& WS_EX_LAYOUTRTL
))
1767 sync_window_region(data
, (HRGN
)1);
1770 release_win_data(data
);
1774 /*****************************************************************
1775 * SetWindowText (MACDRV.@)
1777 void CDECL
macdrv_SetWindowText(HWND hwnd
, LPCWSTR text
)
1781 TRACE("%p, %s\n", hwnd
, debugstr_w(text
));
1783 if ((win
= macdrv_get_cocoa_window(hwnd
, FALSE
)))
1784 macdrv_set_cocoa_window_title(win
, text
, strlenW(text
));
1788 /***********************************************************************
1789 * ShowWindow (MACDRV.@)
1791 UINT CDECL
macdrv_ShowWindow(HWND hwnd
, INT cmd
, RECT
*rect
, UINT swp
)
1793 struct macdrv_thread_data
*thread_data
= macdrv_thread_data();
1794 struct macdrv_win_data
*data
= get_win_data(hwnd
);
1797 TRACE("win %p/%p cmd %d at %s flags %08x\n",
1798 hwnd
, data
? data
->cocoa_window
: NULL
, cmd
, wine_dbgstr_rect(rect
), swp
);
1800 if (!data
|| !data
->cocoa_window
) goto done
;
1801 if (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
1803 if (rect
->left
!= -32000 || rect
->top
!= -32000)
1805 OffsetRect(rect
, -32000 - rect
->left
, -32000 - rect
->top
);
1806 swp
&= ~(SWP_NOMOVE
| SWP_NOCLIENTMOVE
);
1810 if (!data
->on_screen
) goto done
;
1812 /* only fetch the new rectangle if the ShowWindow was a result of an external event */
1814 if (!thread_data
->current_event
|| thread_data
->current_event
->window
!= data
->cocoa_window
)
1817 if (thread_data
->current_event
->type
!= WINDOW_FRAME_CHANGED
&&
1818 thread_data
->current_event
->type
!= WINDOW_DID_UNMINIMIZE
)
1821 macdrv_get_cocoa_window_frame(data
->cocoa_window
, &frame
);
1822 *rect
= rect_from_cgrect(frame
);
1823 macdrv_mac_to_window_rect(data
, rect
);
1824 TRACE("rect %s -> %s\n", wine_dbgstr_cgrect(frame
), wine_dbgstr_rect(rect
));
1825 swp
&= ~(SWP_NOMOVE
| SWP_NOCLIENTMOVE
| SWP_NOSIZE
| SWP_NOCLIENTSIZE
);
1828 release_win_data(data
);
1833 /***********************************************************************
1834 * SysCommand (MACDRV.@)
1836 * Perform WM_SYSCOMMAND handling.
1838 LRESULT CDECL
macdrv_SysCommand(HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1840 struct macdrv_win_data
*data
;
1842 WPARAM command
= wparam
& 0xfff0;
1844 TRACE("%p, %x, %lx\n", hwnd
, (unsigned)wparam
, lparam
);
1846 if (!(data
= get_win_data(hwnd
))) goto done
;
1847 if (!data
->cocoa_window
|| !data
->on_screen
) goto done
;
1849 /* prevent a simple ALT press+release from activating the system menu,
1850 as that can get confusing */
1851 if (command
== SC_KEYMENU
&& !(WCHAR
)lparam
&& !GetMenu(hwnd
) &&
1852 (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_SYSMENU
))
1854 TRACE("ignoring SC_KEYMENU wp %lx lp %lx\n", wparam
, lparam
);
1858 if (command
== SC_MOVE
)
1860 release_win_data(data
);
1861 return move_window(hwnd
, wparam
);
1865 release_win_data(data
);
1870 /***********************************************************************
1871 * UpdateLayeredWindow (MACDRV.@)
1873 BOOL CDECL
macdrv_UpdateLayeredWindow(HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
,
1874 const RECT
*window_rect
)
1876 struct window_surface
*surface
;
1877 struct macdrv_win_data
*data
;
1878 BLENDFUNCTION blend
= { AC_SRC_OVER
, 0, 255, 0 };
1880 char buffer
[FIELD_OFFSET(BITMAPINFO
, bmiColors
[256])];
1881 BITMAPINFO
*bmi
= (BITMAPINFO
*)buffer
;
1882 void *src_bits
, *dst_bits
;
1883 RECT rect
, src_rect
;
1888 if (!(data
= get_win_data(hwnd
))) return FALSE
;
1890 data
->layered
= TRUE
;
1891 data
->ulw_layered
= TRUE
;
1893 rect
= *window_rect
;
1894 OffsetRect(&rect
, -window_rect
->left
, -window_rect
->top
);
1896 surface
= data
->surface
;
1897 if (!surface
|| !EqualRect(&surface
->rect
, &rect
))
1899 data
->surface
= create_surface(data
->cocoa_window
, &rect
, NULL
, TRUE
);
1900 set_window_surface(data
->cocoa_window
, data
->surface
);
1901 if (surface
) window_surface_release(surface
);
1902 surface
= data
->surface
;
1903 if (data
->unminimized_surface
)
1905 window_surface_release(data
->unminimized_surface
);
1906 data
->unminimized_surface
= NULL
;
1909 else set_surface_use_alpha(surface
, TRUE
);
1911 if (surface
) window_surface_add_ref(surface
);
1912 release_win_data(data
);
1914 if (!surface
) return FALSE
;
1917 window_surface_release(surface
);
1921 if (info
->dwFlags
& ULW_ALPHA
)
1923 /* Apply SourceConstantAlpha via window alpha, not blend. */
1924 alpha
= info
->pblend
->SourceConstantAlpha
;
1925 blend
= *info
->pblend
;
1926 blend
.SourceConstantAlpha
= 0xff;
1931 dst_bits
= surface
->funcs
->get_info(surface
, bmi
);
1933 if (!(dib
= CreateDIBSection(info
->hdcDst
, bmi
, DIB_RGB_COLORS
, &src_bits
, NULL
, 0))) goto done
;
1934 if (!(hdc
= CreateCompatibleDC(0))) goto done
;
1936 SelectObject(hdc
, dib
);
1939 IntersectRect(&rect
, &rect
, info
->prcDirty
);
1940 surface
->funcs
->lock(surface
);
1941 memcpy(src_bits
, dst_bits
, bmi
->bmiHeader
.biSizeImage
);
1942 surface
->funcs
->unlock(surface
);
1943 PatBlt(hdc
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, BLACKNESS
);
1946 if (info
->pptSrc
) OffsetRect( &src_rect
, info
->pptSrc
->x
, info
->pptSrc
->y
);
1947 DPtoLP( info
->hdcSrc
, (POINT
*)&src_rect
, 2 );
1949 if (!(ret
= GdiAlphaBlend(hdc
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
1950 info
->hdcSrc
, src_rect
.left
, src_rect
.top
,
1951 src_rect
.right
- src_rect
.left
, src_rect
.bottom
- src_rect
.top
,
1955 if ((data
= get_win_data(hwnd
)))
1957 if (surface
== data
->surface
)
1959 surface
->funcs
->lock(surface
);
1960 memcpy(dst_bits
, src_bits
, bmi
->bmiHeader
.biSizeImage
);
1961 add_bounds_rect(surface
->funcs
->get_bounds(surface
), &rect
);
1962 surface
->funcs
->unlock(surface
);
1963 surface
->funcs
->flush(surface
);
1966 /* The ULW flags are a superset of the LWA flags. */
1967 sync_window_opacity(data
, info
->crKey
, alpha
, TRUE
, info
->dwFlags
);
1969 release_win_data(data
);
1973 window_surface_release(surface
);
1974 if (hdc
) DeleteDC(hdc
);
1975 if (dib
) DeleteObject(dib
);
1980 /**********************************************************************
1981 * WindowMessage (MACDRV.@)
1983 LRESULT CDECL
macdrv_WindowMessage(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1985 struct macdrv_win_data
*data
;
1987 TRACE("%p, %u, %u, %lu\n", hwnd
, msg
, (unsigned)wp
, lp
);
1991 case WM_MACDRV_SET_WIN_REGION
:
1992 if ((data
= get_win_data(hwnd
)))
1994 sync_window_region(data
, (HRGN
)1);
1995 release_win_data(data
);
1998 case WM_MACDRV_UPDATE_DESKTOP_RECT
:
1999 if (hwnd
== GetDesktopWindow())
2001 CGRect new_desktop_rect
;
2002 RECT current_desktop_rect
;
2004 macdrv_reset_device_metrics();
2005 new_desktop_rect
= macdrv_get_desktop_rect();
2006 if (!GetWindowRect(hwnd
, ¤t_desktop_rect
) ||
2007 !CGRectEqualToRect(cgrect_from_rect(current_desktop_rect
), new_desktop_rect
))
2009 SendMessageTimeoutW(HWND_BROADCAST
, WM_MACDRV_RESET_DEVICE_METRICS
, 0, 0,
2010 SMTO_ABORTIFHUNG
, 2000, NULL
);
2011 SetWindowPos(hwnd
, 0, CGRectGetMinX(new_desktop_rect
), CGRectGetMinY(new_desktop_rect
),
2012 CGRectGetWidth(new_desktop_rect
), CGRectGetHeight(new_desktop_rect
),
2013 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_DEFERERASE
);
2014 SendMessageTimeoutW(HWND_BROADCAST
, WM_MACDRV_DISPLAYCHANGE
, wp
, lp
,
2015 SMTO_ABORTIFHUNG
, 2000, NULL
);
2019 case WM_MACDRV_RESET_DEVICE_METRICS
:
2020 macdrv_reset_device_metrics();
2022 case WM_MACDRV_DISPLAYCHANGE
:
2023 macdrv_reassert_window_position(hwnd
);
2024 SendMessageW(hwnd
, WM_DISPLAYCHANGE
, wp
, lp
);
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
);
2032 FIXME("unrecognized window msg %x hwnd %p wp %lx lp %lx\n", msg
, hwnd
, wp
, lp
);
2037 static inline RECT
get_surface_rect(const RECT
*visible_rect
)
2040 RECT desktop_rect
= rect_from_cgrect(macdrv_get_desktop_rect());
2042 IntersectRect(&rect
, visible_rect
, &desktop_rect
);
2043 OffsetRect(&rect
, -visible_rect
->left
, -visible_rect
->top
);
2046 rect
.right
= max(rect
.left
+ 128, (rect
.right
+ 127) & ~127);
2047 rect
.bottom
= max(rect
.top
+ 128, (rect
.bottom
+ 127) & ~127);
2052 /***********************************************************************
2053 * WindowPosChanging (MACDRV.@)
2055 BOOL CDECL
macdrv_WindowPosChanging(HWND hwnd
, HWND insert_after
, UINT swp_flags
,
2056 const RECT
*window_rect
, const RECT
*client_rect
,
2057 RECT
*visible_rect
, struct window_surface
**surface
)
2059 struct macdrv_win_data
*data
= get_win_data(hwnd
);
2060 DWORD style
= GetWindowLongW(hwnd
, GWL_STYLE
);
2063 TRACE("%p after %p swp %04x window %s client %s visible %s surface %p\n", hwnd
, insert_after
,
2064 swp_flags
, wine_dbgstr_rect(window_rect
), wine_dbgstr_rect(client_rect
),
2065 wine_dbgstr_rect(visible_rect
), surface
);
2067 if (!data
&& !(data
= macdrv_create_win_data(hwnd
, window_rect
, client_rect
))) return TRUE
;
2069 *visible_rect
= *window_rect
;
2070 macdrv_window_to_mac_rect(data
, style
, visible_rect
, window_rect
, client_rect
);
2071 TRACE("visible_rect %s -> %s\n", wine_dbgstr_rect(window_rect
),
2072 wine_dbgstr_rect(visible_rect
));
2074 /* create the window surface if necessary */
2075 if (!data
->cocoa_window
) goto done
;
2076 if (swp_flags
& SWP_HIDEWINDOW
) goto done
;
2077 if (data
->ulw_layered
) goto done
;
2079 if (*surface
) window_surface_release(*surface
);
2082 surface_rect
= get_surface_rect(visible_rect
);
2085 if (EqualRect(&data
->surface
->rect
, &surface_rect
))
2087 /* existing surface is good enough */
2088 surface_clip_to_visible_rect(data
->surface
, visible_rect
);
2089 window_surface_add_ref(data
->surface
);
2090 *surface
= data
->surface
;
2094 else if (!(swp_flags
& SWP_SHOWWINDOW
) && !(style
& WS_VISIBLE
)) goto done
;
2096 *surface
= create_surface(data
->cocoa_window
, &surface_rect
, data
->surface
, FALSE
);
2099 release_win_data(data
);
2104 /***********************************************************************
2105 * WindowPosChanged (MACDRV.@)
2107 void CDECL
macdrv_WindowPosChanged(HWND hwnd
, HWND insert_after
, UINT swp_flags
,
2108 const RECT
*window_rect
, const RECT
*client_rect
,
2109 const RECT
*visible_rect
, const RECT
*valid_rects
,
2110 struct window_surface
*surface
)
2112 struct macdrv_thread_data
*thread_data
;
2113 struct macdrv_win_data
*data
;
2114 DWORD new_style
= GetWindowLongW(hwnd
, GWL_STYLE
);
2115 RECT old_window_rect
, old_whole_rect
, old_client_rect
;
2117 if (!(data
= get_win_data(hwnd
))) return;
2119 thread_data
= macdrv_thread_data();
2121 old_window_rect
= data
->window_rect
;
2122 old_whole_rect
= data
->whole_rect
;
2123 old_client_rect
= data
->client_rect
;
2124 data
->window_rect
= *window_rect
;
2125 data
->whole_rect
= *visible_rect
;
2126 data
->client_rect
= *client_rect
;
2127 if (data
->cocoa_window
&& !data
->ulw_layered
)
2129 if (surface
) window_surface_add_ref(surface
);
2130 if (new_style
& WS_MINIMIZE
)
2132 if (!data
->unminimized_surface
&& data
->surface
)
2134 data
->unminimized_surface
= data
->surface
;
2135 window_surface_add_ref(data
->unminimized_surface
);
2140 set_window_surface(data
->cocoa_window
, surface
);
2141 if (data
->unminimized_surface
)
2143 window_surface_release(data
->unminimized_surface
);
2144 data
->unminimized_surface
= NULL
;
2147 if (data
->surface
) window_surface_release(data
->surface
);
2148 data
->surface
= surface
;
2151 TRACE("win %p/%p window %s whole %s client %s style %08x flags %08x surface %p\n",
2152 hwnd
, data
->cocoa_window
, wine_dbgstr_rect(window_rect
),
2153 wine_dbgstr_rect(visible_rect
), wine_dbgstr_rect(client_rect
),
2154 new_style
, swp_flags
, surface
);
2156 if (!IsRectEmpty(&valid_rects
[0]))
2158 macdrv_window window
= data
->cocoa_window
;
2159 int x_offset
= old_whole_rect
.left
- data
->whole_rect
.left
;
2160 int y_offset
= old_whole_rect
.top
- data
->whole_rect
.top
;
2162 /* if all that happened is that the whole window moved, copy everything */
2163 if (!(swp_flags
& SWP_FRAMECHANGED
) &&
2164 old_whole_rect
.right
- data
->whole_rect
.right
== x_offset
&&
2165 old_whole_rect
.bottom
- data
->whole_rect
.bottom
== y_offset
&&
2166 old_client_rect
.left
- data
->client_rect
.left
== x_offset
&&
2167 old_client_rect
.right
- data
->client_rect
.right
== x_offset
&&
2168 old_client_rect
.top
- data
->client_rect
.top
== y_offset
&&
2169 old_client_rect
.bottom
- data
->client_rect
.bottom
== y_offset
&&
2170 EqualRect(&valid_rects
[0], &data
->client_rect
))
2172 /* A Cocoa window's bits are moved automatically */
2173 if (!window
&& (x_offset
!= 0 || y_offset
!= 0))
2175 release_win_data(data
);
2176 move_window_bits(hwnd
, window
, &old_whole_rect
, visible_rect
,
2177 &old_client_rect
, client_rect
, window_rect
);
2178 if (!(data
= get_win_data(hwnd
))) return;
2183 release_win_data(data
);
2184 move_window_bits(hwnd
, window
, &valid_rects
[1], &valid_rects
[0],
2185 &old_client_rect
, client_rect
, window_rect
);
2186 if (!(data
= get_win_data(hwnd
))) return;
2190 sync_gl_view(data
, &old_whole_rect
, &old_client_rect
);
2192 if (!data
->cocoa_window
&& !data
->cocoa_view
) goto done
;
2194 if (data
->on_screen
)
2196 if ((swp_flags
& SWP_HIDEWINDOW
) && !(new_style
& WS_VISIBLE
))
2200 /* check if we are currently processing an event relevant to this window */
2201 if (thread_data
&& thread_data
->current_event
&&
2202 data
->cocoa_window
&& thread_data
->current_event
->window
== data
->cocoa_window
&&
2203 (thread_data
->current_event
->type
== WINDOW_FRAME_CHANGED
||
2204 thread_data
->current_event
->type
== WINDOW_DID_UNMINIMIZE
))
2206 if (thread_data
->current_event
->type
== WINDOW_FRAME_CHANGED
)
2207 sync_client_view_position(data
);
2211 sync_window_position(data
, swp_flags
, &old_window_rect
, &old_whole_rect
);
2212 if (data
->cocoa_window
)
2213 set_cocoa_window_properties(data
);
2216 if (new_style
& WS_VISIBLE
)
2218 if (data
->cocoa_window
)
2220 if (!data
->on_screen
|| (swp_flags
& (SWP_FRAMECHANGED
|SWP_STATECHANGED
)))
2221 set_cocoa_window_properties(data
);
2223 /* layered windows are not shown until their attributes are set */
2224 if (!data
->on_screen
&&
2225 (data
->layered
|| !(GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_LAYERED
)))
2228 else if (!data
->on_screen
)
2233 release_win_data(data
);
2237 /***********************************************************************
2238 * macdrv_window_close_requested
2240 * Handler for WINDOW_CLOSE_REQUESTED events.
2242 void macdrv_window_close_requested(HWND hwnd
)
2246 if (GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
)
2248 TRACE("not closing win %p class style CS_NOCLOSE\n", hwnd
);
2252 sysmenu
= GetSystemMenu(hwnd
, FALSE
);
2255 UINT state
= GetMenuState(sysmenu
, SC_CLOSE
, MF_BYCOMMAND
);
2256 if (state
== 0xFFFFFFFF || (state
& (MF_DISABLED
| MF_GRAYED
)))
2258 TRACE("not closing win %p menu state 0x%08x\n", hwnd
, state
);
2263 perform_window_command(hwnd
, 0, 0, SC_CLOSE
, HTCLOSE
);
2267 /***********************************************************************
2268 * macdrv_window_frame_changed
2270 * Handler for WINDOW_FRAME_CHANGED events.
2272 void macdrv_window_frame_changed(HWND hwnd
, const macdrv_event
*event
)
2274 struct macdrv_win_data
*data
;
2277 UINT flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
2282 if (!(data
= get_win_data(hwnd
))) return;
2283 if (!data
->on_screen
|| data
->minimized
)
2285 release_win_data(data
);
2291 parent
= GetAncestor(hwnd
, GA_PARENT
);
2293 TRACE("win %p/%p new Cocoa frame %s fullscreen %d in_resize %d\n", hwnd
, data
->cocoa_window
,
2294 wine_dbgstr_cgrect(event
->window_frame_changed
.frame
),
2295 event
->window_frame_changed
.fullscreen
, event
->window_frame_changed
.in_resize
);
2297 rect
= rect_from_cgrect(event
->window_frame_changed
.frame
);
2298 macdrv_mac_to_window_rect(data
, &rect
);
2299 MapWindowPoints(0, parent
, (POINT
*)&rect
, 2);
2301 width
= rect
.right
- rect
.left
;
2302 height
= rect
.bottom
- rect
.top
;
2304 if (data
->window_rect
.left
== rect
.left
&& data
->window_rect
.top
== rect
.top
)
2305 flags
|= SWP_NOMOVE
;
2307 TRACE("%p moving from (%d,%d) to (%d,%d)\n", hwnd
, data
->window_rect
.left
,
2308 data
->window_rect
.top
, rect
.left
, rect
.top
);
2310 if ((data
->window_rect
.right
- data
->window_rect
.left
== width
&&
2311 data
->window_rect
.bottom
- data
->window_rect
.top
== height
) ||
2312 (IsRectEmpty(&data
->window_rect
) && width
== 1 && height
== 1))
2313 flags
|= SWP_NOSIZE
;
2315 TRACE("%p resizing from (%dx%d) to (%dx%d)\n", hwnd
, data
->window_rect
.right
- data
->window_rect
.left
,
2316 data
->window_rect
.bottom
- data
->window_rect
.top
, width
, height
);
2318 being_dragged
= data
->drag_event
!= NULL
;
2319 release_win_data(data
);
2321 if (event
->window_frame_changed
.fullscreen
)
2322 flags
|= SWP_NOSENDCHANGING
;
2323 if (!(flags
& SWP_NOSIZE
) || !(flags
& SWP_NOMOVE
))
2325 int send_sizemove
= !event
->window_frame_changed
.in_resize
&& !being_dragged
&& !event
->window_frame_changed
.skip_size_move_loop
;
2327 SendMessageW(hwnd
, WM_ENTERSIZEMOVE
, 0, 0);
2328 SetWindowPos(hwnd
, 0, rect
.left
, rect
.top
, width
, height
, flags
);
2330 SendMessageW(hwnd
, WM_EXITSIZEMOVE
, 0, 0);
2335 /***********************************************************************
2336 * macdrv_window_got_focus
2338 * Handler for WINDOW_GOT_FOCUS events.
2340 void macdrv_window_got_focus(HWND hwnd
, const macdrv_event
*event
)
2342 LONG style
= GetWindowLongW(hwnd
, GWL_STYLE
);
2346 TRACE("win %p/%p serial %lu enabled %d visible %d style %08x focus %p active %p fg %p\n",
2347 hwnd
, event
->window
, event
->window_got_focus
.serial
, IsWindowEnabled(hwnd
),
2348 IsWindowVisible(hwnd
), style
, GetFocus(), GetActiveWindow(), GetForegroundWindow());
2350 if (can_window_become_foreground(hwnd
) && !(style
& WS_MINIMIZE
))
2352 /* simulate a mouse click on the menu to find out
2353 * whether the window wants to be activated */
2354 LRESULT ma
= SendMessageW(hwnd
, WM_MOUSEACTIVATE
,
2355 (WPARAM
)GetAncestor(hwnd
, GA_ROOT
),
2356 MAKELONG(HTMENU
, WM_LBUTTONDOWN
));
2357 if (ma
!= MA_NOACTIVATEANDEAT
&& ma
!= MA_NOACTIVATE
)
2359 TRACE("setting foreground window to %p\n", hwnd
);
2360 SetForegroundWindow(hwnd
);
2365 TRACE("win %p/%p rejecting focus\n", hwnd
, event
->window
);
2366 macdrv_window_rejected_focus(event
);
2370 /***********************************************************************
2371 * macdrv_window_lost_focus
2373 * Handler for WINDOW_LOST_FOCUS events.
2375 void macdrv_window_lost_focus(HWND hwnd
, const macdrv_event
*event
)
2379 TRACE("win %p/%p fg %p\n", hwnd
, event
->window
, GetForegroundWindow());
2381 if (hwnd
== GetForegroundWindow())
2383 SendMessageW(hwnd
, WM_CANCELMODE
, 0, 0);
2384 if (hwnd
== GetForegroundWindow())
2385 SetForegroundWindow(GetDesktopWindow());
2390 /***********************************************************************
2391 * macdrv_app_activated
2393 * Handler for APP_ACTIVATED events.
2395 void macdrv_app_activated(void)
2398 macdrv_UpdateClipboard();
2402 /***********************************************************************
2403 * macdrv_app_deactivated
2405 * Handler for APP_DEACTIVATED events.
2407 void macdrv_app_deactivated(void)
2411 if (GetActiveWindow() == GetForegroundWindow())
2413 TRACE("setting fg to desktop\n");
2414 SetForegroundWindow(GetDesktopWindow());
2419 /***********************************************************************
2420 * macdrv_window_maximize_requested
2422 * Handler for WINDOW_MAXIMIZE_REQUESTED events.
2424 void macdrv_window_maximize_requested(HWND hwnd
)
2426 perform_window_command(hwnd
, WS_MAXIMIZEBOX
, WS_MAXIMIZE
, SC_MAXIMIZE
, HTMAXBUTTON
);
2430 /***********************************************************************
2431 * macdrv_window_minimize_requested
2433 * Handler for WINDOW_MINIMIZE_REQUESTED events.
2435 void macdrv_window_minimize_requested(HWND hwnd
)
2437 perform_window_command(hwnd
, WS_MINIMIZEBOX
, WS_MINIMIZE
, SC_MINIMIZE
, HTMINBUTTON
);
2441 /***********************************************************************
2442 * macdrv_window_did_minimize
2444 * Handler for WINDOW_DID_MINIMIZE events.
2446 void macdrv_window_did_minimize(HWND hwnd
)
2448 TRACE("win %p\n", hwnd
);
2450 /* If all our windows are minimized, disable cursor clipping. */
2451 if (!macdrv_is_any_wine_window_visible())
2456 /***********************************************************************
2457 * macdrv_window_did_unminimize
2459 * Handler for WINDOW_DID_UNMINIMIZE events.
2461 void macdrv_window_did_unminimize(HWND hwnd
)
2463 struct macdrv_win_data
*data
;
2466 TRACE("win %p\n", hwnd
);
2468 if (!(data
= get_win_data(hwnd
))) return;
2469 if (!data
->minimized
) goto done
;
2471 style
= GetWindowLongW(hwnd
, GWL_STYLE
);
2473 data
->minimized
= FALSE
;
2474 if ((style
& (WS_MINIMIZE
| WS_VISIBLE
)) == (WS_MINIMIZE
| WS_VISIBLE
))
2476 TRACE("restoring win %p/%p\n", hwnd
, data
->cocoa_window
);
2477 release_win_data(data
);
2478 SetActiveWindow(hwnd
);
2479 SendMessageW(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
2483 TRACE("not restoring win %p/%p style %08x\n", hwnd
, data
->cocoa_window
, style
);
2486 release_win_data(data
);
2490 /***********************************************************************
2491 * macdrv_window_brought_forward
2493 * Handler for WINDOW_BROUGHT_FORWARD events.
2495 void macdrv_window_brought_forward(HWND hwnd
)
2497 TRACE("win %p\n", hwnd
);
2498 SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
2502 /***********************************************************************
2503 * macdrv_window_resize_ended
2505 * Handler for WINDOW_RESIZE_ENDED events.
2507 void macdrv_window_resize_ended(HWND hwnd
)
2509 TRACE("hwnd %p\n", hwnd
);
2510 SendMessageW(hwnd
, WM_EXITSIZEMOVE
, 0, 0);
2514 /***********************************************************************
2515 * macdrv_window_restore_requested
2517 * Handler for WINDOW_RESTORE_REQUESTED events. This is specifically
2518 * for restoring from maximized, not from minimized.
2520 void macdrv_window_restore_requested(HWND hwnd
, const macdrv_event
*event
)
2522 if (event
->window_restore_requested
.keep_frame
&& hwnd
)
2524 DWORD style
= GetWindowLongW(hwnd
, GWL_STYLE
);
2525 struct macdrv_win_data
*data
;
2527 if ((style
& WS_MAXIMIZE
) && (style
& WS_VISIBLE
) && (data
= get_win_data(hwnd
)))
2530 HWND parent
= GetAncestor(hwnd
, GA_PARENT
);
2532 rect
= rect_from_cgrect(event
->window_restore_requested
.frame
);
2533 macdrv_mac_to_window_rect(data
, &rect
);
2534 MapWindowPoints(0, parent
, (POINT
*)&rect
, 2);
2536 release_win_data(data
);
2538 SetInternalWindowPos(hwnd
, SW_SHOW
, &rect
, NULL
);
2542 perform_window_command(hwnd
, WS_MAXIMIZE
, 0, SC_RESTORE
, HTMAXBUTTON
);
2546 /***********************************************************************
2547 * macdrv_window_drag_begin
2549 * Handler for WINDOW_DRAG_BEGIN events.
2551 void macdrv_window_drag_begin(HWND hwnd
, const macdrv_event
*event
)
2553 DWORD style
= GetWindowLongW(hwnd
, GWL_STYLE
);
2554 struct macdrv_win_data
*data
;
2555 HANDLE drag_event
= NULL
;
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 drag_event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2568 if (!drag_event
) 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
) && GetForegroundWindow() != hwnd
)
2575 /* ask whether the window wants to be activated */
2576 LRESULT ma
= SendMessageW(hwnd
, WM_MOUSEACTIVATE
, (WPARAM
)GetAncestor(hwnd
, GA_ROOT
),
2577 MAKELONG(HTCAPTION
, WM_LBUTTONDOWN
));
2578 if (ma
!= MA_NOACTIVATEANDEAT
&& ma
!= MA_NOACTIVATE
)
2580 TRACE("setting foreground window to %p\n", hwnd
);
2581 SetForegroundWindow(hwnd
);
2586 SendMessageW(hwnd
, WM_ENTERSIZEMOVE
, 0, 0);
2591 while (!PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
))
2593 DWORD result
= MsgWaitForMultipleObjectsEx(1, &drag_event
, INFINITE
, QS_ALLINPUT
, MWMO_INPUTAVAILABLE
);
2594 if (result
== WAIT_OBJECT_0
)
2603 if (msg
.message
== WM_QUIT
)
2606 if (!CallMsgFilterW(&msg
, MSGF_SIZE
) && msg
.message
!= WM_KEYDOWN
&&
2607 msg
.message
!= WM_MOUSEMOVE
&& msg
.message
!= WM_LBUTTONDOWN
&& msg
.message
!= WM_LBUTTONUP
)
2609 TranslateMessage(&msg
);
2610 DispatchMessageW(&msg
);
2614 SendMessageW(hwnd
, WM_EXITSIZEMOVE
, 0, 0);
2618 if ((data
= get_win_data(hwnd
)))
2619 data
->drag_event
= NULL
;
2622 release_win_data(data
);
2623 if (drag_event
) CloseHandle(drag_event
);
2627 /***********************************************************************
2628 * macdrv_window_drag_end
2630 * Handler for WINDOW_DRAG_END events.
2632 void macdrv_window_drag_end(HWND hwnd
)
2634 struct macdrv_win_data
*data
;
2636 TRACE("win %p\n", hwnd
);
2638 if (!(data
= get_win_data(hwnd
))) return;
2639 if (data
->drag_event
)
2640 SetEvent(data
->drag_event
);
2641 release_win_data(data
);
2645 /***********************************************************************
2646 * macdrv_reassert_window_position
2648 * Handler for REASSERT_WINDOW_POSITION events.
2650 void macdrv_reassert_window_position(HWND hwnd
)
2652 struct macdrv_win_data
*data
= get_win_data(hwnd
);
2655 if (data
->cocoa_window
&& data
->on_screen
)
2656 sync_window_position(data
, SWP_NOZORDER
| SWP_NOACTIVATE
, NULL
, NULL
);
2657 release_win_data(data
);
2673 static BOOL CALLBACK
get_process_windows(HWND hwnd
, LPARAM lp
)
2675 struct quit_info
*qi
= (struct quit_info
*)lp
;
2678 GetWindowThreadProcessId(hwnd
, &pid
);
2679 if (pid
== GetCurrentProcessId())
2681 if (qi
->count
>= qi
->capacity
)
2683 UINT new_cap
= qi
->capacity
* 2;
2684 HWND
*new_wins
= HeapReAlloc(GetProcessHeap(), 0, qi
->wins
,
2685 new_cap
* sizeof(*qi
->wins
));
2686 if (!new_wins
) return FALSE
;
2687 qi
->wins
= new_wins
;
2688 qi
->capacity
= new_cap
;
2691 qi
->wins
[qi
->count
++] = hwnd
;
2698 static void CALLBACK
quit_callback(HWND hwnd
, UINT msg
, ULONG_PTR data
, LRESULT result
)
2700 struct quit_info
*qi
= (struct quit_info
*)data
;
2704 if (msg
== WM_QUERYENDSESSION
)
2706 TRACE("got WM_QUERYENDSESSION result %ld from win %p (%u of %u done)\n", result
,
2707 hwnd
, qi
->done
, qi
->count
);
2709 if (!result
&& !IsWindow(hwnd
))
2711 TRACE("win %p no longer exists; ignoring apparent refusal\n", hwnd
);
2715 if (!result
&& qi
->result
)
2719 /* On the first FALSE from WM_QUERYENDSESSION, we already know the
2720 ultimate reply. Might as well tell Cocoa now. */
2724 TRACE("giving quit reply %d\n", qi
->result
);
2725 macdrv_quit_reply(qi
->result
);
2729 if (qi
->done
>= qi
->count
)
2734 for (i
= 0; i
< qi
->count
; i
++)
2736 TRACE("sending WM_ENDSESSION to win %p result %d flags 0x%08x\n", qi
->wins
[i
],
2737 qi
->result
, qi
->flags
);
2738 if (!SendMessageCallbackW(qi
->wins
[i
], WM_ENDSESSION
, qi
->result
, qi
->flags
,
2739 quit_callback
, (ULONG_PTR
)qi
))
2741 WARN("failed to send WM_ENDSESSION to win %p; error 0x%08x\n",
2742 qi
->wins
[i
], GetLastError());
2743 quit_callback(qi
->wins
[i
], WM_ENDSESSION
, (ULONG_PTR
)qi
, 0);
2748 else /* WM_ENDSESSION */
2750 TRACE("finished WM_ENDSESSION for win %p (%u of %u done)\n", hwnd
, qi
->done
, qi
->count
);
2752 if (qi
->done
>= qi
->count
)
2756 TRACE("giving quit reply %d\n", qi
->result
);
2757 macdrv_quit_reply(qi
->result
);
2760 TRACE("%sterminating process\n", qi
->result
? "" : "not ");
2762 TerminateProcess(GetCurrentProcess(), 0);
2764 HeapFree(GetProcessHeap(), 0, qi
->wins
);
2765 HeapFree(GetProcessHeap(), 0, qi
);
2771 /***********************************************************************
2772 * macdrv_app_quit_requested
2774 * Handler for APP_QUIT_REQUESTED events.
2776 void macdrv_app_quit_requested(const macdrv_event
*event
)
2778 struct quit_info
*qi
;
2781 TRACE("reason %d\n", event
->app_quit_requested
.reason
);
2783 qi
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qi
));
2788 qi
->wins
= HeapAlloc(GetProcessHeap(), 0, qi
->capacity
* sizeof(*qi
->wins
));
2789 qi
->count
= qi
->done
= 0;
2791 if (!qi
->wins
|| !EnumWindows(get_process_windows
, (LPARAM
)qi
))
2794 switch (event
->app_quit_requested
.reason
)
2796 case QUIT_REASON_LOGOUT
:
2798 qi
->flags
= ENDSESSION_LOGOFF
;
2800 case QUIT_REASON_RESTART
:
2801 case QUIT_REASON_SHUTDOWN
:
2807 qi
->replied
= FALSE
;
2809 for (i
= 0; i
< qi
->count
; i
++)
2811 TRACE("sending WM_QUERYENDSESSION to win %p\n", qi
->wins
[i
]);
2812 if (!SendMessageCallbackW(qi
->wins
[i
], WM_QUERYENDSESSION
, 0, qi
->flags
,
2813 quit_callback
, (ULONG_PTR
)qi
))
2815 DWORD error
= GetLastError();
2816 BOOL invalid
= (error
== ERROR_INVALID_WINDOW_HANDLE
);
2818 TRACE("failed to send WM_QUERYENDSESSION to win %p because it's invalid; assuming success\n",
2821 WARN("failed to send WM_QUERYENDSESSION to win %p; error 0x%08x; assuming refusal\n",
2822 qi
->wins
[i
], error
);
2823 quit_callback(qi
->wins
[i
], WM_QUERYENDSESSION
, (ULONG_PTR
)qi
, invalid
);
2827 /* quit_callback() will clean up qi */
2831 WARN("failed to allocate window list\n");
2834 HeapFree(GetProcessHeap(), 0, qi
->wins
);
2835 HeapFree(GetProcessHeap(), 0, qi
);
2837 macdrv_quit_reply(FALSE
);
2841 /***********************************************************************
2844 * Handler for QUERY_RESIZE_SIZE query.
2846 BOOL
query_resize_size(HWND hwnd
, macdrv_query
*query
)
2848 struct macdrv_win_data
*data
= get_win_data(hwnd
);
2849 RECT rect
= rect_from_cgrect(query
->resize_size
.rect
);
2853 if (!data
) return FALSE
;
2855 macdrv_mac_to_window_rect(data
, &rect
);
2857 if (query
->resize_size
.from_left
)
2859 if (query
->resize_size
.from_top
)
2860 corner
= WMSZ_TOPLEFT
;
2862 corner
= WMSZ_BOTTOMLEFT
;
2864 else if (query
->resize_size
.from_top
)
2865 corner
= WMSZ_TOPRIGHT
;
2867 corner
= WMSZ_BOTTOMRIGHT
;
2869 if (SendMessageW(hwnd
, WM_SIZING
, corner
, (LPARAM
)&rect
))
2871 macdrv_window_to_mac_rect(data
, GetWindowLongW(hwnd
, GWL_STYLE
), &rect
,
2872 &data
->window_rect
, &data
->client_rect
);
2873 query
->resize_size
.rect
= cgrect_from_rect(rect
);
2877 release_win_data(data
);
2882 /***********************************************************************
2883 * query_resize_start
2885 * Handler for QUERY_RESIZE_START query.
2887 BOOL
query_resize_start(HWND hwnd
)
2889 TRACE("hwnd %p\n", hwnd
);
2893 sync_window_min_max_info(hwnd
);
2894 SendMessageW(hwnd
, WM_ENTERSIZEMOVE
, 0, 0);
2900 /***********************************************************************
2901 * query_min_max_info
2903 * Handler for QUERY_MIN_MAX_INFO query.
2905 BOOL
query_min_max_info(HWND hwnd
)
2907 TRACE("hwnd %p\n", hwnd
);
2908 sync_window_min_max_info(hwnd
);