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
28 #include "wine/unicode.h"
29 #include "wine/server.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(macdrv
);
34 static CRITICAL_SECTION win_data_section
;
35 static CRITICAL_SECTION_DEBUG critsect_debug
=
37 0, 0, &win_data_section
,
38 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
39 0, 0, { (DWORD_PTR
)(__FILE__
": win_data_section") }
41 static CRITICAL_SECTION win_data_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
43 static CFMutableDictionaryRef win_datas
;
45 static DWORD activate_on_focus_time
;
48 void CDECL
macdrv_SetFocus(HWND hwnd
);
51 /***********************************************************************
52 * get_cocoa_window_features
54 static void get_cocoa_window_features(struct macdrv_win_data
*data
,
55 DWORD style
, DWORD ex_style
,
56 struct macdrv_window_features
* wf
)
58 memset(wf
, 0, sizeof(*wf
));
60 if (IsRectEmpty(&data
->window_rect
)) return;
62 if ((style
& WS_CAPTION
) == WS_CAPTION
&& !(ex_style
& WS_EX_LAYERED
))
68 if (style
& WS_SYSMENU
) wf
->close_button
= 1;
69 if (style
& WS_MINIMIZEBOX
) wf
->minimize_button
= 1;
70 if (style
& WS_MAXIMIZEBOX
) wf
->resizable
= 1;
71 if (ex_style
& WS_EX_TOOLWINDOW
) wf
->utility
= 1;
74 if (ex_style
& WS_EX_DLGMODALFRAME
) wf
->shadow
= 1;
75 else if (style
& WS_THICKFRAME
)
78 if (!data
->shaped
) wf
->resizable
= 1;
80 else if ((style
& (WS_DLGFRAME
|WS_BORDER
)) == WS_DLGFRAME
) wf
->shadow
= 1;
84 /*******************************************************************
87 * Check if we can activate the specified window.
89 static inline BOOL
can_activate_window(HWND hwnd
)
91 LONG style
= GetWindowLongW(hwnd
, GWL_STYLE
);
93 if (!(style
& WS_VISIBLE
)) return FALSE
;
94 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
95 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_NOACTIVATE
) return FALSE
;
96 if (hwnd
== GetDesktopWindow()) return FALSE
;
97 return !(style
& WS_DISABLED
);
101 /***********************************************************************
102 * get_cocoa_window_state
104 static void get_cocoa_window_state(struct macdrv_win_data
*data
,
105 DWORD style
, DWORD ex_style
,
106 struct macdrv_window_state
* state
)
108 memset(state
, 0, sizeof(*state
));
109 state
->disabled
= (style
& WS_DISABLED
) != 0;
110 state
->no_activate
= !can_activate_window(data
->hwnd
);
111 state
->floating
= (ex_style
& WS_EX_TOPMOST
) != 0;
112 state
->excluded_by_expose
= state
->excluded_by_cycle
=
113 (!(ex_style
& WS_EX_APPWINDOW
) &&
114 (GetWindow(data
->hwnd
, GW_OWNER
) || (ex_style
& (WS_EX_TOOLWINDOW
| WS_EX_NOACTIVATE
))));
115 if (IsRectEmpty(&data
->window_rect
))
116 state
->excluded_by_expose
= TRUE
;
117 state
->minimized
= (style
& WS_MINIMIZE
) != 0;
118 state
->minimized_valid
= state
->minimized
!= data
->minimized
;
122 /***********************************************************************
123 * get_mac_rect_offset
125 * Helper for macdrv_window_to_mac_rect and macdrv_mac_to_window_rect.
127 static void get_mac_rect_offset(struct macdrv_win_data
*data
, DWORD style
, RECT
*rect
)
129 DWORD ex_style
, style_mask
= 0, ex_style_mask
= 0;
131 rect
->top
= rect
->bottom
= rect
->left
= rect
->right
= 0;
133 ex_style
= GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
);
137 struct macdrv_window_features wf
;
138 get_cocoa_window_features(data
, style
, ex_style
, &wf
);
140 if (wf
.title_bar
) style_mask
|= WS_CAPTION
;
143 style_mask
|= WS_DLGFRAME
| WS_THICKFRAME
;
144 ex_style_mask
|= WS_EX_DLGMODALFRAME
;
148 AdjustWindowRectEx(rect
, style
& style_mask
, FALSE
, ex_style
& ex_style_mask
);
150 TRACE("%p/%p style %08x ex_style %08x shaped %d -> %s\n", data
->hwnd
, data
->cocoa_window
,
151 style
, ex_style
, data
->shaped
, wine_dbgstr_rect(rect
));
155 /***********************************************************************
156 * macdrv_window_to_mac_rect
158 * Convert a rect from client to Mac window coordinates
160 static void macdrv_window_to_mac_rect(struct macdrv_win_data
*data
, DWORD style
, RECT
*rect
)
164 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return;
165 if (IsRectEmpty(rect
)) return;
167 get_mac_rect_offset(data
, style
, &rc
);
169 rect
->left
-= rc
.left
;
170 rect
->right
-= rc
.right
;
172 rect
->bottom
-= rc
.bottom
;
173 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
174 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
178 /***********************************************************************
179 * macdrv_mac_to_window_rect
181 * Opposite of macdrv_window_to_mac_rect
183 static void macdrv_mac_to_window_rect(struct macdrv_win_data
*data
, RECT
*rect
)
186 DWORD style
= GetWindowLongW(data
->hwnd
, GWL_STYLE
);
188 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return;
189 if (IsRectEmpty(rect
)) return;
191 get_mac_rect_offset(data
, style
, &rc
);
193 rect
->left
+= rc
.left
;
194 rect
->right
+= rc
.right
;
196 rect
->bottom
+= rc
.bottom
;
197 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
198 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
202 /***********************************************************************
203 * constrain_window_frame
205 * Alter a window frame rectangle to fit within a) Cocoa's documented
206 * limits, and b) sane sizes, like twice the desktop rect.
208 static void constrain_window_frame(CGRect
* frame
)
210 CGRect desktop_rect
= macdrv_get_desktop_rect();
211 int max_width
, max_height
;
213 max_width
= min(32000, 2 * CGRectGetWidth(desktop_rect
));
214 max_height
= min(32000, 2 * CGRectGetHeight(desktop_rect
));
216 if (frame
->origin
.x
< -16000) frame
->origin
.x
= -16000;
217 if (frame
->origin
.y
< -16000) frame
->origin
.y
= -16000;
218 if (frame
->origin
.x
> 16000) frame
->origin
.x
= 16000;
219 if (frame
->origin
.y
> 16000) frame
->origin
.y
= 16000;
220 if (frame
->size
.width
> max_width
) frame
->size
.width
= max_width
;
221 if (frame
->size
.height
> max_height
) frame
->size
.height
= max_height
;
225 /***********************************************************************
228 static struct macdrv_win_data
*alloc_win_data(HWND hwnd
)
230 struct macdrv_win_data
*data
;
232 if ((data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
))))
235 data
->color_key
= CLR_INVALID
;
236 EnterCriticalSection(&win_data_section
);
238 win_datas
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
239 CFDictionarySetValue(win_datas
, hwnd
, data
);
245 /***********************************************************************
248 * Lock and return the data structure associated with a window.
250 struct macdrv_win_data
*get_win_data(HWND hwnd
)
252 struct macdrv_win_data
*data
;
254 if (!hwnd
) return NULL
;
255 EnterCriticalSection(&win_data_section
);
256 if (win_datas
&& (data
= (struct macdrv_win_data
*)CFDictionaryGetValue(win_datas
, hwnd
)))
258 LeaveCriticalSection(&win_data_section
);
263 /***********************************************************************
266 * Release the data returned by get_win_data.
268 void release_win_data(struct macdrv_win_data
*data
)
270 if (data
) LeaveCriticalSection(&win_data_section
);
274 /***********************************************************************
275 * macdrv_get_cocoa_window
277 * Return the Mac window associated with the full area of a window
279 macdrv_window
macdrv_get_cocoa_window(HWND hwnd
, BOOL require_on_screen
)
281 struct macdrv_win_data
*data
= get_win_data(hwnd
);
282 macdrv_window ret
= NULL
;
283 if (data
&& (data
->on_screen
|| !require_on_screen
))
284 ret
= data
->cocoa_window
;
285 release_win_data(data
);
290 /***********************************************************************
291 * set_cocoa_window_properties
293 * Set the window properties for a Cocoa window based on its Windows
296 static void set_cocoa_window_properties(struct macdrv_win_data
*data
)
298 DWORD style
, ex_style
;
300 macdrv_window owner_win
;
301 struct macdrv_window_features wf
;
302 struct macdrv_window_state state
;
304 style
= GetWindowLongW(data
->hwnd
, GWL_STYLE
);
305 ex_style
= GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
);
307 owner
= GetWindow(data
->hwnd
, GW_OWNER
);
308 owner_win
= macdrv_get_cocoa_window(owner
, TRUE
);
309 macdrv_set_cocoa_parent_window(data
->cocoa_window
, owner_win
);
311 get_cocoa_window_features(data
, style
, ex_style
, &wf
);
312 macdrv_set_cocoa_window_features(data
->cocoa_window
, &wf
);
314 get_cocoa_window_state(data
, style
, ex_style
, &state
);
315 macdrv_set_cocoa_window_state(data
->cocoa_window
, &state
);
316 if (state
.minimized_valid
)
317 data
->minimized
= state
.minimized
;
321 /***********************************************************************
324 * Update the window region.
326 static void sync_window_region(struct macdrv_win_data
*data
, HRGN win_region
)
328 HRGN hrgn
= win_region
;
329 RGNDATA
*region_data
;
333 if (!data
->cocoa_window
) return;
334 data
->shaped
= FALSE
;
336 if (IsRectEmpty(&data
->window_rect
)) /* set an empty shape */
338 TRACE("win %p/%p setting empty shape for zero-sized window\n", data
->hwnd
, data
->cocoa_window
);
339 macdrv_set_window_shape(data
->cocoa_window
, &CGRectZero
, 1);
343 if (hrgn
== (HRGN
)1) /* hack: win_region == 1 means retrieve region from server */
345 if (!(hrgn
= CreateRectRgn(0, 0, 0, 0))) return;
346 if (GetWindowRgn(data
->hwnd
, hrgn
) == ERROR
)
353 if (hrgn
&& GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
)
354 MirrorRgn(data
->hwnd
, hrgn
);
357 OffsetRgn(hrgn
, data
->window_rect
.left
- data
->whole_rect
.left
,
358 data
->window_rect
.top
- data
->whole_rect
.top
);
360 region_data
= get_region_data(hrgn
, 0);
363 rects
= (CGRect
*)region_data
->Buffer
;
364 count
= region_data
->rdh
.nCount
;
365 /* Special case optimization. If the region entirely encloses the Cocoa
366 window, it's the same as there being no region. It's potentially
367 hard/slow to test this for arbitrary regions, so we just check for
368 very simple regions. */
369 if (count
== 1 && CGRectContainsRect(rects
[0], cgrect_from_rect(data
->whole_rect
)))
371 TRACE("optimizing for simple region that contains Cocoa content rect\n");
382 TRACE("win %p/%p win_region %p rects %p count %d\n", data
->hwnd
, data
->cocoa_window
, win_region
, rects
, count
);
383 macdrv_set_window_shape(data
->cocoa_window
, rects
, count
);
385 HeapFree(GetProcessHeap(), 0, region_data
);
386 data
->shaped
= (region_data
!= NULL
);
388 if (hrgn
&& hrgn
!= win_region
) DeleteObject(hrgn
);
392 /***********************************************************************
395 static inline void add_bounds_rect(RECT
*bounds
, const RECT
*rect
)
397 if (rect
->left
>= rect
->right
|| rect
->top
>= rect
->bottom
) return;
398 bounds
->left
= min(bounds
->left
, rect
->left
);
399 bounds
->top
= min(bounds
->top
, rect
->top
);
400 bounds
->right
= max(bounds
->right
, rect
->right
);
401 bounds
->bottom
= max(bounds
->bottom
, rect
->bottom
);
405 /***********************************************************************
406 * sync_window_opacity
408 static void sync_window_opacity(struct macdrv_win_data
*data
, COLORREF key
, BYTE alpha
,
409 BOOL per_pixel_alpha
, DWORD flags
)
411 CGFloat opacity
= 1.0;
412 BOOL needs_flush
= FALSE
;
414 if (flags
& LWA_ALPHA
) opacity
= alpha
/ 255.0;
416 TRACE("setting window %p/%p alpha to %g\n", data
->hwnd
, data
->cocoa_window
, opacity
);
417 macdrv_set_window_alpha(data
->cocoa_window
, opacity
);
419 if (flags
& LWA_COLORKEY
)
421 /* FIXME: treat PALETTEINDEX and DIBINDEX as black */
422 if ((key
& (1 << 24)) || key
>> 16 == 0x10ff)
428 if (data
->color_key
!= key
)
430 if (key
== CLR_INVALID
)
432 TRACE("clearing color-key for window %p/%p\n", data
->hwnd
, data
->cocoa_window
);
433 macdrv_clear_window_color_key(data
->cocoa_window
);
437 TRACE("setting color-key for window %p/%p to RGB %d,%d,%d\n", data
->hwnd
, data
->cocoa_window
,
438 GetRValue(key
), GetGValue(key
), GetBValue(key
));
439 macdrv_set_window_color_key(data
->cocoa_window
, GetRValue(key
), GetGValue(key
), GetBValue(key
));
442 data
->color_key
= key
;
446 if (!data
->per_pixel_alpha
!= !per_pixel_alpha
)
448 macdrv_window_use_per_pixel_alpha(data
->cocoa_window
, per_pixel_alpha
);
449 data
->per_pixel_alpha
= per_pixel_alpha
;
453 if (needs_flush
&& data
->surface
)
458 rect
= data
->whole_rect
;
459 OffsetRect(&rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
460 data
->surface
->funcs
->lock(data
->surface
);
461 bounds
= data
->surface
->funcs
->get_bounds(data
->surface
);
462 add_bounds_rect(bounds
, &rect
);
463 data
->surface
->funcs
->unlock(data
->surface
);
468 /***********************************************************************
469 * sync_window_min_max_info
471 static void sync_window_min_max_info(HWND hwnd
)
473 LONG style
= GetWindowLongW(hwnd
, GWL_STYLE
);
474 LONG exstyle
= GetWindowLongW(hwnd
, GWL_EXSTYLE
);
475 RECT win_rect
, primary_monitor_rect
;
481 struct macdrv_win_data
*data
;
483 TRACE("win %p\n", hwnd
);
485 if (!macdrv_get_cocoa_window(hwnd
, FALSE
)) return;
487 GetWindowRect(hwnd
, &win_rect
);
488 minmax
.ptReserved
.x
= win_rect
.left
;
489 minmax
.ptReserved
.y
= win_rect
.top
;
491 if ((style
& WS_CAPTION
) == WS_CAPTION
)
492 adjustedStyle
= style
& ~WS_BORDER
; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
494 adjustedStyle
= style
;
496 primary_monitor_rect
.left
= primary_monitor_rect
.top
= 0;
497 primary_monitor_rect
.right
= GetSystemMetrics(SM_CXSCREEN
);
498 primary_monitor_rect
.bottom
= GetSystemMetrics(SM_CYSCREEN
);
499 AdjustWindowRectEx(&primary_monitor_rect
, adjustedStyle
, ((style
& WS_POPUP
) && GetMenu(hwnd
)), exstyle
);
501 xinc
= -primary_monitor_rect
.left
;
502 yinc
= -primary_monitor_rect
.top
;
504 minmax
.ptMaxSize
.x
= primary_monitor_rect
.right
- primary_monitor_rect
.left
;
505 minmax
.ptMaxSize
.y
= primary_monitor_rect
.bottom
- primary_monitor_rect
.top
;
506 minmax
.ptMaxPosition
.x
= -xinc
;
507 minmax
.ptMaxPosition
.y
= -yinc
;
508 if (style
& (WS_DLGFRAME
| WS_BORDER
))
510 minmax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
511 minmax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
515 minmax
.ptMinTrackSize
.x
= 2 * xinc
;
516 minmax
.ptMinTrackSize
.y
= 2 * yinc
;
518 minmax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXMAXTRACK
);
519 minmax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYMAXTRACK
);
521 wpl
.length
= sizeof(wpl
);
522 if (GetWindowPlacement(hwnd
, &wpl
) && (wpl
.ptMaxPosition
.x
!= -1 || wpl
.ptMaxPosition
.y
!= -1))
524 minmax
.ptMaxPosition
= wpl
.ptMaxPosition
;
526 /* Convert from GetWindowPlacement's workspace coordinates to screen coordinates. */
527 minmax
.ptMaxPosition
.x
-= wpl
.rcNormalPosition
.left
- win_rect
.left
;
528 minmax
.ptMaxPosition
.y
-= wpl
.rcNormalPosition
.top
- win_rect
.top
;
531 TRACE("initial ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax
.ptMaxSize
),
532 wine_dbgstr_point(&minmax
.ptMaxPosition
), wine_dbgstr_point(&minmax
.ptMinTrackSize
), wine_dbgstr_point(&minmax
.ptMaxTrackSize
));
534 SendMessageW(hwnd
, WM_GETMINMAXINFO
, 0, (LPARAM
)&minmax
);
536 TRACE("app's ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax
.ptMaxSize
),
537 wine_dbgstr_point(&minmax
.ptMaxPosition
), wine_dbgstr_point(&minmax
.ptMinTrackSize
), wine_dbgstr_point(&minmax
.ptMaxTrackSize
));
539 /* if the app didn't change the values, adapt them for the window's monitor */
540 if ((monitor
= MonitorFromWindow(hwnd
, MONITOR_DEFAULTTOPRIMARY
)))
542 MONITORINFO mon_info
;
545 mon_info
.cbSize
= sizeof(mon_info
);
546 GetMonitorInfoW(monitor
, &mon_info
);
548 if ((style
& WS_MAXIMIZEBOX
) && ((style
& WS_CAPTION
) == WS_CAPTION
|| !(style
& WS_POPUP
)))
549 monitor_rect
= mon_info
.rcWork
;
551 monitor_rect
= mon_info
.rcMonitor
;
553 if (minmax
.ptMaxSize
.x
== primary_monitor_rect
.right
- primary_monitor_rect
.left
&&
554 minmax
.ptMaxSize
.y
== primary_monitor_rect
.bottom
- primary_monitor_rect
.top
)
556 minmax
.ptMaxSize
.x
= (monitor_rect
.right
- monitor_rect
.left
) + 2 * xinc
;
557 minmax
.ptMaxSize
.y
= (monitor_rect
.bottom
- monitor_rect
.top
) + 2 * yinc
;
559 if (minmax
.ptMaxPosition
.x
== -xinc
&& minmax
.ptMaxPosition
.y
== -yinc
)
561 minmax
.ptMaxPosition
.x
= monitor_rect
.left
- xinc
;
562 minmax
.ptMaxPosition
.y
= monitor_rect
.top
- yinc
;
566 minmax
.ptMaxTrackSize
.x
= max(minmax
.ptMaxTrackSize
.x
, minmax
.ptMinTrackSize
.x
);
567 minmax
.ptMaxTrackSize
.y
= max(minmax
.ptMaxTrackSize
.y
, minmax
.ptMinTrackSize
.y
);
569 TRACE("adjusted ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax
.ptMaxSize
),
570 wine_dbgstr_point(&minmax
.ptMaxPosition
), wine_dbgstr_point(&minmax
.ptMinTrackSize
), wine_dbgstr_point(&minmax
.ptMaxTrackSize
));
572 if ((data
= get_win_data(hwnd
)) && data
->cocoa_window
)
574 RECT min_rect
, max_rect
;
575 CGSize min_size
, max_size
;
577 SetRect(&min_rect
, 0, 0, minmax
.ptMinTrackSize
.x
, minmax
.ptMinTrackSize
.y
);
578 macdrv_window_to_mac_rect(data
, style
, &min_rect
);
579 min_size
= CGSizeMake(min_rect
.right
- min_rect
.left
, min_rect
.bottom
- min_rect
.top
);
581 if (minmax
.ptMaxTrackSize
.x
== GetSystemMetrics(SM_CXMAXTRACK
) &&
582 minmax
.ptMaxTrackSize
.y
== GetSystemMetrics(SM_CYMAXTRACK
))
583 max_size
= CGSizeMake(CGFLOAT_MAX
, CGFLOAT_MAX
);
586 SetRect(&max_rect
, 0, 0, minmax
.ptMaxTrackSize
.x
, minmax
.ptMaxTrackSize
.y
);
587 macdrv_window_to_mac_rect(data
, style
, &max_rect
);
588 max_size
= CGSizeMake(max_rect
.right
- max_rect
.left
, max_rect
.bottom
- max_rect
.top
);
591 TRACE("min_size (%g,%g) max_size (%g,%g)\n", min_size
.width
, min_size
.height
, max_size
.width
, max_size
.height
);
592 macdrv_set_window_min_max_sizes(data
->cocoa_window
, min_size
, max_size
);
595 release_win_data(data
);
599 /**********************************************************************
600 * create_cocoa_window
602 * Create the whole Mac window for a given window
604 static void create_cocoa_window(struct macdrv_win_data
*data
)
606 struct macdrv_thread_data
*thread_data
= macdrv_init_thread_data();
608 struct macdrv_window_features wf
;
610 DWORD style
, ex_style
;
616 if ((win_rgn
= CreateRectRgn(0, 0, 0, 0)) &&
617 GetWindowRgn(data
->hwnd
, win_rgn
) == ERROR
)
619 DeleteObject(win_rgn
);
622 data
->shaped
= (win_rgn
!= 0);
624 style
= GetWindowLongW(data
->hwnd
, GWL_STYLE
);
625 ex_style
= GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
);
627 data
->whole_rect
= data
->window_rect
;
628 macdrv_window_to_mac_rect(data
, style
, &data
->whole_rect
);
630 get_cocoa_window_features(data
, style
, ex_style
, &wf
);
632 frame
= cgrect_from_rect(data
->whole_rect
);
633 constrain_window_frame(&frame
);
634 if (frame
.size
.width
< 1 || frame
.size
.height
< 1)
635 frame
.size
.width
= frame
.size
.height
= 1;
637 TRACE("creating %p window %s whole %s client %s\n", data
->hwnd
, wine_dbgstr_rect(&data
->window_rect
),
638 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_rect(&data
->client_rect
));
640 data
->cocoa_window
= macdrv_create_cocoa_window(&wf
, frame
, data
->hwnd
, thread_data
->queue
);
641 if (!data
->cocoa_window
) goto done
;
643 set_cocoa_window_properties(data
);
645 /* set the window text */
646 if (!InternalGetWindowText(data
->hwnd
, text
, sizeof(text
)/sizeof(WCHAR
))) text
[0] = 0;
647 macdrv_set_cocoa_window_title(data
->cocoa_window
, text
, strlenW(text
));
649 /* set the window region */
650 if (win_rgn
|| IsRectEmpty(&data
->window_rect
)) sync_window_region(data
, win_rgn
);
652 /* set the window opacity */
653 if (!GetLayeredWindowAttributes(data
->hwnd
, &key
, &alpha
, &layered_flags
)) layered_flags
= 0;
654 sync_window_opacity(data
, key
, alpha
, FALSE
, layered_flags
);
657 if (win_rgn
) DeleteObject(win_rgn
);
661 /**********************************************************************
662 * destroy_cocoa_window
664 * Destroy the whole Mac window for a given window.
666 static void destroy_cocoa_window(struct macdrv_win_data
*data
)
668 if (!data
->cocoa_window
) return;
670 TRACE("win %p Cocoa win %p\n", data
->hwnd
, data
->cocoa_window
);
672 macdrv_destroy_cocoa_window(data
->cocoa_window
);
673 data
->cocoa_window
= 0;
674 data
->on_screen
= FALSE
;
675 data
->color_key
= CLR_INVALID
;
676 if (data
->surface
) window_surface_release(data
->surface
);
677 data
->surface
= NULL
;
678 if (data
->unminimized_surface
) window_surface_release(data
->unminimized_surface
);
679 data
->unminimized_surface
= NULL
;
683 /***********************************************************************
684 * macdrv_create_win_data
686 * Create a Mac data window structure for an existing window.
688 static struct macdrv_win_data
*macdrv_create_win_data(HWND hwnd
, const RECT
*window_rect
,
689 const RECT
*client_rect
)
691 struct macdrv_win_data
*data
;
694 if (GetWindowThreadProcessId(hwnd
, NULL
) != GetCurrentThreadId()) return NULL
;
696 if (!(parent
= GetAncestor(hwnd
, GA_PARENT
))) /* desktop */
698 macdrv_init_thread_data();
702 /* don't create win data for HWND_MESSAGE windows */
703 if (parent
!= GetDesktopWindow() && !GetAncestor(parent
, GA_PARENT
)) return NULL
;
705 if (!(data
= alloc_win_data(hwnd
))) return NULL
;
707 data
->whole_rect
= data
->window_rect
= *window_rect
;
708 data
->client_rect
= *client_rect
;
710 if (parent
== GetDesktopWindow())
712 create_cocoa_window(data
);
713 TRACE("win %p/%p window %s whole %s client %s\n",
714 hwnd
, data
->cocoa_window
, wine_dbgstr_rect(&data
->window_rect
),
715 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_rect(&data
->client_rect
));
722 /***********************************************************************
725 static void show_window(struct macdrv_win_data
*data
)
729 macdrv_window prev_window
= NULL
;
730 macdrv_window next_window
= NULL
;
731 BOOL activate
= FALSE
;
733 /* find window that this one must be after */
734 prev
= GetWindow(data
->hwnd
, GW_HWNDPREV
);
735 while (prev
&& !((GetWindowLongW(prev
, GWL_STYLE
) & (WS_VISIBLE
| WS_MINIMIZE
)) == WS_VISIBLE
&&
736 (prev_window
= macdrv_get_cocoa_window(prev
, TRUE
))))
737 prev
= GetWindow(prev
, GW_HWNDPREV
);
740 /* find window that this one must be before */
741 next
= GetWindow(data
->hwnd
, GW_HWNDNEXT
);
742 while (next
&& !((GetWindowLongW(next
, GWL_STYLE
) & (WS_VISIBLE
| WS_MINIMIZE
)) == WS_VISIBLE
&&
743 (next_window
= macdrv_get_cocoa_window(next
, TRUE
))))
744 next
= GetWindow(next
, GW_HWNDNEXT
);
747 TRACE("win %p/%p below %p/%p above %p/%p\n",
748 data
->hwnd
, data
->cocoa_window
, prev
, prev_window
, next
, next_window
);
751 activate
= activate_on_focus_time
&& (GetTickCount() - activate_on_focus_time
< 2000);
752 data
->on_screen
= macdrv_order_cocoa_window(data
->cocoa_window
, prev_window
, next_window
, activate
);
755 HWND hwndFocus
= GetFocus();
756 if (hwndFocus
&& (data
->hwnd
== hwndFocus
|| IsChild(data
->hwnd
, hwndFocus
)))
757 macdrv_SetFocus(hwndFocus
);
759 activate_on_focus_time
= 0;
764 /***********************************************************************
767 static void hide_window(struct macdrv_win_data
*data
)
769 TRACE("win %p/%p\n", data
->hwnd
, data
->cocoa_window
);
771 macdrv_hide_cocoa_window(data
->cocoa_window
);
772 data
->on_screen
= FALSE
;
776 /***********************************************************************
779 * Calls GetRegionData on the given region and converts the rectangle
780 * array to CGRect format. The returned buffer must be freed by
781 * caller using HeapFree(GetProcessHeap(),...).
782 * If hdc_lptodp is not 0, the rectangles are converted through LPtoDP.
784 RGNDATA
*get_region_data(HRGN hrgn
, HDC hdc_lptodp
)
792 if (!hrgn
|| !(size
= GetRegionData(hrgn
, 0, NULL
))) return NULL
;
793 if (sizeof(CGRect
) > sizeof(RECT
))
795 /* add extra size for CGRect array */
796 int count
= (size
- sizeof(RGNDATAHEADER
)) / sizeof(RECT
);
797 size
+= count
* (sizeof(CGRect
) - sizeof(RECT
));
799 if (!(data
= HeapAlloc(GetProcessHeap(), 0, size
))) return NULL
;
800 if (!GetRegionData(hrgn
, size
, data
))
802 HeapFree(GetProcessHeap(), 0, data
);
806 rect
= (RECT
*)data
->Buffer
;
807 cgrect
= (CGRect
*)data
->Buffer
;
808 if (hdc_lptodp
) /* map to device coordinates */
810 LPtoDP(hdc_lptodp
, (POINT
*)rect
, data
->rdh
.nCount
* 2);
811 for (i
= 0; i
< data
->rdh
.nCount
; i
++)
813 if (rect
[i
].right
< rect
[i
].left
)
815 INT tmp
= rect
[i
].right
;
816 rect
[i
].right
= rect
[i
].left
;
819 if (rect
[i
].bottom
< rect
[i
].top
)
821 INT tmp
= rect
[i
].bottom
;
822 rect
[i
].bottom
= rect
[i
].top
;
828 if (sizeof(CGRect
) > sizeof(RECT
))
830 /* need to start from the end */
831 for (i
= data
->rdh
.nCount
-1; i
>= 0; i
--)
832 cgrect
[i
] = cgrect_from_rect(rect
[i
]);
836 for (i
= 0; i
< data
->rdh
.nCount
; i
++)
837 cgrect
[i
] = cgrect_from_rect(rect
[i
]);
843 /***********************************************************************
844 * sync_window_position
846 * Synchronize the Mac window position with the Windows one
848 static void sync_window_position(struct macdrv_win_data
*data
, UINT swp_flags
, const RECT
*old_window_rect
,
849 const RECT
*old_whole_rect
)
853 if (data
->minimized
) return;
855 frame
= cgrect_from_rect(data
->whole_rect
);
856 constrain_window_frame(&frame
);
857 if (frame
.size
.width
< 1 || frame
.size
.height
< 1)
858 frame
.size
.width
= frame
.size
.height
= 1;
860 data
->on_screen
= macdrv_set_cocoa_window_frame(data
->cocoa_window
, &frame
);
861 if (old_window_rect
&& old_whole_rect
&&
862 (IsRectEmpty(old_window_rect
) != IsRectEmpty(&data
->window_rect
) ||
863 old_window_rect
->left
- old_whole_rect
->left
!= data
->window_rect
.left
- data
->whole_rect
.left
||
864 old_window_rect
->top
- old_whole_rect
->top
!= data
->window_rect
.top
- data
->whole_rect
.top
))
865 sync_window_region(data
, (HRGN
)1);
867 TRACE("win %p/%p whole_rect %s frame %s\n", data
->hwnd
, data
->cocoa_window
,
868 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_cgrect(frame
));
870 if (data
->on_screen
&& (!(swp_flags
& SWP_NOZORDER
) || (swp_flags
& SWP_SHOWWINDOW
)))
875 /***********************************************************************
878 * Move the window bits when a window is moved.
880 static void move_window_bits(HWND hwnd
, macdrv_window window
, const RECT
*old_rect
, const RECT
*new_rect
,
881 const RECT
*old_client_rect
, const RECT
*new_client_rect
,
882 const RECT
*new_window_rect
)
884 RECT src_rect
= *old_rect
;
885 RECT dst_rect
= *new_rect
;
886 HDC hdc_src
, hdc_dst
;
892 OffsetRect(&dst_rect
, -new_window_rect
->left
, -new_window_rect
->top
);
893 parent
= GetAncestor(hwnd
, GA_PARENT
);
894 hdc_src
= GetDCEx(parent
, 0, DCX_CACHE
);
895 hdc_dst
= GetDCEx(hwnd
, 0, DCX_CACHE
| DCX_WINDOW
);
899 OffsetRect(&dst_rect
, -new_client_rect
->left
, -new_client_rect
->top
);
900 /* make src rect relative to the old position of the window */
901 OffsetRect(&src_rect
, -old_client_rect
->left
, -old_client_rect
->top
);
902 if (dst_rect
.left
== src_rect
.left
&& dst_rect
.top
== src_rect
.top
) return;
903 hdc_src
= hdc_dst
= GetDCEx(hwnd
, 0, DCX_CACHE
);
906 rgn
= CreateRectRgnIndirect(&dst_rect
);
907 SelectClipRgn(hdc_dst
, rgn
);
909 ExcludeUpdateRgn(hdc_dst
, hwnd
);
911 TRACE("copying bits for win %p/%p %s -> %s\n", hwnd
, window
,
912 wine_dbgstr_rect(&src_rect
), wine_dbgstr_rect(&dst_rect
));
913 BitBlt(hdc_dst
, dst_rect
.left
, dst_rect
.top
,
914 dst_rect
.right
- dst_rect
.left
, dst_rect
.bottom
- dst_rect
.top
,
915 hdc_src
, src_rect
.left
, src_rect
.top
, SRCCOPY
);
917 ReleaseDC(hwnd
, hdc_dst
);
918 if (hdc_src
!= hdc_dst
) ReleaseDC(parent
, hdc_src
);
922 /**********************************************************************
923 * activate_on_following_focus
925 void activate_on_following_focus(void)
927 activate_on_focus_time
= GetTickCount();
928 if (!activate_on_focus_time
) activate_on_focus_time
= 1;
932 /***********************************************************************
935 static void set_app_icon(void)
937 CFArrayRef images
= create_app_icon_images();
940 macdrv_set_application_icon(images
);
946 /**********************************************************************
947 * CreateDesktopWindow (MACDRV.@)
949 BOOL CDECL
macdrv_CreateDesktopWindow(HWND hwnd
)
951 unsigned int width
, height
;
955 /* retrieve the real size of the desktop */
956 SERVER_START_REQ(get_window_rectangles
)
958 req
->handle
= wine_server_user_handle(hwnd
);
959 req
->relative
= COORDS_CLIENT
;
960 wine_server_call(req
);
961 width
= reply
->window
.right
;
962 height
= reply
->window
.bottom
;
966 if (!width
&& !height
) /* not initialized yet */
968 CGRect rect
= macdrv_get_desktop_rect();
970 SERVER_START_REQ(set_window_pos
)
972 req
->handle
= wine_server_user_handle(hwnd
);
974 req
->swp_flags
= SWP_NOZORDER
;
975 req
->window
.left
= CGRectGetMinX(rect
);
976 req
->window
.top
= CGRectGetMinY(rect
);
977 req
->window
.right
= CGRectGetMaxX(rect
);
978 req
->window
.bottom
= CGRectGetMaxY(rect
);
979 req
->client
= req
->window
;
980 wine_server_call(req
);
990 /**********************************************************************
991 * CreateWindow (MACDRV.@)
993 BOOL CDECL
macdrv_CreateWindow(HWND hwnd
)
999 /***********************************************************************
1000 * DestroyWindow (MACDRV.@)
1002 void CDECL
macdrv_DestroyWindow(HWND hwnd
)
1004 struct macdrv_win_data
*data
;
1006 TRACE("%p\n", hwnd
);
1008 if (!(data
= get_win_data(hwnd
))) return;
1010 if (data
->gl_view
) macdrv_dispose_view(data
->gl_view
);
1011 destroy_cocoa_window(data
);
1013 CFDictionaryRemoveValue(win_datas
, hwnd
);
1014 release_win_data(data
);
1015 HeapFree(GetProcessHeap(), 0, data
);
1019 /*****************************************************************
1020 * SetFocus (MACDRV.@)
1022 * Set the Mac focus.
1024 void CDECL
macdrv_SetFocus(HWND hwnd
)
1026 struct macdrv_thread_data
*thread_data
= macdrv_thread_data();
1027 struct macdrv_win_data
*data
;
1029 TRACE("%p\n", hwnd
);
1031 if (!thread_data
) return;
1032 thread_data
->dead_key_state
= 0;
1034 if (!(hwnd
= GetAncestor(hwnd
, GA_ROOT
))) return;
1035 if (!(data
= get_win_data(hwnd
))) return;
1037 if (data
->cocoa_window
&& data
->on_screen
)
1039 BOOL activate
= activate_on_focus_time
&& (GetTickCount() - activate_on_focus_time
< 2000);
1041 macdrv_give_cocoa_window_focus(data
->cocoa_window
, activate
);
1042 activate_on_focus_time
= 0;
1045 release_win_data(data
);
1049 /***********************************************************************
1050 * SetLayeredWindowAttributes (MACDRV.@)
1052 * Set transparency attributes for a layered window.
1054 void CDECL
macdrv_SetLayeredWindowAttributes(HWND hwnd
, COLORREF key
, BYTE alpha
, DWORD flags
)
1056 struct macdrv_win_data
*data
= get_win_data(hwnd
);
1058 TRACE("hwnd %p key %#08x alpha %#02x flags %x\n", hwnd
, key
, alpha
, flags
);
1062 data
->layered
= TRUE
;
1063 if (data
->cocoa_window
)
1065 sync_window_opacity(data
, key
, alpha
, FALSE
, flags
);
1066 /* since layered attributes are now set, can now show the window */
1067 if ((GetWindowLongW(hwnd
, GWL_STYLE
) & WS_VISIBLE
) && !data
->on_screen
)
1070 release_win_data(data
);
1073 FIXME("setting layered attributes on window %p of other process not supported\n", hwnd
);
1077 /*****************************************************************
1078 * SetParent (MACDRV.@)
1080 void CDECL
macdrv_SetParent(HWND hwnd
, HWND parent
, HWND old_parent
)
1082 struct macdrv_win_data
*data
;
1084 TRACE("%p, %p, %p\n", hwnd
, parent
, old_parent
);
1086 if (parent
== old_parent
) return;
1087 if (!(data
= get_win_data(hwnd
))) return;
1089 if (parent
!= GetDesktopWindow()) /* a child window */
1091 if (old_parent
== GetDesktopWindow())
1093 /* destroy the old Mac window */
1094 destroy_cocoa_window(data
);
1097 else /* new top level window */
1098 create_cocoa_window(data
);
1099 release_win_data(data
);
1101 set_gl_view_parent(hwnd
, parent
);
1105 /***********************************************************************
1106 * SetWindowRgn (MACDRV.@)
1108 * Assign specified region to window (for non-rectangular windows)
1110 int CDECL
macdrv_SetWindowRgn(HWND hwnd
, HRGN hrgn
, BOOL redraw
)
1112 struct macdrv_win_data
*data
;
1114 TRACE("%p, %p, %d\n", hwnd
, hrgn
, redraw
);
1116 if ((data
= get_win_data(hwnd
)))
1118 sync_window_region(data
, hrgn
);
1119 release_win_data(data
);
1125 GetWindowThreadProcessId(hwnd
, &procid
);
1126 if (procid
!= GetCurrentProcessId())
1127 SendMessageW(hwnd
, WM_MACDRV_SET_WIN_REGION
, 0, 0);
1134 /***********************************************************************
1135 * SetWindowStyle (MACDRV.@)
1137 * Update the state of the Cocoa window to reflect a style change
1139 void CDECL
macdrv_SetWindowStyle(HWND hwnd
, INT offset
, STYLESTRUCT
*style
)
1141 struct macdrv_win_data
*data
;
1143 TRACE("hwnd %p offset %d styleOld 0x%08x styleNew 0x%08x\n", hwnd
, offset
, style
->styleOld
, style
->styleNew
);
1145 if (hwnd
== GetDesktopWindow()) return;
1146 if (!(data
= get_win_data(hwnd
))) return;
1148 if (data
->cocoa_window
)
1150 DWORD changed
= style
->styleNew
^ style
->styleOld
;
1152 set_cocoa_window_properties(data
);
1154 if (offset
== GWL_EXSTYLE
&& (changed
& WS_EX_LAYERED
)) /* changing WS_EX_LAYERED resets attributes */
1156 data
->layered
= FALSE
;
1157 data
->ulw_layered
= FALSE
;
1158 sync_window_opacity(data
, 0, 0, FALSE
, 0);
1159 if (data
->surface
) set_surface_use_alpha(data
->surface
, FALSE
);
1162 if (offset
== GWL_EXSTYLE
&& (changed
& WS_EX_LAYOUTRTL
))
1163 sync_window_region(data
, (HRGN
)1);
1166 release_win_data(data
);
1170 /*****************************************************************
1171 * SetWindowText (MACDRV.@)
1173 void CDECL
macdrv_SetWindowText(HWND hwnd
, LPCWSTR text
)
1177 TRACE("%p, %s\n", hwnd
, debugstr_w(text
));
1179 if ((win
= macdrv_get_cocoa_window(hwnd
, FALSE
)))
1180 macdrv_set_cocoa_window_title(win
, text
, strlenW(text
));
1184 /***********************************************************************
1185 * ShowWindow (MACDRV.@)
1187 UINT CDECL
macdrv_ShowWindow(HWND hwnd
, INT cmd
, RECT
*rect
, UINT swp
)
1189 struct macdrv_thread_data
*thread_data
= macdrv_thread_data();
1190 struct macdrv_win_data
*data
= get_win_data(hwnd
);
1193 TRACE("win %p/%p cmd %d at %s flags %08x\n",
1194 hwnd
, data
? data
->cocoa_window
: NULL
, cmd
, wine_dbgstr_rect(rect
), swp
);
1196 if (!data
|| !data
->cocoa_window
) goto done
;
1197 if (IsRectEmpty(rect
)) goto done
;
1198 if (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
1200 if (rect
->left
!= -32000 || rect
->top
!= -32000)
1202 OffsetRect(rect
, -32000 - rect
->left
, -32000 - rect
->top
);
1203 swp
&= ~(SWP_NOMOVE
| SWP_NOCLIENTMOVE
);
1207 if (!data
->on_screen
) goto done
;
1209 /* only fetch the new rectangle if the ShowWindow was a result of an external event */
1211 if (!thread_data
->current_event
|| thread_data
->current_event
->window
!= data
->cocoa_window
)
1214 if (thread_data
->current_event
->type
!= WINDOW_FRAME_CHANGED
&&
1215 thread_data
->current_event
->type
!= WINDOW_DID_UNMINIMIZE
)
1218 macdrv_get_cocoa_window_frame(data
->cocoa_window
, &frame
);
1219 *rect
= rect_from_cgrect(frame
);
1220 macdrv_mac_to_window_rect(data
, rect
);
1221 TRACE("rect %s -> %s\n", wine_dbgstr_cgrect(frame
), wine_dbgstr_rect(rect
));
1222 swp
&= ~(SWP_NOMOVE
| SWP_NOCLIENTMOVE
| SWP_NOSIZE
| SWP_NOCLIENTSIZE
);
1225 release_win_data(data
);
1230 /***********************************************************************
1231 * SysCommand (MACDRV.@)
1233 * Perform WM_SYSCOMMAND handling.
1235 LRESULT CDECL
macdrv_SysCommand(HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1237 struct macdrv_win_data
*data
;
1240 TRACE("%p, %x, %lx\n", hwnd
, (unsigned)wparam
, lparam
);
1242 if (!(data
= get_win_data(hwnd
))) goto done
;
1243 if (!data
->cocoa_window
|| !data
->on_screen
) goto done
;
1245 /* prevent a simple ALT press+release from activating the system menu,
1246 as that can get confusing */
1247 if ((wparam
& 0xfff0) == SC_KEYMENU
&& !(WCHAR
)lparam
&& !GetMenu(hwnd
) &&
1248 (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_SYSMENU
))
1250 TRACE("ignoring SC_KEYMENU wp %lx lp %lx\n", wparam
, lparam
);
1255 release_win_data(data
);
1260 /***********************************************************************
1261 * UpdateLayeredWindow (MACDRV.@)
1263 BOOL CDECL
macdrv_UpdateLayeredWindow(HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
,
1264 const RECT
*window_rect
)
1266 struct window_surface
*surface
;
1267 struct macdrv_win_data
*data
;
1268 BLENDFUNCTION blend
= { AC_SRC_OVER
, 0, 255, 0 };
1270 char buffer
[FIELD_OFFSET(BITMAPINFO
, bmiColors
[256])];
1271 BITMAPINFO
*bmi
= (BITMAPINFO
*)buffer
;
1272 void *src_bits
, *dst_bits
;
1278 if (!(data
= get_win_data(hwnd
))) return FALSE
;
1280 data
->layered
= TRUE
;
1281 data
->ulw_layered
= TRUE
;
1283 rect
= *window_rect
;
1284 OffsetRect(&rect
, -window_rect
->left
, -window_rect
->top
);
1286 surface
= data
->surface
;
1287 if (!surface
|| memcmp(&surface
->rect
, &rect
, sizeof(RECT
)))
1289 data
->surface
= create_surface(data
->cocoa_window
, &rect
, NULL
, TRUE
);
1290 set_window_surface(data
->cocoa_window
, data
->surface
);
1291 if (surface
) window_surface_release(surface
);
1292 surface
= data
->surface
;
1293 if (data
->unminimized_surface
)
1295 window_surface_release(data
->unminimized_surface
);
1296 data
->unminimized_surface
= NULL
;
1299 else set_surface_use_alpha(surface
, TRUE
);
1301 if (surface
) window_surface_add_ref(surface
);
1302 release_win_data(data
);
1304 if (!surface
) return FALSE
;
1307 window_surface_release(surface
);
1311 if (info
->dwFlags
& ULW_ALPHA
)
1313 /* Apply SourceConstantAlpha via window alpha, not blend. */
1314 alpha
= info
->pblend
->SourceConstantAlpha
;
1315 blend
= *info
->pblend
;
1316 blend
.SourceConstantAlpha
= 0xff;
1321 dst_bits
= surface
->funcs
->get_info(surface
, bmi
);
1323 if (!(dib
= CreateDIBSection(info
->hdcDst
, bmi
, DIB_RGB_COLORS
, &src_bits
, NULL
, 0))) goto done
;
1324 if (!(hdc
= CreateCompatibleDC(0))) goto done
;
1326 SelectObject(hdc
, dib
);
1329 IntersectRect(&rect
, &rect
, info
->prcDirty
);
1330 surface
->funcs
->lock(surface
);
1331 memcpy(src_bits
, dst_bits
, bmi
->bmiHeader
.biSizeImage
);
1332 surface
->funcs
->unlock(surface
);
1333 PatBlt(hdc
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, BLACKNESS
);
1335 if (!(ret
= GdiAlphaBlend(hdc
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
1337 rect
.left
+ (info
->pptSrc
? info
->pptSrc
->x
: 0),
1338 rect
.top
+ (info
->pptSrc
? info
->pptSrc
->y
: 0),
1339 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
1343 if ((data
= get_win_data(hwnd
)))
1345 if (surface
== data
->surface
)
1347 surface
->funcs
->lock(surface
);
1348 memcpy(dst_bits
, src_bits
, bmi
->bmiHeader
.biSizeImage
);
1349 add_bounds_rect(surface
->funcs
->get_bounds(surface
), &rect
);
1350 surface
->funcs
->unlock(surface
);
1351 surface
->funcs
->flush(surface
);
1354 /* The ULW flags are a superset of the LWA flags. */
1355 sync_window_opacity(data
, info
->crKey
, alpha
, TRUE
, info
->dwFlags
);
1357 release_win_data(data
);
1361 window_surface_release(surface
);
1362 if (hdc
) DeleteDC(hdc
);
1363 if (dib
) DeleteObject(dib
);
1368 /**********************************************************************
1369 * WindowMessage (MACDRV.@)
1371 LRESULT CDECL
macdrv_WindowMessage(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1373 struct macdrv_win_data
*data
;
1375 TRACE("%p, %u, %u, %lu\n", hwnd
, msg
, (unsigned)wp
, lp
);
1379 case WM_MACDRV_SET_WIN_REGION
:
1380 if ((data
= get_win_data(hwnd
)))
1382 sync_window_region(data
, (HRGN
)1);
1383 release_win_data(data
);
1386 case WM_MACDRV_UPDATE_DESKTOP_RECT
:
1387 if (hwnd
== GetDesktopWindow())
1389 CGRect new_desktop_rect
;
1390 RECT current_desktop_rect
;
1392 macdrv_reset_device_metrics();
1393 new_desktop_rect
= macdrv_get_desktop_rect();
1394 if (!GetWindowRect(hwnd
, ¤t_desktop_rect
) ||
1395 !CGRectEqualToRect(cgrect_from_rect(current_desktop_rect
), new_desktop_rect
))
1397 SendMessageTimeoutW(HWND_BROADCAST
, WM_MACDRV_RESET_DEVICE_METRICS
, 0, 0,
1398 SMTO_ABORTIFHUNG
, 2000, NULL
);
1399 SetWindowPos(hwnd
, 0, CGRectGetMinX(new_desktop_rect
), CGRectGetMinY(new_desktop_rect
),
1400 CGRectGetWidth(new_desktop_rect
), CGRectGetHeight(new_desktop_rect
),
1401 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_DEFERERASE
);
1402 SendMessageTimeoutW(HWND_BROADCAST
, WM_MACDRV_DISPLAYCHANGE
, wp
, lp
,
1403 SMTO_ABORTIFHUNG
, 2000, NULL
);
1407 case WM_MACDRV_RESET_DEVICE_METRICS
:
1408 macdrv_reset_device_metrics();
1410 case WM_MACDRV_DISPLAYCHANGE
:
1411 if ((data
= get_win_data(hwnd
)))
1413 if (data
->cocoa_window
&& data
->on_screen
)
1414 sync_window_position(data
, SWP_NOZORDER
| SWP_NOACTIVATE
, NULL
, NULL
);
1415 release_win_data(data
);
1417 SendMessageW(hwnd
, WM_DISPLAYCHANGE
, wp
, lp
);
1419 case WM_MACDRV_ACTIVATE_ON_FOLLOWING_FOCUS
:
1420 activate_on_following_focus();
1421 TRACE("WM_MACDRV_ACTIVATE_ON_FOLLOWING_FOCUS time %u\n", activate_on_focus_time
);
1425 FIXME("unrecognized window msg %x hwnd %p wp %lx lp %lx\n", msg
, hwnd
, wp
, lp
);
1430 static inline RECT
get_surface_rect(const RECT
*visible_rect
)
1433 RECT desktop_rect
= rect_from_cgrect(macdrv_get_desktop_rect());
1435 IntersectRect(&rect
, visible_rect
, &desktop_rect
);
1436 OffsetRect(&rect
, -visible_rect
->left
, -visible_rect
->top
);
1439 rect
.right
= max(rect
.left
+ 128, (rect
.right
+ 127) & ~127);
1440 rect
.bottom
= max(rect
.top
+ 128, (rect
.bottom
+ 127) & ~127);
1445 /***********************************************************************
1446 * WindowPosChanging (MACDRV.@)
1448 void CDECL
macdrv_WindowPosChanging(HWND hwnd
, HWND insert_after
, UINT swp_flags
,
1449 const RECT
*window_rect
, const RECT
*client_rect
,
1450 RECT
*visible_rect
, struct window_surface
**surface
)
1452 struct macdrv_win_data
*data
= get_win_data(hwnd
);
1453 DWORD style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1456 TRACE("%p after %p swp %04x window %s client %s visible %s surface %p\n", hwnd
, insert_after
,
1457 swp_flags
, wine_dbgstr_rect(window_rect
), wine_dbgstr_rect(client_rect
),
1458 wine_dbgstr_rect(visible_rect
), surface
);
1460 if (!data
&& !(data
= macdrv_create_win_data(hwnd
, window_rect
, client_rect
))) return;
1462 *visible_rect
= *window_rect
;
1463 macdrv_window_to_mac_rect(data
, style
, visible_rect
);
1464 TRACE("visible_rect %s -> %s\n", wine_dbgstr_rect(window_rect
),
1465 wine_dbgstr_rect(visible_rect
));
1467 /* create the window surface if necessary */
1468 if (!data
->cocoa_window
) goto done
;
1469 if (swp_flags
& SWP_HIDEWINDOW
) goto done
;
1470 if (data
->ulw_layered
) goto done
;
1472 if (*surface
) window_surface_release(*surface
);
1475 surface_rect
= get_surface_rect(visible_rect
);
1478 if (!memcmp(&data
->surface
->rect
, &surface_rect
, sizeof(surface_rect
)))
1480 /* existing surface is good enough */
1481 surface_clip_to_visible_rect(data
->surface
, visible_rect
);
1482 window_surface_add_ref(data
->surface
);
1483 *surface
= data
->surface
;
1487 else if (!(swp_flags
& SWP_SHOWWINDOW
) && !(style
& WS_VISIBLE
)) goto done
;
1489 *surface
= create_surface(data
->cocoa_window
, &surface_rect
, data
->surface
, FALSE
);
1492 release_win_data(data
);
1496 /***********************************************************************
1497 * WindowPosChanged (MACDRV.@)
1499 void CDECL
macdrv_WindowPosChanged(HWND hwnd
, HWND insert_after
, UINT swp_flags
,
1500 const RECT
*window_rect
, const RECT
*client_rect
,
1501 const RECT
*visible_rect
, const RECT
*valid_rects
,
1502 struct window_surface
*surface
)
1504 struct macdrv_thread_data
*thread_data
;
1505 struct macdrv_win_data
*data
;
1506 DWORD new_style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1507 RECT old_window_rect
, old_whole_rect
, old_client_rect
;
1509 if (!(data
= get_win_data(hwnd
))) return;
1511 thread_data
= macdrv_thread_data();
1513 old_window_rect
= data
->window_rect
;
1514 old_whole_rect
= data
->whole_rect
;
1515 old_client_rect
= data
->client_rect
;
1516 data
->window_rect
= *window_rect
;
1517 data
->whole_rect
= *visible_rect
;
1518 data
->client_rect
= *client_rect
;
1519 if (!data
->ulw_layered
)
1521 if (surface
) window_surface_add_ref(surface
);
1522 if (new_style
& WS_MINIMIZE
)
1524 if (!data
->unminimized_surface
&& data
->surface
)
1526 data
->unminimized_surface
= data
->surface
;
1527 window_surface_add_ref(data
->unminimized_surface
);
1532 set_window_surface(data
->cocoa_window
, surface
);
1533 if (data
->unminimized_surface
)
1535 window_surface_release(data
->unminimized_surface
);
1536 data
->unminimized_surface
= NULL
;
1539 if (data
->surface
) window_surface_release(data
->surface
);
1540 data
->surface
= surface
;
1543 TRACE("win %p/%p window %s whole %s client %s style %08x flags %08x surface %p\n",
1544 hwnd
, data
->cocoa_window
, wine_dbgstr_rect(window_rect
),
1545 wine_dbgstr_rect(visible_rect
), wine_dbgstr_rect(client_rect
),
1546 new_style
, swp_flags
, surface
);
1548 if (!IsRectEmpty(&valid_rects
[0]))
1550 macdrv_window window
= data
->cocoa_window
;
1551 int x_offset
= old_whole_rect
.left
- data
->whole_rect
.left
;
1552 int y_offset
= old_whole_rect
.top
- data
->whole_rect
.top
;
1554 /* if all that happened is that the whole window moved, copy everything */
1555 if (!(swp_flags
& SWP_FRAMECHANGED
) &&
1556 old_whole_rect
.right
- data
->whole_rect
.right
== x_offset
&&
1557 old_whole_rect
.bottom
- data
->whole_rect
.bottom
== y_offset
&&
1558 old_client_rect
.left
- data
->client_rect
.left
== x_offset
&&
1559 old_client_rect
.right
- data
->client_rect
.right
== x_offset
&&
1560 old_client_rect
.top
- data
->client_rect
.top
== y_offset
&&
1561 old_client_rect
.bottom
- data
->client_rect
.bottom
== y_offset
&&
1562 !memcmp(&valid_rects
[0], &data
->client_rect
, sizeof(RECT
)))
1564 /* A Cocoa window's bits are moved automatically */
1565 if (!window
&& (x_offset
!= 0 || y_offset
!= 0))
1567 release_win_data(data
);
1568 move_window_bits(hwnd
, window
, &old_whole_rect
, visible_rect
,
1569 &old_client_rect
, client_rect
, window_rect
);
1570 if (!(data
= get_win_data(hwnd
))) return;
1575 release_win_data(data
);
1576 move_window_bits(hwnd
, window
, &valid_rects
[1], &valid_rects
[0],
1577 &old_client_rect
, client_rect
, window_rect
);
1578 if (!(data
= get_win_data(hwnd
))) return;
1584 if (!data
->cocoa_window
) goto done
;
1586 if (data
->on_screen
)
1588 if ((swp_flags
& SWP_HIDEWINDOW
) && !(new_style
& WS_VISIBLE
))
1592 /* check if we are currently processing an event relevant to this window */
1593 if (!thread_data
|| !thread_data
->current_event
||
1594 thread_data
->current_event
->window
!= data
->cocoa_window
||
1595 (thread_data
->current_event
->type
!= WINDOW_FRAME_CHANGED
&&
1596 thread_data
->current_event
->type
!= WINDOW_DID_UNMINIMIZE
))
1598 sync_window_position(data
, swp_flags
, &old_window_rect
, &old_whole_rect
);
1599 set_cocoa_window_properties(data
);
1602 if (new_style
& WS_VISIBLE
)
1604 if (!data
->on_screen
|| (swp_flags
& (SWP_FRAMECHANGED
|SWP_STATECHANGED
)))
1605 set_cocoa_window_properties(data
);
1607 /* layered windows are not shown until their attributes are set */
1608 if (!data
->on_screen
&&
1609 (data
->layered
|| !(GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_LAYERED
)))
1614 release_win_data(data
);
1618 /***********************************************************************
1619 * macdrv_window_close_requested
1621 * Handler for WINDOW_CLOSE_REQUESTED events.
1623 void macdrv_window_close_requested(HWND hwnd
)
1625 /* Ignore the delete window request if the window has been disabled. This
1626 * is to disallow applications from being closed while in a modal state.
1628 if (IsWindowEnabled(hwnd
))
1632 if (GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
) return;
1633 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1636 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1637 if (state
== 0xFFFFFFFF || (state
& (MF_DISABLED
| MF_GRAYED
)))
1640 if (GetActiveWindow() != hwnd
)
1642 LRESULT ma
= SendMessageW(hwnd
, WM_MOUSEACTIVATE
,
1643 (WPARAM
)GetAncestor(hwnd
, GA_ROOT
),
1644 MAKELPARAM(HTCLOSE
, WM_NCLBUTTONDOWN
));
1647 case MA_NOACTIVATEANDEAT
:
1648 case MA_ACTIVATEANDEAT
:
1654 SetActiveWindow(hwnd
);
1657 WARN("unknown WM_MOUSEACTIVATE code %d\n", (int) ma
);
1662 PostMessageW(hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1667 /***********************************************************************
1668 * macdrv_window_frame_changed
1670 * Handler for WINDOW_FRAME_CHANGED events.
1672 void macdrv_window_frame_changed(HWND hwnd
, const macdrv_event
*event
)
1674 struct macdrv_win_data
*data
;
1677 UINT flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
1681 if (!(data
= get_win_data(hwnd
))) return;
1682 if (!data
->on_screen
|| data
->minimized
)
1684 release_win_data(data
);
1690 parent
= GetAncestor(hwnd
, GA_PARENT
);
1692 TRACE("win %p/%p new Cocoa frame %s fullscreen %d in_resize %d\n", hwnd
, data
->cocoa_window
,
1693 wine_dbgstr_cgrect(event
->window_frame_changed
.frame
),
1694 event
->window_frame_changed
.fullscreen
, event
->window_frame_changed
.in_resize
);
1696 rect
= rect_from_cgrect(event
->window_frame_changed
.frame
);
1697 macdrv_mac_to_window_rect(data
, &rect
);
1698 MapWindowPoints(0, parent
, (POINT
*)&rect
, 2);
1700 width
= rect
.right
- rect
.left
;
1701 height
= rect
.bottom
- rect
.top
;
1703 if (data
->window_rect
.left
== rect
.left
&& data
->window_rect
.top
== rect
.top
)
1704 flags
|= SWP_NOMOVE
;
1706 TRACE("%p moving from (%d,%d) to (%d,%d)\n", hwnd
, data
->window_rect
.left
,
1707 data
->window_rect
.top
, rect
.left
, rect
.top
);
1709 if ((data
->window_rect
.right
- data
->window_rect
.left
== width
&&
1710 data
->window_rect
.bottom
- data
->window_rect
.top
== height
) ||
1711 (IsRectEmpty(&data
->window_rect
) && width
== 1 && height
== 1))
1712 flags
|= SWP_NOSIZE
;
1714 TRACE("%p resizing from (%dx%d) to (%dx%d)\n", hwnd
, data
->window_rect
.right
- data
->window_rect
.left
,
1715 data
->window_rect
.bottom
- data
->window_rect
.top
, width
, height
);
1717 release_win_data(data
);
1719 if (event
->window_frame_changed
.fullscreen
)
1720 flags
|= SWP_NOSENDCHANGING
;
1721 if (!(flags
& SWP_NOSIZE
) || !(flags
& SWP_NOMOVE
))
1723 if (!event
->window_frame_changed
.in_resize
)
1724 SendMessageW(hwnd
, WM_ENTERSIZEMOVE
, 0, 0);
1725 SetWindowPos(hwnd
, 0, rect
.left
, rect
.top
, width
, height
, flags
);
1726 if (!event
->window_frame_changed
.in_resize
)
1727 SendMessageW(hwnd
, WM_EXITSIZEMOVE
, 0, 0);
1732 /***********************************************************************
1733 * macdrv_window_got_focus
1735 * Handler for WINDOW_GOT_FOCUS events.
1737 void macdrv_window_got_focus(HWND hwnd
, const macdrv_event
*event
)
1739 LONG style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1743 TRACE("win %p/%p serial %lu enabled %d visible %d style %08x focus %p active %p fg %p\n",
1744 hwnd
, event
->window
, event
->window_got_focus
.serial
, IsWindowEnabled(hwnd
),
1745 IsWindowVisible(hwnd
), style
, GetFocus(), GetActiveWindow(), GetForegroundWindow());
1747 if (can_activate_window(hwnd
) && !(style
& WS_MINIMIZE
))
1749 /* simulate a mouse click on the caption to find out
1750 * whether the window wants to be activated */
1751 LRESULT ma
= SendMessageW(hwnd
, WM_MOUSEACTIVATE
,
1752 (WPARAM
)GetAncestor(hwnd
, GA_ROOT
),
1753 MAKELONG(HTCAPTION
,WM_LBUTTONDOWN
));
1754 if (ma
!= MA_NOACTIVATEANDEAT
&& ma
!= MA_NOACTIVATE
)
1756 TRACE("setting foreground window to %p\n", hwnd
);
1757 SetForegroundWindow(hwnd
);
1762 TRACE("win %p/%p rejecting focus\n", hwnd
, event
->window
);
1763 macdrv_window_rejected_focus(event
);
1767 /***********************************************************************
1768 * macdrv_window_lost_focus
1770 * Handler for WINDOW_LOST_FOCUS events.
1772 void macdrv_window_lost_focus(HWND hwnd
, const macdrv_event
*event
)
1776 TRACE("win %p/%p fg %p\n", hwnd
, event
->window
, GetForegroundWindow());
1778 if (hwnd
== GetForegroundWindow())
1780 SendMessageW(hwnd
, WM_CANCELMODE
, 0, 0);
1781 if (hwnd
== GetForegroundWindow())
1782 SetForegroundWindow(GetDesktopWindow());
1787 /***********************************************************************
1788 * macdrv_app_deactivated
1790 * Handler for APP_DEACTIVATED events.
1792 void macdrv_app_deactivated(void)
1794 if (GetActiveWindow() == GetForegroundWindow())
1796 TRACE("setting fg to desktop\n");
1797 SetForegroundWindow(GetDesktopWindow());
1802 /***********************************************************************
1803 * macdrv_window_minimize_requested
1805 * Handler for WINDOW_MINIMIZE_REQUESTED events.
1807 void macdrv_window_minimize_requested(HWND hwnd
)
1812 style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1813 if (!(style
& WS_MINIMIZEBOX
) || (style
& (WS_DISABLED
| WS_MINIMIZE
)))
1815 TRACE("not minimizing win %p style 0x%08x\n", hwnd
, style
);
1819 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1822 UINT state
= GetMenuState(hSysMenu
, SC_MINIMIZE
, MF_BYCOMMAND
);
1823 if (state
== 0xFFFFFFFF || (state
& (MF_DISABLED
| MF_GRAYED
)))
1825 TRACE("not minimizing win %p menu state 0x%08x\n", hwnd
, state
);
1830 if (GetActiveWindow() != hwnd
)
1832 LRESULT ma
= SendMessageW(hwnd
, WM_MOUSEACTIVATE
, (WPARAM
)GetAncestor(hwnd
, GA_ROOT
),
1833 MAKELPARAM(HTMINBUTTON
, WM_NCLBUTTONDOWN
));
1836 case MA_NOACTIVATEANDEAT
:
1837 case MA_ACTIVATEANDEAT
:
1838 TRACE("not minimizing win %p mouse-activate result %ld\n", hwnd
, ma
);
1844 SetActiveWindow(hwnd
);
1847 WARN("unknown WM_MOUSEACTIVATE code %ld\n", ma
);
1852 TRACE("minimizing win %p\n", hwnd
);
1853 SendMessageW(hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
1857 /***********************************************************************
1858 * macdrv_window_did_unminimize
1860 * Handler for WINDOW_DID_UNMINIMIZE events.
1862 void macdrv_window_did_unminimize(HWND hwnd
)
1864 struct macdrv_win_data
*data
;
1867 TRACE("win %p\n", hwnd
);
1869 if (!(data
= get_win_data(hwnd
))) return;
1870 if (!data
->minimized
) goto done
;
1872 style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1874 data
->minimized
= FALSE
;
1875 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1877 TRACE("restoring win %p/%p\n", hwnd
, data
->cocoa_window
);
1878 release_win_data(data
);
1879 SendMessageW(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
1883 TRACE("not restoring win %p/%p style %08x\n", hwnd
, data
->cocoa_window
, style
);
1886 release_win_data(data
);
1890 /***********************************************************************
1891 * macdrv_window_brought_forward
1893 * Handler for WINDOW_BROUGHT_FORWARD events.
1895 void macdrv_window_brought_forward(HWND hwnd
)
1897 TRACE("win %p\n", hwnd
);
1898 SetWindowPos(hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1902 /***********************************************************************
1903 * macdrv_window_resize_ended
1905 * Handler for WINDOW_RESIZE_ENDED events.
1907 void macdrv_window_resize_ended(HWND hwnd
)
1909 TRACE("hwnd %p\n", hwnd
);
1910 SendMessageW(hwnd
, WM_EXITSIZEMOVE
, 0, 0);
1925 static BOOL CALLBACK
get_process_windows(HWND hwnd
, LPARAM lp
)
1927 struct quit_info
*qi
= (struct quit_info
*)lp
;
1930 GetWindowThreadProcessId(hwnd
, &pid
);
1931 if (pid
== GetCurrentProcessId())
1933 if (qi
->count
>= qi
->capacity
)
1935 UINT new_cap
= qi
->capacity
* 2;
1936 HWND
*new_wins
= HeapReAlloc(GetProcessHeap(), 0, qi
->wins
,
1937 new_cap
* sizeof(*qi
->wins
));
1938 if (!new_wins
) return FALSE
;
1939 qi
->wins
= new_wins
;
1940 qi
->capacity
= new_cap
;
1943 qi
->wins
[qi
->count
++] = hwnd
;
1950 static void CALLBACK
quit_callback(HWND hwnd
, UINT msg
, ULONG_PTR data
, LRESULT result
)
1952 struct quit_info
*qi
= (struct quit_info
*)data
;
1956 if (msg
== WM_QUERYENDSESSION
)
1958 TRACE("got WM_QUERYENDSESSION result %ld from win %p (%u of %u done)\n", result
,
1959 hwnd
, qi
->done
, qi
->count
);
1961 if (!result
&& qi
->result
)
1965 /* On the first FALSE from WM_QUERYENDSESSION, we already know the
1966 ultimate reply. Might as well tell Cocoa now. */
1970 TRACE("giving quit reply %d\n", qi
->result
);
1971 macdrv_quit_reply(qi
->result
);
1975 if (qi
->done
>= qi
->count
)
1980 for (i
= 0; i
< qi
->count
; i
++)
1982 TRACE("sending WM_ENDSESSION to win %p result %d flags 0x%08x\n", qi
->wins
[i
],
1983 qi
->result
, qi
->flags
);
1984 if (!SendMessageCallbackW(qi
->wins
[i
], WM_ENDSESSION
, qi
->result
, qi
->flags
,
1985 quit_callback
, (ULONG_PTR
)qi
))
1987 WARN("failed to send WM_ENDSESSION to win %p; error 0x%08x\n",
1988 qi
->wins
[i
], GetLastError());
1989 quit_callback(qi
->wins
[i
], WM_ENDSESSION
, (ULONG_PTR
)qi
, 0);
1994 else /* WM_ENDSESSION */
1996 TRACE("finished WM_ENDSESSION for win %p (%u of %u done)\n", hwnd
, qi
->done
, qi
->count
);
1998 if (qi
->done
>= qi
->count
)
2002 TRACE("giving quit reply %d\n", qi
->result
);
2003 macdrv_quit_reply(qi
->result
);
2006 TRACE("%sterminating process\n", qi
->result
? "" : "not ");
2008 TerminateProcess(GetCurrentProcess(), 0);
2010 HeapFree(GetProcessHeap(), 0, qi
->wins
);
2011 HeapFree(GetProcessHeap(), 0, qi
);
2017 /***********************************************************************
2018 * macdrv_app_quit_requested
2020 * Handler for APP_QUIT_REQUESTED events.
2022 void macdrv_app_quit_requested(const macdrv_event
*event
)
2024 struct quit_info
*qi
;
2027 TRACE("reason %d\n", event
->app_quit_requested
.reason
);
2029 qi
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qi
));
2034 qi
->wins
= HeapAlloc(GetProcessHeap(), 0, qi
->capacity
* sizeof(*qi
->wins
));
2035 qi
->count
= qi
->done
= 0;
2037 if (!qi
->wins
|| !EnumWindows(get_process_windows
, (LPARAM
)qi
))
2040 switch (event
->app_quit_requested
.reason
)
2042 case QUIT_REASON_LOGOUT
:
2044 qi
->flags
= ENDSESSION_LOGOFF
;
2046 case QUIT_REASON_RESTART
:
2047 case QUIT_REASON_SHUTDOWN
:
2053 qi
->replied
= FALSE
;
2055 for (i
= 0; i
< qi
->count
; i
++)
2057 TRACE("sending WM_QUERYENDSESSION to win %p\n", qi
->wins
[i
]);
2058 if (!SendMessageCallbackW(qi
->wins
[i
], WM_QUERYENDSESSION
, 0, qi
->flags
,
2059 quit_callback
, (ULONG_PTR
)qi
))
2061 WARN("failed to send WM_QUERYENDSESSION to win %p; error 0x%08x; assuming refusal\n",
2062 qi
->wins
[i
], GetLastError());
2063 quit_callback(qi
->wins
[i
], WM_QUERYENDSESSION
, (ULONG_PTR
)qi
, FALSE
);
2067 /* quit_callback() will clean up qi */
2071 WARN("failed to allocate window list\n");
2074 HeapFree(GetProcessHeap(), 0, qi
->wins
);
2075 HeapFree(GetProcessHeap(), 0, qi
);
2077 macdrv_quit_reply(FALSE
);
2081 /***********************************************************************
2082 * query_resize_start
2084 * Handler for QUERY_RESIZE_START query.
2086 BOOL
query_resize_start(HWND hwnd
)
2088 TRACE("hwnd %p\n", hwnd
);
2090 sync_window_min_max_info(hwnd
);
2091 SendMessageW(hwnd
, WM_ENTERSIZEMOVE
, 0, 0);
2097 /***********************************************************************
2098 * query_min_max_info
2100 * Handler for QUERY_MIN_MAX_INFO query.
2102 BOOL
query_min_max_info(HWND hwnd
)
2104 TRACE("hwnd %p\n", hwnd
);
2105 sync_window_min_max_info(hwnd
);