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
;
46 void CDECL
macdrv_SetFocus(HWND hwnd
);
49 /***********************************************************************
50 * get_cocoa_window_features
52 static void get_cocoa_window_features(struct macdrv_win_data
*data
,
53 DWORD style
, DWORD ex_style
,
54 struct macdrv_window_features
* wf
)
56 memset(wf
, 0, sizeof(*wf
));
58 if (IsRectEmpty(&data
->window_rect
)) return;
60 if ((style
& WS_CAPTION
) == WS_CAPTION
&& !(ex_style
& WS_EX_LAYERED
))
66 if (style
& WS_SYSMENU
) wf
->close_button
= 1;
67 if (style
& WS_MINIMIZEBOX
) wf
->minimize_button
= 1;
68 if (style
& WS_MAXIMIZEBOX
) wf
->resizable
= 1;
69 if (ex_style
& WS_EX_TOOLWINDOW
) wf
->utility
= 1;
72 if (ex_style
& WS_EX_DLGMODALFRAME
) wf
->shadow
= 1;
73 else if (style
& WS_THICKFRAME
)
76 if (!data
->shaped
) wf
->resizable
= 1;
78 else if ((style
& (WS_DLGFRAME
|WS_BORDER
)) == WS_DLGFRAME
) wf
->shadow
= 1;
82 /*******************************************************************
85 * Check if we can activate the specified window.
87 static inline BOOL
can_activate_window(HWND hwnd
)
89 LONG style
= GetWindowLongW(hwnd
, GWL_STYLE
);
92 if (!(style
& WS_VISIBLE
)) return FALSE
;
93 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
94 if (style
& WS_MINIMIZE
) return FALSE
;
95 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_NOACTIVATE
) return FALSE
;
96 if (hwnd
== GetDesktopWindow()) return FALSE
;
97 if (GetWindowRect(hwnd
, &rect
) && IsRectEmpty(&rect
)) return FALSE
;
98 return !(style
& WS_DISABLED
);
102 /***********************************************************************
103 * get_cocoa_window_state
105 static void get_cocoa_window_state(struct macdrv_win_data
*data
,
106 DWORD style
, DWORD ex_style
,
107 struct macdrv_window_state
* state
)
109 memset(state
, 0, sizeof(*state
));
110 state
->disabled
= (style
& WS_DISABLED
) != 0;
111 state
->no_activate
= !can_activate_window(data
->hwnd
);
112 state
->floating
= (ex_style
& WS_EX_TOPMOST
) != 0;
113 state
->excluded_by_expose
= state
->excluded_by_cycle
=
114 !(ex_style
& WS_EX_APPWINDOW
) &&
115 (GetWindow(data
->hwnd
, GW_OWNER
) || (ex_style
& (WS_EX_TOOLWINDOW
| WS_EX_NOACTIVATE
)));
116 state
->minimized
= (style
& WS_MINIMIZE
) != 0;
120 /***********************************************************************
121 * get_mac_rect_offset
123 * Helper for macdrv_window_to_mac_rect and macdrv_mac_to_window_rect.
125 static void get_mac_rect_offset(struct macdrv_win_data
*data
, DWORD style
, RECT
*rect
)
127 DWORD ex_style
, style_mask
= 0, ex_style_mask
= 0;
129 rect
->top
= rect
->bottom
= rect
->left
= rect
->right
= 0;
131 ex_style
= GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
);
135 struct macdrv_window_features wf
;
136 get_cocoa_window_features(data
, style
, ex_style
, &wf
);
138 if (wf
.title_bar
) style_mask
|= WS_CAPTION
;
141 style_mask
|= WS_DLGFRAME
| WS_THICKFRAME
;
142 ex_style_mask
|= WS_EX_DLGMODALFRAME
;
146 AdjustWindowRectEx(rect
, style
& style_mask
, FALSE
, ex_style
& ex_style_mask
);
148 TRACE("%p/%p style %08x ex_style %08x shaped %d -> %s\n", data
->hwnd
, data
->cocoa_window
,
149 style
, ex_style
, data
->shaped
, wine_dbgstr_rect(rect
));
153 /***********************************************************************
154 * macdrv_window_to_mac_rect
156 * Convert a rect from client to Mac window coordinates
158 static void macdrv_window_to_mac_rect(struct macdrv_win_data
*data
, DWORD style
, RECT
*rect
)
162 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return;
163 if (IsRectEmpty(rect
)) return;
165 get_mac_rect_offset(data
, style
, &rc
);
167 rect
->left
-= rc
.left
;
168 rect
->right
-= rc
.right
;
170 rect
->bottom
-= rc
.bottom
;
171 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
172 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
176 /***********************************************************************
177 * macdrv_mac_to_window_rect
179 * Opposite of macdrv_window_to_mac_rect
181 static void macdrv_mac_to_window_rect(struct macdrv_win_data
*data
, RECT
*rect
)
184 DWORD style
= GetWindowLongW(data
->hwnd
, GWL_STYLE
);
186 if ((style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return;
187 if (IsRectEmpty(rect
)) return;
189 get_mac_rect_offset(data
, style
, &rc
);
191 rect
->left
+= rc
.left
;
192 rect
->right
+= rc
.right
;
194 rect
->bottom
+= rc
.bottom
;
195 if (rect
->top
>= rect
->bottom
) rect
->bottom
= rect
->top
+ 1;
196 if (rect
->left
>= rect
->right
) rect
->right
= rect
->left
+ 1;
200 /***********************************************************************
201 * constrain_window_frame
203 * Alter a window frame rectangle to fit within a) Cocoa's documented
204 * limits, and b) sane sizes, like twice the desktop rect.
206 static void constrain_window_frame(CGRect
* frame
)
208 CGRect desktop_rect
= macdrv_get_desktop_rect();
209 int max_width
, max_height
;
211 max_width
= min(32000, 2 * CGRectGetWidth(desktop_rect
));
212 max_height
= min(32000, 2 * CGRectGetHeight(desktop_rect
));
214 if (frame
->origin
.x
< -16000) frame
->origin
.x
= -16000;
215 if (frame
->origin
.y
< -16000) frame
->origin
.y
= -16000;
216 if (frame
->origin
.x
> 16000) frame
->origin
.x
= 16000;
217 if (frame
->origin
.y
> 16000) frame
->origin
.y
= 16000;
218 if (frame
->size
.width
> max_width
) frame
->size
.width
= max_width
;
219 if (frame
->size
.height
> max_height
) frame
->size
.height
= max_height
;
223 /***********************************************************************
226 static struct macdrv_win_data
*alloc_win_data(HWND hwnd
)
228 struct macdrv_win_data
*data
;
230 if ((data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
))))
233 data
->color_key
= CLR_INVALID
;
234 EnterCriticalSection(&win_data_section
);
236 win_datas
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
);
237 CFDictionarySetValue(win_datas
, hwnd
, data
);
243 /***********************************************************************
246 * Lock and return the data structure associated with a window.
248 struct macdrv_win_data
*get_win_data(HWND hwnd
)
250 struct macdrv_win_data
*data
;
252 if (!hwnd
) return NULL
;
253 EnterCriticalSection(&win_data_section
);
254 if (win_datas
&& (data
= (struct macdrv_win_data
*)CFDictionaryGetValue(win_datas
, hwnd
)))
256 LeaveCriticalSection(&win_data_section
);
261 /***********************************************************************
264 * Release the data returned by get_win_data.
266 void release_win_data(struct macdrv_win_data
*data
)
268 if (data
) LeaveCriticalSection(&win_data_section
);
272 /***********************************************************************
273 * macdrv_get_cocoa_window
275 * Return the Mac window associated with the full area of a window
277 macdrv_window
macdrv_get_cocoa_window(HWND hwnd
, BOOL require_on_screen
)
279 struct macdrv_win_data
*data
= get_win_data(hwnd
);
280 macdrv_window ret
= NULL
;
281 if (data
&& (data
->on_screen
|| !require_on_screen
))
282 ret
= data
->cocoa_window
;
283 release_win_data(data
);
288 /***********************************************************************
289 * set_cocoa_window_properties
291 * Set the window properties for a Cocoa window based on its Windows
294 static void set_cocoa_window_properties(struct macdrv_win_data
*data
)
296 DWORD style
, ex_style
;
298 macdrv_window owner_win
;
299 struct macdrv_window_features wf
;
300 struct macdrv_window_state state
;
302 style
= GetWindowLongW(data
->hwnd
, GWL_STYLE
);
303 ex_style
= GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
);
305 owner
= GetWindow(data
->hwnd
, GW_OWNER
);
306 owner_win
= macdrv_get_cocoa_window(owner
, TRUE
);
307 macdrv_set_cocoa_parent_window(data
->cocoa_window
, owner_win
);
309 get_cocoa_window_features(data
, style
, ex_style
, &wf
);
310 macdrv_set_cocoa_window_features(data
->cocoa_window
, &wf
);
312 get_cocoa_window_state(data
, style
, ex_style
, &state
);
313 macdrv_set_cocoa_window_state(data
->cocoa_window
, &state
);
314 data
->minimized
= state
.minimized
;
318 /***********************************************************************
321 * Update the window region.
323 static void sync_window_region(struct macdrv_win_data
*data
, HRGN win_region
)
325 HRGN hrgn
= win_region
;
326 RGNDATA
*region_data
;
330 if (!data
->cocoa_window
) return;
331 data
->shaped
= FALSE
;
333 if (hrgn
== (HRGN
)1) /* hack: win_region == 1 means retrieve region from server */
335 if (!(hrgn
= CreateRectRgn(0, 0, 0, 0))) return;
336 if (GetWindowRgn(data
->hwnd
, hrgn
) == ERROR
)
343 if (hrgn
&& GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
)
344 MirrorRgn(data
->hwnd
, hrgn
);
347 OffsetRgn(hrgn
, data
->window_rect
.left
- data
->whole_rect
.left
,
348 data
->window_rect
.top
- data
->whole_rect
.top
);
350 region_data
= get_region_data(hrgn
, 0);
353 rects
= (CGRect
*)region_data
->Buffer
;
354 count
= region_data
->rdh
.nCount
;
355 /* Special case optimization. If the region entirely encloses the Cocoa
356 window, it's the same as there being no region. It's potentially
357 hard/slow to test this for arbitrary regions, so we just check for
358 very simple regions. */
359 if (count
== 1 && CGRectContainsRect(rects
[0], cgrect_from_rect(data
->whole_rect
)))
361 TRACE("optimizing for simple region that contains Cocoa content rect\n");
372 TRACE("win %p/%p win_region %p rects %p count %d\n", data
->hwnd
, data
->cocoa_window
, win_region
, rects
, count
);
373 macdrv_set_window_shape(data
->cocoa_window
, rects
, count
);
375 HeapFree(GetProcessHeap(), 0, region_data
);
376 data
->shaped
= (region_data
!= NULL
);
378 if (hrgn
&& hrgn
!= win_region
) DeleteObject(hrgn
);
382 /***********************************************************************
385 static inline void add_bounds_rect(RECT
*bounds
, const RECT
*rect
)
387 if (rect
->left
>= rect
->right
|| rect
->top
>= rect
->bottom
) return;
388 bounds
->left
= min(bounds
->left
, rect
->left
);
389 bounds
->top
= min(bounds
->top
, rect
->top
);
390 bounds
->right
= max(bounds
->right
, rect
->right
);
391 bounds
->bottom
= max(bounds
->bottom
, rect
->bottom
);
395 /***********************************************************************
396 * sync_window_opacity
398 static void sync_window_opacity(struct macdrv_win_data
*data
, COLORREF key
, BYTE alpha
,
399 BOOL per_pixel_alpha
, DWORD flags
)
401 CGFloat opacity
= 1.0;
402 BOOL needs_flush
= FALSE
;
404 if (flags
& LWA_ALPHA
) opacity
= alpha
/ 255.0;
406 TRACE("setting window %p/%p alpha to %g\n", data
->hwnd
, data
->cocoa_window
, opacity
);
407 macdrv_set_window_alpha(data
->cocoa_window
, opacity
);
409 if (flags
& LWA_COLORKEY
)
411 /* FIXME: treat PALETTEINDEX and DIBINDEX as black */
412 if ((key
& (1 << 24)) || key
>> 16 == 0x10ff)
418 if (data
->color_key
!= key
)
420 if (key
== CLR_INVALID
)
422 TRACE("clearing color-key for window %p/%p\n", data
->hwnd
, data
->cocoa_window
);
423 macdrv_clear_window_color_key(data
->cocoa_window
);
427 TRACE("setting color-key for window %p/%p to RGB %d,%d,%d\n", data
->hwnd
, data
->cocoa_window
,
428 GetRValue(key
), GetGValue(key
), GetBValue(key
));
429 macdrv_set_window_color_key(data
->cocoa_window
, GetRValue(key
), GetGValue(key
), GetBValue(key
));
432 data
->color_key
= key
;
436 if (!data
->per_pixel_alpha
!= !per_pixel_alpha
)
438 macdrv_window_use_per_pixel_alpha(data
->cocoa_window
, per_pixel_alpha
);
439 data
->per_pixel_alpha
= per_pixel_alpha
;
443 if (needs_flush
&& data
->surface
)
448 rect
= data
->whole_rect
;
449 OffsetRect(&rect
, -data
->whole_rect
.left
, -data
->whole_rect
.top
);
450 data
->surface
->funcs
->lock(data
->surface
);
451 bounds
= data
->surface
->funcs
->get_bounds(data
->surface
);
452 add_bounds_rect(bounds
, &rect
);
453 data
->surface
->funcs
->unlock(data
->surface
);
458 /**********************************************************************
459 * create_cocoa_window
461 * Create the whole Mac window for a given window
463 static void create_cocoa_window(struct macdrv_win_data
*data
)
465 struct macdrv_thread_data
*thread_data
= macdrv_init_thread_data();
467 struct macdrv_window_features wf
;
469 DWORD style
, ex_style
;
475 if ((win_rgn
= CreateRectRgn(0, 0, 0, 0)) &&
476 GetWindowRgn(data
->hwnd
, win_rgn
) == ERROR
)
478 DeleteObject(win_rgn
);
481 data
->shaped
= (win_rgn
!= 0);
483 style
= GetWindowLongW(data
->hwnd
, GWL_STYLE
);
484 ex_style
= GetWindowLongW(data
->hwnd
, GWL_EXSTYLE
);
486 data
->whole_rect
= data
->window_rect
;
487 macdrv_window_to_mac_rect(data
, style
, &data
->whole_rect
);
489 memset(&wf
, 0, sizeof(wf
));
490 get_cocoa_window_features(data
, style
, ex_style
, &wf
);
492 frame
= cgrect_from_rect(data
->whole_rect
);
493 constrain_window_frame(&frame
);
495 TRACE("creating %p window %s whole %s client %s\n", data
->hwnd
, wine_dbgstr_rect(&data
->window_rect
),
496 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_rect(&data
->client_rect
));
498 data
->cocoa_window
= macdrv_create_cocoa_window(&wf
, frame
, data
->hwnd
, thread_data
->queue
);
499 if (!data
->cocoa_window
) goto done
;
501 set_cocoa_window_properties(data
);
503 /* set the window text */
504 if (!InternalGetWindowText(data
->hwnd
, text
, sizeof(text
)/sizeof(WCHAR
))) text
[0] = 0;
505 macdrv_set_cocoa_window_title(data
->cocoa_window
, text
, strlenW(text
));
507 /* set the window region */
508 if (win_rgn
) sync_window_region(data
, win_rgn
);
510 /* set the window opacity */
511 if (!GetLayeredWindowAttributes(data
->hwnd
, &key
, &alpha
, &layered_flags
)) layered_flags
= 0;
512 sync_window_opacity(data
, key
, alpha
, FALSE
, layered_flags
);
515 if (win_rgn
) DeleteObject(win_rgn
);
519 /**********************************************************************
520 * destroy_cocoa_window
522 * Destroy the whole Mac window for a given window.
524 static void destroy_cocoa_window(struct macdrv_win_data
*data
)
526 if (!data
->cocoa_window
) return;
528 TRACE("win %p Cocoa win %p\n", data
->hwnd
, data
->cocoa_window
);
530 macdrv_destroy_cocoa_window(data
->cocoa_window
);
531 data
->cocoa_window
= 0;
532 data
->on_screen
= FALSE
;
533 data
->color_key
= CLR_INVALID
;
534 if (data
->surface
) window_surface_release(data
->surface
);
535 data
->surface
= NULL
;
539 /***********************************************************************
540 * macdrv_create_win_data
542 * Create a Mac data window structure for an existing window.
544 static struct macdrv_win_data
*macdrv_create_win_data(HWND hwnd
, const RECT
*window_rect
,
545 const RECT
*client_rect
)
547 struct macdrv_win_data
*data
;
550 if (GetWindowThreadProcessId(hwnd
, NULL
) != GetCurrentThreadId()) return NULL
;
552 if (!(parent
= GetAncestor(hwnd
, GA_PARENT
))) /* desktop */
554 macdrv_init_thread_data();
558 /* don't create win data for HWND_MESSAGE windows */
559 if (parent
!= GetDesktopWindow() && !GetAncestor(parent
, GA_PARENT
)) return NULL
;
561 if (!(data
= alloc_win_data(hwnd
))) return NULL
;
563 data
->whole_rect
= data
->window_rect
= *window_rect
;
564 data
->client_rect
= *client_rect
;
566 if (parent
== GetDesktopWindow())
568 create_cocoa_window(data
);
569 TRACE("win %p/%p window %s whole %s client %s\n",
570 hwnd
, data
->cocoa_window
, wine_dbgstr_rect(&data
->window_rect
),
571 wine_dbgstr_rect(&data
->whole_rect
), wine_dbgstr_rect(&data
->client_rect
));
578 /***********************************************************************
581 static void show_window(struct macdrv_win_data
*data
)
585 macdrv_window prev_window
= NULL
;
586 macdrv_window next_window
= NULL
;
588 /* find window that this one must be after */
589 prev
= GetWindow(data
->hwnd
, GW_HWNDPREV
);
590 while (prev
&& !((GetWindowLongW(prev
, GWL_STYLE
) & WS_VISIBLE
) &&
591 (prev_window
= macdrv_get_cocoa_window(prev
, TRUE
))))
592 prev
= GetWindow(prev
, GW_HWNDPREV
);
595 /* find window that this one must be before */
596 next
= GetWindow(data
->hwnd
, GW_HWNDNEXT
);
597 while (next
&& !((GetWindowLongW(next
, GWL_STYLE
) & WS_VISIBLE
) &&
598 (next_window
= macdrv_get_cocoa_window(next
, TRUE
))))
599 next
= GetWindow(next
, GW_HWNDNEXT
);
602 TRACE("win %p/%p below %p/%p above %p/%p\n",
603 data
->hwnd
, data
->cocoa_window
, prev
, prev_window
, next
, next_window
);
605 data
->on_screen
= macdrv_order_cocoa_window(data
->cocoa_window
, prev_window
, next_window
);
608 HWND hwndFocus
= GetFocus();
609 if (hwndFocus
&& (data
->hwnd
== hwndFocus
|| IsChild(data
->hwnd
, hwndFocus
)))
610 macdrv_SetFocus(hwndFocus
);
615 /***********************************************************************
618 static void hide_window(struct macdrv_win_data
*data
)
620 TRACE("win %p/%p\n", data
->hwnd
, data
->cocoa_window
);
622 macdrv_hide_cocoa_window(data
->cocoa_window
);
623 data
->on_screen
= FALSE
;
627 /***********************************************************************
630 * Calls GetRegionData on the given region and converts the rectangle
631 * array to CGRect format. The returned buffer must be freed by
632 * caller using HeapFree(GetProcessHeap(),...).
633 * If hdc_lptodp is not 0, the rectangles are converted through LPtoDP.
635 RGNDATA
*get_region_data(HRGN hrgn
, HDC hdc_lptodp
)
643 if (!hrgn
|| !(size
= GetRegionData(hrgn
, 0, NULL
))) return NULL
;
644 if (sizeof(CGRect
) > sizeof(RECT
))
646 /* add extra size for CGRect array */
647 int count
= (size
- sizeof(RGNDATAHEADER
)) / sizeof(RECT
);
648 size
+= count
* (sizeof(CGRect
) - sizeof(RECT
));
650 if (!(data
= HeapAlloc(GetProcessHeap(), 0, size
))) return NULL
;
651 if (!GetRegionData(hrgn
, size
, data
))
653 HeapFree(GetProcessHeap(), 0, data
);
657 rect
= (RECT
*)data
->Buffer
;
658 cgrect
= (CGRect
*)data
->Buffer
;
659 if (hdc_lptodp
) /* map to device coordinates */
661 LPtoDP(hdc_lptodp
, (POINT
*)rect
, data
->rdh
.nCount
* 2);
662 for (i
= 0; i
< data
->rdh
.nCount
; i
++)
664 if (rect
[i
].right
< rect
[i
].left
)
666 INT tmp
= rect
[i
].right
;
667 rect
[i
].right
= rect
[i
].left
;
670 if (rect
[i
].bottom
< rect
[i
].top
)
672 INT tmp
= rect
[i
].bottom
;
673 rect
[i
].bottom
= rect
[i
].top
;
679 if (sizeof(CGRect
) > sizeof(RECT
))
681 /* need to start from the end */
682 for (i
= data
->rdh
.nCount
-1; i
>= 0; i
--)
683 cgrect
[i
] = cgrect_from_rect(rect
[i
]);
687 for (i
= 0; i
< data
->rdh
.nCount
; i
++)
688 cgrect
[i
] = cgrect_from_rect(rect
[i
]);
694 /***********************************************************************
695 * sync_window_position
697 * Synchronize the Mac window position with the Windows one
699 static void sync_window_position(struct macdrv_win_data
*data
, UINT swp_flags
)
703 if (data
->minimized
) return;
705 frame
= cgrect_from_rect(data
->whole_rect
);
706 constrain_window_frame(&frame
);
708 data
->on_screen
= macdrv_set_cocoa_window_frame(data
->cocoa_window
, &frame
);
709 if (data
->shaped
) sync_window_region(data
, (HRGN
)1);
711 TRACE("win %p/%p pos %s\n", data
->hwnd
, data
->cocoa_window
,
712 wine_dbgstr_rect(&data
->whole_rect
));
714 if (data
->on_screen
&& (!(swp_flags
& SWP_NOZORDER
) || (swp_flags
& SWP_SHOWWINDOW
)))
719 /***********************************************************************
722 * Move the window bits when a window is moved.
724 static void move_window_bits(HWND hwnd
, macdrv_window window
, const RECT
*old_rect
, const RECT
*new_rect
,
725 const RECT
*old_client_rect
, const RECT
*new_client_rect
,
726 const RECT
*new_window_rect
)
728 RECT src_rect
= *old_rect
;
729 RECT dst_rect
= *new_rect
;
730 HDC hdc_src
, hdc_dst
;
736 OffsetRect(&dst_rect
, -new_window_rect
->left
, -new_window_rect
->top
);
737 parent
= GetAncestor(hwnd
, GA_PARENT
);
738 hdc_src
= GetDCEx(parent
, 0, DCX_CACHE
);
739 hdc_dst
= GetDCEx(hwnd
, 0, DCX_CACHE
| DCX_WINDOW
);
743 OffsetRect(&dst_rect
, -new_client_rect
->left
, -new_client_rect
->top
);
744 /* make src rect relative to the old position of the window */
745 OffsetRect(&src_rect
, -old_client_rect
->left
, -old_client_rect
->top
);
746 if (dst_rect
.left
== src_rect
.left
&& dst_rect
.top
== src_rect
.top
) return;
747 hdc_src
= hdc_dst
= GetDCEx(hwnd
, 0, DCX_CACHE
);
750 rgn
= CreateRectRgnIndirect(&dst_rect
);
751 SelectClipRgn(hdc_dst
, rgn
);
753 ExcludeUpdateRgn(hdc_dst
, hwnd
);
755 TRACE("copying bits for win %p/%p %s -> %s\n", hwnd
, window
,
756 wine_dbgstr_rect(&src_rect
), wine_dbgstr_rect(&dst_rect
));
757 BitBlt(hdc_dst
, dst_rect
.left
, dst_rect
.top
,
758 dst_rect
.right
- dst_rect
.left
, dst_rect
.bottom
- dst_rect
.top
,
759 hdc_src
, src_rect
.left
, src_rect
.top
, SRCCOPY
);
761 ReleaseDC(hwnd
, hdc_dst
);
762 if (hdc_src
!= hdc_dst
) ReleaseDC(parent
, hdc_src
);
766 /**********************************************************************
767 * CreateDesktopWindow (MACDRV.@)
769 BOOL CDECL
macdrv_CreateDesktopWindow(HWND hwnd
)
771 unsigned int width
, height
;
775 /* retrieve the real size of the desktop */
776 SERVER_START_REQ(get_window_rectangles
)
778 req
->handle
= wine_server_user_handle(hwnd
);
779 req
->relative
= COORDS_CLIENT
;
780 wine_server_call(req
);
781 width
= reply
->window
.right
;
782 height
= reply
->window
.bottom
;
786 if (!width
&& !height
) /* not initialized yet */
788 CGRect rect
= macdrv_get_desktop_rect();
790 SERVER_START_REQ(set_window_pos
)
792 req
->handle
= wine_server_user_handle(hwnd
);
794 req
->swp_flags
= SWP_NOZORDER
;
795 req
->window
.left
= CGRectGetMinX(rect
);
796 req
->window
.top
= CGRectGetMinY(rect
);
797 req
->window
.right
= CGRectGetMaxX(rect
);
798 req
->window
.bottom
= CGRectGetMaxY(rect
);
799 req
->client
= req
->window
;
800 wine_server_call(req
);
809 /**********************************************************************
810 * CreateWindow (MACDRV.@)
812 BOOL CDECL
macdrv_CreateWindow(HWND hwnd
)
818 /***********************************************************************
819 * DestroyWindow (MACDRV.@)
821 void CDECL
macdrv_DestroyWindow(HWND hwnd
)
823 struct macdrv_win_data
*data
;
827 if (!(data
= get_win_data(hwnd
))) return;
829 if (data
->gl_view
) macdrv_dispose_view(data
->gl_view
);
830 destroy_cocoa_window(data
);
832 CFDictionaryRemoveValue(win_datas
, hwnd
);
833 release_win_data(data
);
834 HeapFree(GetProcessHeap(), 0, data
);
838 /*****************************************************************
839 * SetFocus (MACDRV.@)
843 void CDECL
macdrv_SetFocus(HWND hwnd
)
845 struct macdrv_thread_data
*thread_data
= macdrv_thread_data();
846 struct macdrv_win_data
*data
;
850 if (!thread_data
) return;
851 thread_data
->dead_key_state
= 0;
853 if (!(hwnd
= GetAncestor(hwnd
, GA_ROOT
))) return;
854 if (!(data
= get_win_data(hwnd
))) return;
856 if (data
->cocoa_window
&& data
->on_screen
)
859 macdrv_give_cocoa_window_focus(data
->cocoa_window
);
862 release_win_data(data
);
866 /***********************************************************************
867 * SetLayeredWindowAttributes (MACDRV.@)
869 * Set transparency attributes for a layered window.
871 void CDECL
macdrv_SetLayeredWindowAttributes(HWND hwnd
, COLORREF key
, BYTE alpha
, DWORD flags
)
873 struct macdrv_win_data
*data
= get_win_data(hwnd
);
875 TRACE("hwnd %p key %#08x alpha %#02x flags %x\n", hwnd
, key
, alpha
, flags
);
879 data
->layered
= TRUE
;
880 if (data
->cocoa_window
)
882 sync_window_opacity(data
, key
, alpha
, FALSE
, flags
);
883 /* since layered attributes are now set, can now show the window */
884 if ((GetWindowLongW(hwnd
, GWL_STYLE
) & WS_VISIBLE
) && !data
->on_screen
)
887 release_win_data(data
);
890 FIXME("setting layered attributes on window %p of other process not supported\n", hwnd
);
894 /*****************************************************************
895 * SetParent (MACDRV.@)
897 void CDECL
macdrv_SetParent(HWND hwnd
, HWND parent
, HWND old_parent
)
899 struct macdrv_win_data
*data
;
901 TRACE("%p, %p, %p\n", hwnd
, parent
, old_parent
);
903 if (parent
== old_parent
) return;
904 if (!(data
= get_win_data(hwnd
))) return;
906 if (parent
!= GetDesktopWindow()) /* a child window */
908 if (old_parent
== GetDesktopWindow())
910 /* destroy the old Mac window */
911 destroy_cocoa_window(data
);
914 else /* new top level window */
915 create_cocoa_window(data
);
916 release_win_data(data
);
918 set_gl_view_parent(hwnd
, parent
);
922 /***********************************************************************
923 * SetWindowRgn (MACDRV.@)
925 * Assign specified region to window (for non-rectangular windows)
927 int CDECL
macdrv_SetWindowRgn(HWND hwnd
, HRGN hrgn
, BOOL redraw
)
929 struct macdrv_win_data
*data
;
931 TRACE("%p, %p, %d\n", hwnd
, hrgn
, redraw
);
933 if ((data
= get_win_data(hwnd
)))
935 sync_window_region(data
, hrgn
);
936 release_win_data(data
);
942 GetWindowThreadProcessId(hwnd
, &procid
);
943 if (procid
!= GetCurrentProcessId())
944 SendMessageW(hwnd
, WM_MACDRV_SET_WIN_REGION
, 0, 0);
951 /***********************************************************************
952 * SetWindowStyle (MACDRV.@)
954 * Update the state of the Cocoa window to reflect a style change
956 void CDECL
macdrv_SetWindowStyle(HWND hwnd
, INT offset
, STYLESTRUCT
*style
)
958 struct macdrv_win_data
*data
;
960 TRACE("%p, %d, %p\n", hwnd
, offset
, style
);
962 if (hwnd
== GetDesktopWindow()) return;
963 if (!(data
= get_win_data(hwnd
))) return;
965 if (data
->cocoa_window
)
967 DWORD changed
= style
->styleNew
^ style
->styleOld
;
969 set_cocoa_window_properties(data
);
971 if (offset
== GWL_EXSTYLE
&& (changed
& WS_EX_LAYERED
)) /* changing WS_EX_LAYERED resets attributes */
973 data
->layered
= FALSE
;
974 sync_window_opacity(data
, 0, 0, FALSE
, 0);
975 if (data
->surface
) set_surface_use_alpha(data
->surface
, FALSE
);
979 release_win_data(data
);
983 /*****************************************************************
984 * SetWindowText (MACDRV.@)
986 void CDECL
macdrv_SetWindowText(HWND hwnd
, LPCWSTR text
)
990 TRACE("%p, %s\n", hwnd
, debugstr_w(text
));
992 if ((win
= macdrv_get_cocoa_window(hwnd
, FALSE
)))
993 macdrv_set_cocoa_window_title(win
, text
, strlenW(text
));
997 /***********************************************************************
998 * ShowWindow (MACDRV.@)
1000 UINT CDECL
macdrv_ShowWindow(HWND hwnd
, INT cmd
, RECT
*rect
, UINT swp
)
1002 struct macdrv_thread_data
*thread_data
= macdrv_thread_data();
1003 struct macdrv_win_data
*data
= get_win_data(hwnd
);
1006 if (!data
|| !data
->cocoa_window
) goto done
;
1007 if (IsRectEmpty(rect
)) goto done
;
1008 if (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_MINIMIZE
)
1010 if (rect
->left
!= -32000 || rect
->top
!= -32000)
1012 OffsetRect(rect
, -32000 - rect
->left
, -32000 - rect
->top
);
1013 swp
&= ~(SWP_NOMOVE
| SWP_NOCLIENTMOVE
);
1017 if (!data
->on_screen
) goto done
;
1019 /* only fetch the new rectangle if the ShowWindow was a result of an external event */
1021 if (!thread_data
->current_event
|| thread_data
->current_event
->window
!= data
->cocoa_window
)
1024 if (thread_data
->current_event
->type
!= WINDOW_FRAME_CHANGED
&&
1025 thread_data
->current_event
->type
!= WINDOW_DID_MINIMIZE
&&
1026 thread_data
->current_event
->type
!= WINDOW_DID_UNMINIMIZE
)
1029 TRACE("win %p/%p cmd %d at %s flags %08x\n",
1030 hwnd
, data
->cocoa_window
, cmd
, wine_dbgstr_rect(rect
), swp
);
1032 macdrv_get_cocoa_window_frame(data
->cocoa_window
, &frame
);
1033 *rect
= rect_from_cgrect(frame
);
1034 macdrv_mac_to_window_rect(data
, rect
);
1035 TRACE("rect %s -> %s\n", wine_dbgstr_cgrect(frame
), wine_dbgstr_rect(rect
));
1036 swp
&= ~(SWP_NOMOVE
| SWP_NOCLIENTMOVE
| SWP_NOSIZE
| SWP_NOCLIENTSIZE
);
1039 release_win_data(data
);
1044 /***********************************************************************
1045 * SysCommand (MACDRV.@)
1047 * Perform WM_SYSCOMMAND handling.
1049 LRESULT CDECL
macdrv_SysCommand(HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1051 struct macdrv_win_data
*data
;
1054 TRACE("%p, %x, %lx\n", hwnd
, (unsigned)wparam
, lparam
);
1056 if (!(data
= get_win_data(hwnd
))) goto done
;
1057 if (!data
->cocoa_window
|| !data
->on_screen
) goto done
;
1059 /* prevent a simple ALT press+release from activating the system menu,
1060 as that can get confusing */
1061 if ((wparam
& 0xfff0) == SC_KEYMENU
&& !(WCHAR
)lparam
&& !GetMenu(hwnd
) &&
1062 (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_SYSMENU
))
1064 TRACE("ignoring SC_KEYMENU wp %lx lp %lx\n", wparam
, lparam
);
1069 release_win_data(data
);
1074 /***********************************************************************
1075 * UpdateLayeredWindow (MACDRV.@)
1077 BOOL CDECL
macdrv_UpdateLayeredWindow(HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
,
1078 const RECT
*window_rect
)
1080 struct window_surface
*surface
;
1081 struct macdrv_win_data
*data
;
1082 BLENDFUNCTION blend
= { AC_SRC_OVER
, 0, 255, 0 };
1084 char buffer
[FIELD_OFFSET(BITMAPINFO
, bmiColors
[256])];
1085 BITMAPINFO
*bmi
= (BITMAPINFO
*)buffer
;
1086 void *src_bits
, *dst_bits
;
1092 if (!(data
= get_win_data(hwnd
))) return FALSE
;
1094 data
->layered
= TRUE
;
1096 rect
= *window_rect
;
1097 OffsetRect(&rect
, -window_rect
->left
, -window_rect
->top
);
1099 surface
= data
->surface
;
1100 if (!surface
|| memcmp(&surface
->rect
, &rect
, sizeof(RECT
)))
1102 data
->surface
= create_surface(data
->cocoa_window
, &rect
, TRUE
);
1103 set_window_surface(data
->cocoa_window
, data
->surface
);
1104 if (surface
) window_surface_release(surface
);
1105 surface
= data
->surface
;
1107 else set_surface_use_alpha(surface
, TRUE
);
1109 if (surface
) window_surface_add_ref(surface
);
1110 release_win_data(data
);
1112 if (!surface
) return FALSE
;
1115 window_surface_release(surface
);
1119 if (info
->dwFlags
& ULW_ALPHA
)
1121 /* Apply SourceConstantAlpha via window alpha, not blend. */
1122 alpha
= info
->pblend
->SourceConstantAlpha
;
1123 blend
= *info
->pblend
;
1124 blend
.SourceConstantAlpha
= 0xff;
1129 dst_bits
= surface
->funcs
->get_info(surface
, bmi
);
1131 if (!(dib
= CreateDIBSection(info
->hdcDst
, bmi
, DIB_RGB_COLORS
, &src_bits
, NULL
, 0))) goto done
;
1132 if (!(hdc
= CreateCompatibleDC(0))) goto done
;
1134 SelectObject(hdc
, dib
);
1137 IntersectRect(&rect
, &rect
, info
->prcDirty
);
1138 surface
->funcs
->lock(surface
);
1139 memcpy(src_bits
, dst_bits
, bmi
->bmiHeader
.biSizeImage
);
1140 surface
->funcs
->unlock(surface
);
1141 PatBlt(hdc
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, BLACKNESS
);
1143 if (!(ret
= GdiAlphaBlend(hdc
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
1145 rect
.left
+ (info
->pptSrc
? info
->pptSrc
->x
: 0),
1146 rect
.top
+ (info
->pptSrc
? info
->pptSrc
->y
: 0),
1147 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
1151 if ((data
= get_win_data(hwnd
)))
1153 if (surface
== data
->surface
)
1155 surface
->funcs
->lock(surface
);
1156 memcpy(dst_bits
, src_bits
, bmi
->bmiHeader
.biSizeImage
);
1157 add_bounds_rect(surface
->funcs
->get_bounds(surface
), &rect
);
1158 surface
->funcs
->unlock(surface
);
1159 surface
->funcs
->flush(surface
);
1162 /* The ULW flags are a superset of the LWA flags. */
1163 sync_window_opacity(data
, info
->crKey
, alpha
, TRUE
, info
->dwFlags
);
1165 release_win_data(data
);
1169 window_surface_release(surface
);
1170 if (hdc
) DeleteDC(hdc
);
1171 if (dib
) DeleteObject(dib
);
1176 /**********************************************************************
1177 * WindowMessage (MACDRV.@)
1179 LRESULT CDECL
macdrv_WindowMessage(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1181 struct macdrv_win_data
*data
;
1183 TRACE("%p, %u, %u, %lu\n", hwnd
, msg
, (unsigned)wp
, lp
);
1187 case WM_MACDRV_SET_WIN_REGION
:
1188 if ((data
= get_win_data(hwnd
)))
1190 sync_window_region(data
, (HRGN
)1);
1191 release_win_data(data
);
1194 case WM_MACDRV_UPDATE_DESKTOP_RECT
:
1195 if (hwnd
== GetDesktopWindow())
1197 CGRect new_desktop_rect
;
1198 RECT current_desktop_rect
;
1200 macdrv_reset_device_metrics();
1201 new_desktop_rect
= macdrv_get_desktop_rect();
1202 if (!GetWindowRect(hwnd
, ¤t_desktop_rect
) ||
1203 !CGRectEqualToRect(cgrect_from_rect(current_desktop_rect
), new_desktop_rect
))
1205 SendMessageTimeoutW(HWND_BROADCAST
, WM_MACDRV_RESET_DEVICE_METRICS
, 0, 0,
1206 SMTO_ABORTIFHUNG
, 2000, NULL
);
1207 SetWindowPos(hwnd
, 0, CGRectGetMinX(new_desktop_rect
), CGRectGetMinY(new_desktop_rect
),
1208 CGRectGetWidth(new_desktop_rect
), CGRectGetHeight(new_desktop_rect
),
1209 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_DEFERERASE
);
1210 SendMessageTimeoutW(HWND_BROADCAST
, WM_MACDRV_DISPLAYCHANGE
, wp
, lp
,
1211 SMTO_ABORTIFHUNG
, 2000, NULL
);
1215 case WM_MACDRV_RESET_DEVICE_METRICS
:
1216 macdrv_reset_device_metrics();
1218 case WM_MACDRV_DISPLAYCHANGE
:
1219 if ((data
= get_win_data(hwnd
)))
1221 if (data
->cocoa_window
&& data
->on_screen
)
1222 sync_window_position(data
, SWP_NOZORDER
| SWP_NOACTIVATE
);
1223 release_win_data(data
);
1225 SendMessageW(hwnd
, WM_DISPLAYCHANGE
, wp
, lp
);
1229 FIXME("unrecognized window msg %x hwnd %p wp %lx lp %lx\n", msg
, hwnd
, wp
, lp
);
1234 static inline RECT
get_surface_rect(const RECT
*visible_rect
)
1237 RECT desktop_rect
= rect_from_cgrect(macdrv_get_desktop_rect());
1239 IntersectRect(&rect
, visible_rect
, &desktop_rect
);
1240 OffsetRect(&rect
, -visible_rect
->left
, -visible_rect
->top
);
1243 rect
.right
= max(rect
.left
+ 128, (rect
.right
+ 127) & ~127);
1244 rect
.bottom
= max(rect
.top
+ 128, (rect
.bottom
+ 127) & ~127);
1249 /***********************************************************************
1250 * WindowPosChanging (MACDRV.@)
1252 void CDECL
macdrv_WindowPosChanging(HWND hwnd
, HWND insert_after
, UINT swp_flags
,
1253 const RECT
*window_rect
, const RECT
*client_rect
,
1254 RECT
*visible_rect
, struct window_surface
**surface
)
1256 struct macdrv_win_data
*data
= get_win_data(hwnd
);
1257 DWORD style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1260 TRACE("%p after %p swp %04x window %s client %s visible %s surface %p\n", hwnd
, insert_after
,
1261 swp_flags
, wine_dbgstr_rect(window_rect
), wine_dbgstr_rect(client_rect
),
1262 wine_dbgstr_rect(visible_rect
), surface
);
1264 if (!data
&& !(data
= macdrv_create_win_data(hwnd
, window_rect
, client_rect
))) return;
1266 *visible_rect
= *window_rect
;
1267 macdrv_window_to_mac_rect(data
, style
, visible_rect
);
1268 TRACE("visible_rect %s -> %s\n", wine_dbgstr_rect(window_rect
),
1269 wine_dbgstr_rect(visible_rect
));
1271 /* create the window surface if necessary */
1272 if (!data
->cocoa_window
) goto done
;
1273 if (swp_flags
& SWP_HIDEWINDOW
) goto done
;
1275 if (*surface
) window_surface_release(*surface
);
1278 surface_rect
= get_surface_rect(visible_rect
);
1281 if (!memcmp(&data
->surface
->rect
, &surface_rect
, sizeof(surface_rect
)))
1283 /* existing surface is good enough */
1284 window_surface_add_ref(data
->surface
);
1285 *surface
= data
->surface
;
1289 else if (!(swp_flags
& SWP_SHOWWINDOW
) && !(style
& WS_VISIBLE
)) goto done
;
1291 *surface
= create_surface(data
->cocoa_window
, &surface_rect
, FALSE
);
1294 release_win_data(data
);
1298 /***********************************************************************
1299 * WindowPosChanged (MACDRV.@)
1301 void CDECL
macdrv_WindowPosChanged(HWND hwnd
, HWND insert_after
, UINT swp_flags
,
1302 const RECT
*window_rect
, const RECT
*client_rect
,
1303 const RECT
*visible_rect
, const RECT
*valid_rects
,
1304 struct window_surface
*surface
)
1306 struct macdrv_thread_data
*thread_data
;
1307 struct macdrv_win_data
*data
;
1308 DWORD new_style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1309 RECT old_window_rect
, old_whole_rect
, old_client_rect
;
1311 if (!(data
= get_win_data(hwnd
))) return;
1313 thread_data
= macdrv_thread_data();
1315 old_window_rect
= data
->window_rect
;
1316 old_whole_rect
= data
->whole_rect
;
1317 old_client_rect
= data
->client_rect
;
1318 data
->window_rect
= *window_rect
;
1319 data
->whole_rect
= *visible_rect
;
1320 data
->client_rect
= *client_rect
;
1322 window_surface_add_ref(surface
);
1323 set_window_surface(data
->cocoa_window
, surface
);
1324 if (data
->surface
) window_surface_release(data
->surface
);
1325 data
->surface
= surface
;
1327 TRACE("win %p/%p window %s whole %s client %s style %08x flags %08x surface %p\n",
1328 hwnd
, data
->cocoa_window
, wine_dbgstr_rect(window_rect
),
1329 wine_dbgstr_rect(visible_rect
), wine_dbgstr_rect(client_rect
),
1330 new_style
, swp_flags
, surface
);
1332 if (!IsRectEmpty(&valid_rects
[0]))
1334 macdrv_window window
= data
->cocoa_window
;
1335 int x_offset
= old_whole_rect
.left
- data
->whole_rect
.left
;
1336 int y_offset
= old_whole_rect
.top
- data
->whole_rect
.top
;
1338 /* if all that happened is that the whole window moved, copy everything */
1339 if (!(swp_flags
& SWP_FRAMECHANGED
) &&
1340 old_whole_rect
.right
- data
->whole_rect
.right
== x_offset
&&
1341 old_whole_rect
.bottom
- data
->whole_rect
.bottom
== y_offset
&&
1342 old_client_rect
.left
- data
->client_rect
.left
== x_offset
&&
1343 old_client_rect
.right
- data
->client_rect
.right
== x_offset
&&
1344 old_client_rect
.top
- data
->client_rect
.top
== y_offset
&&
1345 old_client_rect
.bottom
- data
->client_rect
.bottom
== y_offset
&&
1346 !memcmp(&valid_rects
[0], &data
->client_rect
, sizeof(RECT
)))
1348 /* A Cocoa window's bits are moved automatically */
1349 if (!window
&& (x_offset
!= 0 || y_offset
!= 0))
1351 release_win_data(data
);
1352 move_window_bits(hwnd
, window
, &old_whole_rect
, visible_rect
,
1353 &old_client_rect
, client_rect
, window_rect
);
1354 if (!(data
= get_win_data(hwnd
))) return;
1359 release_win_data(data
);
1360 move_window_bits(hwnd
, window
, &valid_rects
[1], &valid_rects
[0],
1361 &old_client_rect
, client_rect
, window_rect
);
1362 if (!(data
= get_win_data(hwnd
))) return;
1368 if (!data
->cocoa_window
) goto done
;
1370 if (data
->on_screen
)
1372 if ((swp_flags
& SWP_HIDEWINDOW
) && !(new_style
& WS_VISIBLE
))
1376 /* check if we are currently processing an event relevant to this window */
1377 if (!thread_data
|| !thread_data
->current_event
||
1378 thread_data
->current_event
->window
!= data
->cocoa_window
||
1379 (thread_data
->current_event
->type
!= WINDOW_FRAME_CHANGED
&&
1380 thread_data
->current_event
->type
!= WINDOW_DID_MINIMIZE
&&
1381 thread_data
->current_event
->type
!= WINDOW_DID_UNMINIMIZE
))
1383 sync_window_position(data
, swp_flags
);
1384 set_cocoa_window_properties(data
);
1387 if (new_style
& WS_VISIBLE
)
1389 if (!data
->on_screen
|| (swp_flags
& (SWP_FRAMECHANGED
|SWP_STATECHANGED
)))
1390 set_cocoa_window_properties(data
);
1392 /* layered windows are not shown until their attributes are set */
1393 if (!data
->on_screen
&&
1394 (data
->layered
|| !(GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_LAYERED
)))
1399 release_win_data(data
);
1403 /***********************************************************************
1404 * macdrv_window_close_requested
1406 * Handler for WINDOW_CLOSE_REQUESTED events.
1408 void macdrv_window_close_requested(HWND hwnd
)
1410 /* Ignore the delete window request if the window has been disabled. This
1411 * is to disallow applications from being closed while in a modal state.
1413 if (IsWindowEnabled(hwnd
))
1417 if (GetClassLongW(hwnd
, GCL_STYLE
) & CS_NOCLOSE
) return;
1418 hSysMenu
= GetSystemMenu(hwnd
, FALSE
);
1421 UINT state
= GetMenuState(hSysMenu
, SC_CLOSE
, MF_BYCOMMAND
);
1422 if (state
== 0xFFFFFFFF || (state
& (MF_DISABLED
| MF_GRAYED
)))
1425 if (GetActiveWindow() != hwnd
)
1427 LRESULT ma
= SendMessageW(hwnd
, WM_MOUSEACTIVATE
,
1428 (WPARAM
)GetAncestor(hwnd
, GA_ROOT
),
1429 MAKELPARAM(HTCLOSE
, WM_NCLBUTTONDOWN
));
1432 case MA_NOACTIVATEANDEAT
:
1433 case MA_ACTIVATEANDEAT
:
1439 SetActiveWindow(hwnd
);
1442 WARN("unknown WM_MOUSEACTIVATE code %d\n", (int) ma
);
1447 PostMessageW(hwnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
1452 /***********************************************************************
1453 * macdrv_window_frame_changed
1455 * Handler for WINDOW_FRAME_CHANGED events.
1457 void macdrv_window_frame_changed(HWND hwnd
, CGRect frame
)
1459 struct macdrv_win_data
*data
;
1462 UINT flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
1466 if (!(data
= get_win_data(hwnd
))) return;
1467 if (!data
->on_screen
)
1469 release_win_data(data
);
1475 parent
= GetAncestor(hwnd
, GA_PARENT
);
1477 TRACE("win %p/%p new Cocoa frame %s\n", hwnd
, data
->cocoa_window
, wine_dbgstr_cgrect(frame
));
1479 rect
= rect_from_cgrect(frame
);
1480 macdrv_mac_to_window_rect(data
, &rect
);
1481 MapWindowPoints(0, parent
, (POINT
*)&rect
, 2);
1483 width
= rect
.right
- rect
.left
;
1484 height
= rect
.bottom
- rect
.top
;
1486 if (data
->window_rect
.left
== rect
.left
&& data
->window_rect
.top
== rect
.top
)
1487 flags
|= SWP_NOMOVE
;
1489 TRACE("%p moving from (%d,%d) to (%d,%d)\n", hwnd
, data
->window_rect
.left
,
1490 data
->window_rect
.top
, rect
.left
, rect
.top
);
1492 if ((data
->window_rect
.right
- data
->window_rect
.left
== width
&&
1493 data
->window_rect
.bottom
- data
->window_rect
.top
== height
) ||
1494 (IsRectEmpty(&data
->window_rect
) && width
<= 0 && height
<= 0))
1495 flags
|= SWP_NOSIZE
;
1497 TRACE("%p resizing from (%dx%d) to (%dx%d)\n", hwnd
, data
->window_rect
.right
- data
->window_rect
.left
,
1498 data
->window_rect
.bottom
- data
->window_rect
.top
, width
, height
);
1500 release_win_data(data
);
1502 if (!(flags
& SWP_NOSIZE
) || !(flags
& SWP_NOMOVE
))
1503 SetWindowPos(hwnd
, 0, rect
.left
, rect
.top
, width
, height
, flags
);
1507 /***********************************************************************
1508 * macdrv_window_got_focus
1510 * Handler for WINDOW_GOT_FOCUS events.
1512 void macdrv_window_got_focus(HWND hwnd
, const macdrv_event
*event
)
1516 TRACE("win %p/%p serial %lu enabled %d visible %d style %08x focus %p active %p fg %p\n",
1517 hwnd
, event
->window
, event
->window_got_focus
.serial
, IsWindowEnabled(hwnd
),
1518 IsWindowVisible(hwnd
), GetWindowLongW(hwnd
, GWL_STYLE
), GetFocus(),
1519 GetActiveWindow(), GetForegroundWindow());
1521 if (can_activate_window(hwnd
))
1523 /* simulate a mouse click on the caption to find out
1524 * whether the window wants to be activated */
1525 LRESULT ma
= SendMessageW(hwnd
, WM_MOUSEACTIVATE
,
1526 (WPARAM
)GetAncestor(hwnd
, GA_ROOT
),
1527 MAKELONG(HTCAPTION
,WM_LBUTTONDOWN
));
1528 if (ma
!= MA_NOACTIVATEANDEAT
&& ma
!= MA_NOACTIVATE
)
1530 TRACE("setting foreground window to %p\n", hwnd
);
1531 SetForegroundWindow(hwnd
);
1536 TRACE("win %p/%p rejecting focus\n", hwnd
, event
->window
);
1537 macdrv_window_rejected_focus(event
);
1541 /***********************************************************************
1542 * macdrv_window_lost_focus
1544 * Handler for WINDOW_LOST_FOCUS events.
1546 void macdrv_window_lost_focus(HWND hwnd
, const macdrv_event
*event
)
1550 TRACE("win %p/%p fg %p\n", hwnd
, event
->window
, GetForegroundWindow());
1552 if (hwnd
== GetForegroundWindow())
1553 SendMessageW(hwnd
, WM_CANCELMODE
, 0, 0);
1557 /***********************************************************************
1558 * macdrv_app_deactivated
1560 * Handler for APP_DEACTIVATED events.
1562 void macdrv_app_deactivated(void)
1564 if (GetActiveWindow() == GetForegroundWindow())
1566 TRACE("setting fg to desktop\n");
1567 SetForegroundWindow(GetDesktopWindow());
1572 /***********************************************************************
1573 * macdrv_window_did_minimize
1575 * Handler for WINDOW_DID_MINIMIZE events.
1577 void macdrv_window_did_minimize(HWND hwnd
)
1579 struct macdrv_win_data
*data
;
1582 TRACE("win %p\n", hwnd
);
1584 if (!(data
= get_win_data(hwnd
))) return;
1585 if (data
->minimized
) goto done
;
1587 style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1589 data
->minimized
= TRUE
;
1590 if ((style
& WS_MINIMIZEBOX
) && !(style
& WS_DISABLED
))
1592 TRACE("minimizing win %p/%p\n", hwnd
, data
->cocoa_window
);
1593 release_win_data(data
);
1594 SendMessageW(hwnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
1597 TRACE("not minimizing win %p/%p style %08x\n", hwnd
, data
->cocoa_window
, style
);
1600 release_win_data(data
);
1604 /***********************************************************************
1605 * macdrv_window_did_unminimize
1607 * Handler for WINDOW_DID_UNMINIMIZE events.
1609 void macdrv_window_did_unminimize(HWND hwnd
)
1611 struct macdrv_win_data
*data
;
1614 TRACE("win %p\n", hwnd
);
1616 if (!(data
= get_win_data(hwnd
))) return;
1617 if (!data
->minimized
) goto done
;
1619 style
= GetWindowLongW(hwnd
, GWL_STYLE
);
1621 data
->minimized
= FALSE
;
1622 if (style
& (WS_MINIMIZE
| WS_MAXIMIZE
))
1624 TRACE("restoring win %p/%p\n", hwnd
, data
->cocoa_window
);
1625 release_win_data(data
);
1626 SendMessageW(hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, 0);
1630 TRACE("not restoring win %p/%p style %08x\n", hwnd
, data
->cocoa_window
, style
);
1633 release_win_data(data
);