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 /***********************************************************************
156 static void show_window(struct macdrv_win_data *data)
158 TRACE("win %p/%p\n", data->hwnd, data->cocoa_window);
160 data->on_screen = macdrv_order_cocoa_window(data->cocoa_window, NULL, NULL);
163 HWND hwndFocus = GetFocus();
164 if (hwndFocus && (data->hwnd == hwndFocus || IsChild(data->hwnd, hwndFocus)))
165 macdrv_SetFocus(hwndFocus);
170 /***********************************************************************
173 static void hide_window(struct macdrv_win_data *data)
175 TRACE("win %p/%p\n", data->hwnd, data->cocoa_window);
177 macdrv_hide_cocoa_window(data->cocoa_window);
178 data->on_screen = FALSE;
182 /***********************************************************************
183 * macdrv_window_to_mac_rect
185 * Convert a rect from client to Mac window coordinates
187 static void macdrv_window_to_mac_rect(struct macdrv_win_data *data, DWORD style, RECT *rect)
191 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return;
192 if (IsRectEmpty(rect)) return;
194 get_mac_rect_offset(data, style, &rc);
196 rect->left -= rc.left;
197 rect->right -= rc.right;
199 rect->bottom -= rc.bottom;
200 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
201 if (rect->left >= rect->right) rect->right = rect->left + 1;
205 /***********************************************************************
206 * macdrv_mac_to_window_rect
208 * Opposite of macdrv_window_to_mac_rect
210 static void macdrv_mac_to_window_rect(struct macdrv_win_data *data, RECT *rect)
213 DWORD style = GetWindowLongW(data->hwnd, GWL_STYLE);
215 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return;
216 if (IsRectEmpty(rect)) return;
218 get_mac_rect_offset(data, style, &rc);
220 rect->left += rc.left;
221 rect->right += rc.right;
223 rect->bottom += rc.bottom;
224 if (rect->top >= rect->bottom) rect->bottom = rect->top + 1;
225 if (rect->left >= rect->right) rect->right = rect->left + 1;
229 /***********************************************************************
230 * constrain_window_frame
232 * Alter a window frame rectangle to fit within a) Cocoa's documented
233 * limits, and b) sane sizes, like twice the desktop rect.
235 static void constrain_window_frame(CGRect* frame)
237 CGRect desktop_rect = macdrv_get_desktop_rect();
238 int max_width, max_height;
240 max_width = min(32000, 2 * CGRectGetWidth(desktop_rect));
241 max_height = min(32000, 2 * CGRectGetHeight(desktop_rect));
243 if (frame->origin.x < -16000) frame->origin.x = -16000;
244 if (frame->origin.y < -16000) frame->origin.y = -16000;
245 if (frame->origin.x > 16000) frame->origin.x = 16000;
246 if (frame->origin.y > 16000) frame->origin.y = 16000;
247 if (frame->size.width > max_width) frame->size.width = max_width;
248 if (frame->size.height > max_height) frame->size.height = max_height;
252 /***********************************************************************
255 static struct macdrv_win_data *alloc_win_data(HWND hwnd)
257 struct macdrv_win_data *data;
259 if ((data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
262 data->color_key = CLR_INVALID;
263 EnterCriticalSection(&win_data_section);
265 win_datas = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
266 CFDictionarySetValue(win_datas, hwnd, data);
272 /***********************************************************************
275 * Lock and return the data structure associated with a window.
277 static struct macdrv_win_data *get_win_data(HWND hwnd)
279 struct macdrv_win_data *data;
281 if (!hwnd) return NULL;
282 EnterCriticalSection(&win_data_section);
283 if (win_datas && (data = (struct macdrv_win_data*)CFDictionaryGetValue(win_datas, hwnd)))
285 LeaveCriticalSection(&win_data_section);
290 /***********************************************************************
293 * Release the data returned by get_win_data.
295 static void release_win_data(struct macdrv_win_data *data)
297 if (data) LeaveCriticalSection(&win_data_section);
301 /***********************************************************************
302 * macdrv_get_cocoa_window
304 * Return the Mac window associated with the full area of a window
306 static macdrv_window macdrv_get_cocoa_window(HWND hwnd)
308 struct macdrv_win_data *data = get_win_data(hwnd);
309 macdrv_window ret = data ? data->cocoa_window : NULL;
310 release_win_data(data);
315 /***********************************************************************
316 * set_cocoa_window_properties
318 * Set the window properties for a Cocoa window based on its Windows
321 static void set_cocoa_window_properties(struct macdrv_win_data *data)
323 DWORD style, ex_style;
325 macdrv_window owner_win;
326 struct macdrv_window_features wf;
327 struct macdrv_window_state state;
329 style = GetWindowLongW(data->hwnd, GWL_STYLE);
330 ex_style = GetWindowLongW(data->hwnd, GWL_EXSTYLE);
332 owner = GetWindow(data->hwnd, GW_OWNER);
333 owner_win = macdrv_get_cocoa_window(owner);
334 macdrv_set_cocoa_parent_window(data->cocoa_window, owner_win);
336 get_cocoa_window_features(data, style, ex_style, &wf);
337 macdrv_set_cocoa_window_features(data->cocoa_window, &wf);
339 get_cocoa_window_state(data, style, ex_style, &state);
340 macdrv_set_cocoa_window_state(data->cocoa_window, &state);
341 data->minimized = state.minimized;
345 /***********************************************************************
348 * Update the window region.
350 static void sync_window_region(struct macdrv_win_data *data, HRGN win_region)
352 HRGN hrgn = win_region;
353 RGNDATA *region_data;
357 if (!data->cocoa_window) return;
358 data->shaped = FALSE;
360 if (hrgn == (HRGN)1) /* hack: win_region == 1 means retrieve region from server */
362 if (!(hrgn = CreateRectRgn(0, 0, 0, 0))) return;
363 if (GetWindowRgn(data->hwnd, hrgn) == ERROR)
370 if (hrgn && GetWindowLongW(data->hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
371 MirrorRgn(data->hwnd, hrgn);
374 OffsetRgn(hrgn, data->window_rect.left - data->whole_rect.left,
375 data->window_rect.top - data->whole_rect.top);
377 region_data = get_region_data(hrgn, 0);
380 rects = (CGRect*)region_data->Buffer;
381 count = region_data->rdh.nCount;
382 /* Special case optimization. If the region entirely encloses the Cocoa
383 window, it's the same as there being no region. It's potentially
384 hard/slow to test this for arbitrary regions, so we just check for
385 very simple regions. */
386 if (count == 1 && CGRectContainsRect(rects[0], cgrect_from_rect(data->whole_rect)))
388 TRACE("optimizing for simple region that contains Cocoa content rect\n");
399 TRACE("win %p/%p win_region %p rects %p count %d\n", data->hwnd, data->cocoa_window, win_region, rects, count);
400 macdrv_set_window_shape(data->cocoa_window, rects, count);
402 HeapFree(GetProcessHeap(), 0, region_data);
403 data->shaped = (region_data != NULL);
405 if (hrgn && hrgn != win_region) DeleteObject(hrgn);
409 /***********************************************************************
412 static inline void add_bounds_rect(RECT *bounds, const RECT *rect)
414 if (rect->left >= rect->right || rect->top >= rect->bottom) return;
415 bounds->left = min(bounds->left, rect->left);
416 bounds->top = min(bounds->top, rect->top);
417 bounds->right = max(bounds->right, rect->right);
418 bounds->bottom = max(bounds->bottom, rect->bottom);
422 /***********************************************************************
423 * sync_window_opacity
425 static void sync_window_opacity(struct macdrv_win_data *data, COLORREF key, BYTE alpha,
426 BOOL per_pixel_alpha, DWORD flags)
428 CGFloat opacity = 1.0;
429 BOOL needs_flush = FALSE;
431 if (flags & LWA_ALPHA) opacity = alpha / 255.0;
433 TRACE("setting window %p/%p alpha to %g\n", data->hwnd, data->cocoa_window, opacity);
434 macdrv_set_window_alpha(data->cocoa_window, opacity);
436 if (flags & LWA_COLORKEY)
438 /* FIXME: treat PALETTEINDEX and DIBINDEX as black */
439 if ((key & (1 << 24)) || key >> 16 == 0x10ff)
445 if (data->color_key != key)
447 if (key == CLR_INVALID)
449 TRACE("clearing color-key for window %p/%p\n", data->hwnd, data->cocoa_window);
450 macdrv_clear_window_color_key(data->cocoa_window);
454 TRACE("setting color-key for window %p/%p to RGB %d,%d,%d\n", data->hwnd, data->cocoa_window,
455 GetRValue(key), GetGValue(key), GetBValue(key));
456 macdrv_set_window_color_key(data->cocoa_window, GetRValue(key), GetGValue(key), GetBValue(key));
459 data->color_key = key;
463 if (!data->per_pixel_alpha != !per_pixel_alpha)
465 macdrv_window_use_per_pixel_alpha(data->cocoa_window, per_pixel_alpha);
466 data->per_pixel_alpha = per_pixel_alpha;
470 if (needs_flush && data->surface)
475 rect = data->whole_rect;
476 OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top);
477 data->surface->funcs->lock(data->surface);
478 bounds = data->surface->funcs->get_bounds(data->surface);
479 add_bounds_rect(bounds, &rect);
480 data->surface->funcs->unlock(data->surface);
485 /**********************************************************************
486 * create_cocoa_window
488 * Create the whole Mac window for a given window
490 static void create_cocoa_window(struct macdrv_win_data *data)
492 struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
494 struct macdrv_window_features wf;
496 DWORD style, ex_style;
502 if ((win_rgn = CreateRectRgn(0, 0, 0, 0)) &&
503 GetWindowRgn(data->hwnd, win_rgn) == ERROR)
505 DeleteObject(win_rgn);
508 data->shaped = (win_rgn != 0);
510 style = GetWindowLongW(data->hwnd, GWL_STYLE);
511 ex_style = GetWindowLongW(data->hwnd, GWL_EXSTYLE);
513 data->whole_rect = data->window_rect;
514 macdrv_window_to_mac_rect(data, style, &data->whole_rect);
516 memset(&wf, 0, sizeof(wf));
517 get_cocoa_window_features(data, style, ex_style, &wf);
519 frame = cgrect_from_rect(data->whole_rect);
520 constrain_window_frame(&frame);
522 TRACE("creating %p window %s whole %s client %s\n", data->hwnd, wine_dbgstr_rect(&data->window_rect),
523 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
525 data->cocoa_window = macdrv_create_cocoa_window(&wf, frame, data->hwnd, thread_data->queue);
526 if (!data->cocoa_window) goto done;
528 set_cocoa_window_properties(data);
530 /* set the window text */
531 if (!InternalGetWindowText(data->hwnd, text, sizeof(text)/sizeof(WCHAR))) text[0] = 0;
532 macdrv_set_cocoa_window_title(data->cocoa_window, text, strlenW(text));
534 /* set the window region */
535 if (win_rgn) sync_window_region(data, win_rgn);
537 /* set the window opacity */
538 if (!GetLayeredWindowAttributes(data->hwnd, &key, &alpha, &layered_flags)) layered_flags = 0;
539 sync_window_opacity(data, key, alpha, FALSE, layered_flags);
542 if (win_rgn) DeleteObject(win_rgn);
546 /**********************************************************************
547 * destroy_cocoa_window
549 * Destroy the whole Mac window for a given window.
551 static void destroy_cocoa_window(struct macdrv_win_data *data)
553 if (!data->cocoa_window) return;
555 TRACE("win %p Cocoa win %p\n", data->hwnd, data->cocoa_window);
557 macdrv_destroy_cocoa_window(data->cocoa_window);
558 data->cocoa_window = 0;
559 data->on_screen = FALSE;
560 data->color_key = CLR_INVALID;
561 if (data->surface) window_surface_release(data->surface);
562 data->surface = NULL;
566 /***********************************************************************
567 * macdrv_create_win_data
569 * Create a Mac data window structure for an existing window.
571 static struct macdrv_win_data *macdrv_create_win_data(HWND hwnd, const RECT *window_rect,
572 const RECT *client_rect)
574 struct macdrv_win_data *data;
577 if (GetWindowThreadProcessId(hwnd, NULL) != GetCurrentThreadId()) return NULL;
579 if (!(parent = GetAncestor(hwnd, GA_PARENT))) /* desktop */
581 macdrv_init_thread_data();
585 /* don't create win data for HWND_MESSAGE windows */
586 if (parent != GetDesktopWindow() && !GetAncestor(parent, GA_PARENT)) return NULL;
588 if (!(data = alloc_win_data(hwnd))) return NULL;
590 data->whole_rect = data->window_rect = *window_rect;
591 data->client_rect = *client_rect;
593 if (parent == GetDesktopWindow())
595 create_cocoa_window(data);
596 TRACE("win %p/%p window %s whole %s client %s\n",
597 hwnd, data->cocoa_window, wine_dbgstr_rect(&data->window_rect),
598 wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect));
605 /***********************************************************************
608 * Calls GetRegionData on the given region and converts the rectangle
609 * array to CGRect format. The returned buffer must be freed by
610 * caller using HeapFree(GetProcessHeap(),...).
611 * If hdc_lptodp is not 0, the rectangles are converted through LPtoDP.
613 RGNDATA *get_region_data(HRGN hrgn, HDC hdc_lptodp)
621 if (!hrgn || !(size = GetRegionData(hrgn, 0, NULL))) return NULL;
622 if (sizeof(CGRect) > sizeof(RECT))
624 /* add extra size for CGRect array */
625 int count = (size - sizeof(RGNDATAHEADER)) / sizeof(RECT);
626 size += count * (sizeof(CGRect) - sizeof(RECT));
628 if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return NULL;
629 if (!GetRegionData(hrgn, size, data))
631 HeapFree(GetProcessHeap(), 0, data);
635 rect = (RECT *)data->Buffer;
636 cgrect = (CGRect *)data->Buffer;
637 if (hdc_lptodp) /* map to device coordinates */
639 LPtoDP(hdc_lptodp, (POINT *)rect, data->rdh.nCount * 2);
640 for (i = 0; i < data->rdh.nCount; i++)
642 if (rect[i].right < rect[i].left)
644 INT tmp = rect[i].right;
645 rect[i].right = rect[i].left;
648 if (rect[i].bottom < rect[i].top)
650 INT tmp = rect[i].bottom;
651 rect[i].bottom = rect[i].top;
657 if (sizeof(CGRect) > sizeof(RECT))
659 /* need to start from the end */
660 for (i = data->rdh.nCount-1; i >= 0; i--)
661 cgrect[i] = cgrect_from_rect(rect[i]);
665 for (i = 0; i < data->rdh.nCount; i++)
666 cgrect[i] = cgrect_from_rect(rect[i]);
672 /***********************************************************************
673 * sync_window_position
675 * Synchronize the Mac window position with the Windows one
677 static void sync_window_position(struct macdrv_win_data *data, UINT swp_flags)
681 if (data->minimized) return;
683 frame = cgrect_from_rect(data->whole_rect);
684 constrain_window_frame(&frame);
686 data->on_screen = macdrv_set_cocoa_window_frame(data->cocoa_window, &frame);
687 if (data->shaped) sync_window_region(data, (HRGN)1);
689 TRACE("win %p/%p pos %s\n", data->hwnd, data->cocoa_window,
690 wine_dbgstr_rect(&data->whole_rect));
692 if (data->on_screen && (!(swp_flags & SWP_NOZORDER) || (swp_flags & SWP_SHOWWINDOW)))
695 macdrv_window prev_window = NULL;
696 macdrv_window next_window = NULL;
698 /* find window that this one must be after */
699 HWND prev = GetWindow(data->hwnd, GW_HWNDPREV);
700 while (prev && !((GetWindowLongW(prev, GWL_STYLE) & WS_VISIBLE) &&
701 (prev_window = macdrv_get_cocoa_window(prev))))
702 prev = GetWindow(prev, GW_HWNDPREV);
705 /* find window that this one must be before */
706 next = GetWindow(data->hwnd, GW_HWNDNEXT);
707 while (next && !((GetWindowLongW(next, GWL_STYLE) & WS_VISIBLE) &&
708 (next_window = macdrv_get_cocoa_window(next))))
709 next = GetWindow(next, GW_HWNDNEXT);
712 data->on_screen = macdrv_order_cocoa_window(data->cocoa_window, prev_window, next_window);
714 TRACE("win %p/%p below %p/%p above %p/%p\n",
715 data->hwnd, data->cocoa_window, prev, prev_window, next, next_window);
720 /***********************************************************************
723 * Move the window bits when a window is moved.
725 static void move_window_bits(HWND hwnd, macdrv_window window, const RECT *old_rect, const RECT *new_rect,
726 const RECT *old_client_rect, const RECT *new_client_rect,
727 const RECT *new_window_rect)
729 RECT src_rect = *old_rect;
730 RECT dst_rect = *new_rect;
731 HDC hdc_src, hdc_dst;
737 OffsetRect(&dst_rect, -new_window_rect->left, -new_window_rect->top);
738 parent = GetAncestor(hwnd, GA_PARENT);
739 hdc_src = GetDCEx(parent, 0, DCX_CACHE);
740 hdc_dst = GetDCEx(hwnd, 0, DCX_CACHE | DCX_WINDOW);
744 OffsetRect(&dst_rect, -new_client_rect->left, -new_client_rect->top);
745 /* make src rect relative to the old position of the window */
746 OffsetRect(&src_rect, -old_client_rect->left, -old_client_rect->top);
747 if (dst_rect.left == src_rect.left && dst_rect.top == src_rect.top) return;
748 hdc_src = hdc_dst = GetDCEx(hwnd, 0, DCX_CACHE);
751 rgn = CreateRectRgnIndirect(&dst_rect);
752 SelectClipRgn(hdc_dst, rgn);
754 ExcludeUpdateRgn(hdc_dst, hwnd);
756 TRACE("copying bits for win %p/%p %s -> %s\n", hwnd, window,
757 wine_dbgstr_rect(&src_rect), wine_dbgstr_rect(&dst_rect));
758 BitBlt(hdc_dst, dst_rect.left, dst_rect.top,
759 dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top,
760 hdc_src, src_rect.left, src_rect.top, SRCCOPY);
762 ReleaseDC(hwnd, hdc_dst);
763 if (hdc_src != hdc_dst) ReleaseDC(parent, hdc_src);
767 /**********************************************************************
768 * CreateDesktopWindow (MACDRV.@)
770 BOOL CDECL macdrv_CreateDesktopWindow(HWND hwnd)
772 unsigned int width, height;
776 /* retrieve the real size of the desktop */
777 SERVER_START_REQ(get_window_rectangles)
779 req->handle = wine_server_user_handle(hwnd);
780 req->relative = COORDS_CLIENT;
781 wine_server_call(req);
782 width = reply->window.right;
783 height = reply->window.bottom;
787 if (!width && !height) /* not initialized yet */
789 CGRect rect = macdrv_get_desktop_rect();
791 SERVER_START_REQ(set_window_pos)
793 req->handle = wine_server_user_handle(hwnd);
795 req->swp_flags = SWP_NOZORDER;
796 req->window.left = CGRectGetMinX(rect);
797 req->window.top = CGRectGetMinY(rect);
798 req->window.right = CGRectGetMaxX(rect);
799 req->window.bottom = CGRectGetMaxY(rect);
800 req->client = req->window;
801 wine_server_call(req);
810 /**********************************************************************
811 * CreateWindow (MACDRV.@)
813 BOOL CDECL macdrv_CreateWindow(HWND hwnd)
819 /***********************************************************************
820 * DestroyWindow (MACDRV.@)
822 void CDECL macdrv_DestroyWindow(HWND hwnd)
824 struct macdrv_win_data *data;
828 if (!(data = get_win_data(hwnd))) return;
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)
859 macdrv_give_cocoa_window_focus(data->cocoa_window);
860 data->on_screen = TRUE;
863 release_win_data(data);
867 /***********************************************************************
868 * SetLayeredWindowAttributes (MACDRV.@)
870 * Set transparency attributes for a layered window.
872 void CDECL macdrv_SetLayeredWindowAttributes(HWND hwnd, COLORREF key, BYTE alpha, DWORD flags)
874 struct macdrv_win_data *data = get_win_data(hwnd);
876 TRACE("hwnd %p key %#08x alpha %#02x flags %x\n", hwnd, key, alpha, flags);
880 data->layered = TRUE;
881 if (data->cocoa_window)
883 sync_window_opacity(data, key, alpha, FALSE, flags);
884 /* since layered attributes are now set, can now show the window */
885 if ((GetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE) && !data->on_screen)
888 release_win_data(data);
891 FIXME("setting layered attributes on window %p of other process not supported\n", hwnd);
895 /*****************************************************************
896 * SetParent (MACDRV.@)
898 void CDECL macdrv_SetParent(HWND hwnd, HWND parent, HWND old_parent)
900 struct macdrv_win_data *data;
902 TRACE("%p, %p, %p\n", hwnd, parent, old_parent);
904 if (parent == old_parent) return;
905 if (!(data = get_win_data(hwnd))) return;
907 if (parent != GetDesktopWindow()) /* a child window */
909 if (old_parent == GetDesktopWindow())
911 /* destroy the old Mac window */
912 destroy_cocoa_window(data);
915 else /* new top level window */
916 create_cocoa_window(data);
917 release_win_data(data);
921 /***********************************************************************
922 * SetWindowRgn (MACDRV.@)
924 * Assign specified region to window (for non-rectangular windows)
926 int CDECL macdrv_SetWindowRgn(HWND hwnd, HRGN hrgn, BOOL redraw)
928 struct macdrv_win_data *data;
930 TRACE("%p, %p, %d\n", hwnd, hrgn, redraw);
932 if ((data = get_win_data(hwnd)))
934 sync_window_region(data, hrgn);
935 release_win_data(data);
941 GetWindowThreadProcessId(hwnd, &procid);
942 if (procid != GetCurrentProcessId())
943 SendMessageW(hwnd, WM_MACDRV_SET_WIN_REGION, 0, 0);
950 /***********************************************************************
951 * SetWindowStyle (MACDRV.@)
953 * Update the state of the Cocoa window to reflect a style change
955 void CDECL macdrv_SetWindowStyle(HWND hwnd, INT offset, STYLESTRUCT *style)
957 struct macdrv_win_data *data;
959 TRACE("%p, %d, %p\n", hwnd, offset, style);
961 if (hwnd == GetDesktopWindow()) return;
962 if (!(data = get_win_data(hwnd))) return;
964 if (data->cocoa_window)
966 DWORD changed = style->styleNew ^ style->styleOld;
968 set_cocoa_window_properties(data);
970 if (offset == GWL_EXSTYLE && (changed & WS_EX_LAYERED)) /* changing WS_EX_LAYERED resets attributes */
972 data->layered = FALSE;
973 sync_window_opacity(data, 0, 0, FALSE, 0);
974 if (data->surface) set_surface_use_alpha(data->surface, FALSE);
978 release_win_data(data);
982 /*****************************************************************
983 * SetWindowText (MACDRV.@)
985 void CDECL macdrv_SetWindowText(HWND hwnd, LPCWSTR text)
989 TRACE("%p, %s\n", hwnd, debugstr_w(text));
991 if ((win = macdrv_get_cocoa_window(hwnd)))
992 macdrv_set_cocoa_window_title(win, text, strlenW(text));
996 /***********************************************************************
997 * ShowWindow (MACDRV.@)
999 UINT CDECL macdrv_ShowWindow(HWND hwnd, INT cmd, RECT *rect, UINT swp)
1001 struct macdrv_thread_data *thread_data = macdrv_thread_data();
1002 struct macdrv_win_data *data = get_win_data(hwnd);
1005 if (!data || !data->cocoa_window) goto done;
1006 if (IsRectEmpty(rect)) goto done;
1007 if (GetWindowLongW(hwnd, GWL_STYLE) & WS_MINIMIZE)
1009 if (rect->left != -32000 || rect->top != -32000)
1011 OffsetRect(rect, -32000 - rect->left, -32000 - rect->top);
1012 swp &= ~(SWP_NOMOVE | SWP_NOCLIENTMOVE);
1016 if (!data->on_screen) goto done;
1018 /* only fetch the new rectangle if the ShowWindow was a result of an external event */
1020 if (!thread_data->current_event || thread_data->current_event->window != data->cocoa_window)
1023 if (thread_data->current_event->type != WINDOW_FRAME_CHANGED &&
1024 thread_data->current_event->type != WINDOW_DID_MINIMIZE &&
1025 thread_data->current_event->type != WINDOW_DID_UNMINIMIZE)
1028 TRACE("win %p/%p cmd %d at %s flags %08x\n",
1029 hwnd, data->cocoa_window, cmd, wine_dbgstr_rect(rect), swp);
1031 macdrv_get_cocoa_window_frame(data->cocoa_window, &frame);
1032 *rect = rect_from_cgrect(frame);
1033 macdrv_mac_to_window_rect(data, rect);
1034 TRACE("rect %s -> %s\n", wine_dbgstr_cgrect(frame), wine_dbgstr_rect(rect));
1035 swp &= ~(SWP_NOMOVE | SWP_NOCLIENTMOVE | SWP_NOSIZE | SWP_NOCLIENTSIZE);
1038 release_win_data(data);
1043 /***********************************************************************
1044 * SysCommand (MACDRV.@)
1046 * Perform WM_SYSCOMMAND handling.
1048 LRESULT CDECL macdrv_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam)
1050 struct macdrv_win_data *data;
1053 TRACE("%p, %x, %lx\n", hwnd, (unsigned)wparam, lparam);
1055 if (!(data = get_win_data(hwnd))) goto done;
1056 if (!data->cocoa_window || !data->on_screen) goto done;
1058 /* prevent a simple ALT press+release from activating the system menu,
1059 as that can get confusing */
1060 if ((wparam & 0xfff0) == SC_KEYMENU && !(WCHAR)lparam && !GetMenu(hwnd) &&
1061 (GetWindowLongW(hwnd, GWL_STYLE) & WS_SYSMENU))
1063 TRACE("ignoring SC_KEYMENU wp %lx lp %lx\n", wparam, lparam);
1068 release_win_data(data);
1073 /***********************************************************************
1074 * UpdateLayeredWindow (MACDRV.@)
1076 BOOL CDECL macdrv_UpdateLayeredWindow(HWND hwnd, const UPDATELAYEREDWINDOWINFO *info,
1077 const RECT *window_rect)
1079 struct window_surface *surface;
1080 struct macdrv_win_data *data;
1081 BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
1083 char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
1084 BITMAPINFO *bmi = (BITMAPINFO *)buffer;
1085 void *src_bits, *dst_bits;
1091 if (!(data = get_win_data(hwnd))) return FALSE;
1093 data->layered = TRUE;
1095 rect = *window_rect;
1096 OffsetRect(&rect, -window_rect->left, -window_rect->top);
1098 surface = data->surface;
1099 if (!surface || memcmp(&surface->rect, &rect, sizeof(RECT)))
1101 data->surface = create_surface(data->cocoa_window, &rect, TRUE);
1102 set_window_surface(data->cocoa_window, data->surface);
1103 if (surface) window_surface_release(surface);
1104 surface = data->surface;
1106 else set_surface_use_alpha(surface, TRUE);
1108 if (surface) window_surface_add_ref(surface);
1109 release_win_data(data);
1111 if (!surface) return FALSE;
1114 window_surface_release(surface);
1118 if (info->dwFlags & ULW_ALPHA)
1120 /* Apply SourceConstantAlpha via window alpha, not blend. */
1121 alpha = info->pblend->SourceConstantAlpha;
1122 blend = *info->pblend;
1123 blend.SourceConstantAlpha = 0xff;
1128 dst_bits = surface->funcs->get_info(surface, bmi);
1130 if (!(dib = CreateDIBSection(info->hdcDst, bmi, DIB_RGB_COLORS, &src_bits, NULL, 0))) goto done;
1131 if (!(hdc = CreateCompatibleDC(0))) goto done;
1133 SelectObject(hdc, dib);
1136 IntersectRect(&rect, &rect, info->prcDirty);
1137 surface->funcs->lock(surface);
1138 memcpy(src_bits, dst_bits, bmi->bmiHeader.biSizeImage);
1139 surface->funcs->unlock(surface);
1140 PatBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, BLACKNESS);
1142 if (!(ret = GdiAlphaBlend(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
1144 rect.left + (info->pptSrc ? info->pptSrc->x : 0),
1145 rect.top + (info->pptSrc ? info->pptSrc->y : 0),
1146 rect.right - rect.left, rect.bottom - rect.top,
1150 if ((data = get_win_data(hwnd)))
1152 if (surface == data->surface)
1154 surface->funcs->lock(surface);
1155 memcpy(dst_bits, src_bits, bmi->bmiHeader.biSizeImage);
1156 add_bounds_rect(surface->funcs->get_bounds(surface), &rect);
1157 surface->funcs->unlock(surface);
1158 surface->funcs->flush(surface);
1161 /* The ULW flags are a superset of the LWA flags. */
1162 sync_window_opacity(data, info->crKey, alpha, TRUE, info->dwFlags);
1164 release_win_data(data);
1168 window_surface_release(surface);
1169 if (hdc) DeleteDC(hdc);
1170 if (dib) DeleteObject(dib);
1175 /**********************************************************************
1176 * WindowMessage (MACDRV.@)
1178 LRESULT CDECL macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1180 struct macdrv_win_data *data;
1182 TRACE("%p, %u, %u, %lu\n", hwnd, msg, (unsigned)wp, lp);
1186 case WM_MACDRV_SET_WIN_REGION:
1187 if ((data = get_win_data(hwnd)))
1189 sync_window_region(data, (HRGN)1);
1190 release_win_data(data);
1195 FIXME("unrecognized window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, wp, lp);
1200 static inline RECT get_surface_rect(const RECT *visible_rect)
1203 RECT desktop_rect = rect_from_cgrect(macdrv_get_desktop_rect());
1205 IntersectRect(&rect, visible_rect, &desktop_rect);
1206 OffsetRect(&rect, -visible_rect->left, -visible_rect->top);
1209 rect.right = max(rect.left + 128, (rect.right + 127) & ~127);
1210 rect.bottom = max(rect.top + 128, (rect.bottom + 127) & ~127);
1215 /***********************************************************************
1216 * WindowPosChanging (MACDRV.@)
1218 void CDECL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags,
1219 const RECT *window_rect, const RECT *client_rect,
1220 RECT *visible_rect, struct window_surface **surface)
1222 struct macdrv_win_data *data = get_win_data(hwnd);
1223 DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
1226 TRACE("%p after %p swp %04x window %s client %s visible %s surface %p\n", hwnd, insert_after,
1227 swp_flags, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
1228 wine_dbgstr_rect(visible_rect), surface);
1230 if (!data && !(data = macdrv_create_win_data(hwnd, window_rect, client_rect))) return;
1232 *visible_rect = *window_rect;
1233 macdrv_window_to_mac_rect(data, style, visible_rect);
1234 TRACE("visible_rect %s -> %s\n", wine_dbgstr_rect(window_rect),
1235 wine_dbgstr_rect(visible_rect));
1237 /* create the window surface if necessary */
1238 if (!data->cocoa_window) goto done;
1239 if (swp_flags & SWP_HIDEWINDOW) goto done;
1241 if (*surface) window_surface_release(*surface);
1244 surface_rect = get_surface_rect(visible_rect);
1247 if (!memcmp(&data->surface->rect, &surface_rect, sizeof(surface_rect)))
1249 /* existing surface is good enough */
1250 window_surface_add_ref(data->surface);
1251 *surface = data->surface;
1255 else if (!(swp_flags & SWP_SHOWWINDOW) && !(style & WS_VISIBLE)) goto done;
1257 *surface = create_surface(data->cocoa_window, &surface_rect, FALSE);
1260 release_win_data(data);
1264 /***********************************************************************
1265 * WindowPosChanged (MACDRV.@)
1267 void CDECL macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
1268 const RECT *window_rect, const RECT *client_rect,
1269 const RECT *visible_rect, const RECT *valid_rects,
1270 struct window_surface *surface)
1272 struct macdrv_thread_data *thread_data;
1273 struct macdrv_win_data *data;
1274 DWORD new_style = GetWindowLongW(hwnd, GWL_STYLE);
1275 RECT old_window_rect, old_whole_rect, old_client_rect;
1277 if (!(data = get_win_data(hwnd))) return;
1279 thread_data = macdrv_thread_data();
1281 old_window_rect = data->window_rect;
1282 old_whole_rect = data->whole_rect;
1283 old_client_rect = data->client_rect;
1284 data->window_rect = *window_rect;
1285 data->whole_rect = *visible_rect;
1286 data->client_rect = *client_rect;
1288 window_surface_add_ref(surface);
1289 set_window_surface(data->cocoa_window, surface);
1290 if (data->surface) window_surface_release(data->surface);
1291 data->surface = surface;
1293 TRACE("win %p/%p window %s whole %s client %s style %08x flags %08x surface %p\n",
1294 hwnd, data->cocoa_window, wine_dbgstr_rect(window_rect),
1295 wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(client_rect),
1296 new_style, swp_flags, surface);
1298 if (!IsRectEmpty(&valid_rects[0]))
1300 macdrv_window window = data->cocoa_window;
1301 int x_offset = old_whole_rect.left - data->whole_rect.left;
1302 int y_offset = old_whole_rect.top - data->whole_rect.top;
1304 /* if all that happened is that the whole window moved, copy everything */
1305 if (!(swp_flags & SWP_FRAMECHANGED) &&
1306 old_whole_rect.right - data->whole_rect.right == x_offset &&
1307 old_whole_rect.bottom - data->whole_rect.bottom == y_offset &&
1308 old_client_rect.left - data->client_rect.left == x_offset &&
1309 old_client_rect.right - data->client_rect.right == x_offset &&
1310 old_client_rect.top - data->client_rect.top == y_offset &&
1311 old_client_rect.bottom - data->client_rect.bottom == y_offset &&
1312 !memcmp(&valid_rects[0], &data->client_rect, sizeof(RECT)))
1314 /* A Cocoa window's bits are moved automatically */
1315 if (!window && (x_offset != 0 || y_offset != 0))
1317 release_win_data(data);
1318 move_window_bits(hwnd, window, &old_whole_rect, visible_rect,
1319 &old_client_rect, client_rect, window_rect);
1320 if (!(data = get_win_data(hwnd))) return;
1325 release_win_data(data);
1326 move_window_bits(hwnd, window, &valid_rects[1], &valid_rects[0],
1327 &old_client_rect, client_rect, window_rect);
1328 if (!(data = get_win_data(hwnd))) return;
1332 if (!data->cocoa_window) goto done;
1334 if (data->on_screen)
1336 if ((swp_flags & SWP_HIDEWINDOW) && !(new_style & WS_VISIBLE))
1340 if (new_style & WS_VISIBLE)
1342 if (!data->on_screen || (swp_flags & (SWP_FRAMECHANGED|SWP_STATECHANGED)))
1343 set_cocoa_window_properties(data);
1345 /* layered windows are not shown until their attributes are set */
1346 if (!data->on_screen &&
1347 (data->layered || !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED)))
1351 /* check if we are currently processing an event relevant to this window */
1352 if (!thread_data || !thread_data->current_event ||
1353 thread_data->current_event->window != data->cocoa_window ||
1354 (thread_data->current_event->type != WINDOW_FRAME_CHANGED &&
1355 thread_data->current_event->type != WINDOW_DID_MINIMIZE &&
1356 thread_data->current_event->type != WINDOW_DID_UNMINIMIZE))
1358 sync_window_position(data, swp_flags);
1359 set_cocoa_window_properties(data);
1363 release_win_data(data);
1367 /***********************************************************************
1368 * macdrv_window_close_requested
1370 * Handler for WINDOW_CLOSE_REQUESTED events.
1372 void macdrv_window_close_requested(HWND hwnd)
1374 /* Ignore the delete window request if the window has been disabled. This
1375 * is to disallow applications from being closed while in a modal state.
1377 if (IsWindowEnabled(hwnd))
1381 if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) return;
1382 hSysMenu = GetSystemMenu(hwnd, FALSE);
1385 UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1386 if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED)))
1389 if (GetActiveWindow() != hwnd)
1391 LRESULT ma = SendMessageW(hwnd, WM_MOUSEACTIVATE,
1392 (WPARAM)GetAncestor(hwnd, GA_ROOT),
1393 MAKELPARAM(HTCLOSE, WM_NCLBUTTONDOWN));
1396 case MA_NOACTIVATEANDEAT:
1397 case MA_ACTIVATEANDEAT:
1403 SetActiveWindow(hwnd);
1406 WARN("unknown WM_MOUSEACTIVATE code %d\n", (int) ma);
1411 PostMessageW(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
1416 /***********************************************************************
1417 * macdrv_window_frame_changed
1419 * Handler for WINDOW_FRAME_CHANGED events.
1421 void macdrv_window_frame_changed(HWND hwnd, CGRect frame)
1423 struct macdrv_win_data *data;
1426 UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
1430 if (!(data = get_win_data(hwnd))) return;
1431 if (!data->on_screen)
1433 release_win_data(data);
1439 parent = GetAncestor(hwnd, GA_PARENT);
1441 TRACE("win %p/%p new Cocoa frame %s\n", hwnd, data->cocoa_window, wine_dbgstr_cgrect(frame));
1443 rect = rect_from_cgrect(frame);
1444 macdrv_mac_to_window_rect(data, &rect);
1445 MapWindowPoints(0, parent, (POINT *)&rect, 2);
1447 width = rect.right - rect.left;
1448 height = rect.bottom - rect.top;
1450 if (data->window_rect.left == rect.left && data->window_rect.top == rect.top)
1451 flags |= SWP_NOMOVE;
1453 TRACE("%p moving from (%d,%d) to (%d,%d)\n", hwnd, data->window_rect.left,
1454 data->window_rect.top, rect.left, rect.top);
1456 if ((data->window_rect.right - data->window_rect.left == width &&
1457 data->window_rect.bottom - data->window_rect.top == height) ||
1458 (IsRectEmpty(&data->window_rect) && width <= 0 && height <= 0))
1459 flags |= SWP_NOSIZE;
1461 TRACE("%p resizing from (%dx%d) to (%dx%d)\n", hwnd, data->window_rect.right - data->window_rect.left,
1462 data->window_rect.bottom - data->window_rect.top, width, height);
1464 release_win_data(data);
1466 if (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE))
1467 SetWindowPos(hwnd, 0, rect.left, rect.top, width, height, flags);
1471 /***********************************************************************
1472 * macdrv_window_got_focus
1474 * Handler for WINDOW_GOT_FOCUS events.
1476 void macdrv_window_got_focus(HWND hwnd, const macdrv_event *event)
1480 TRACE("win %p/%p serial %lu enabled %d visible %d style %08x focus %p active %p fg %p\n",
1481 hwnd, event->window, event->window_got_focus.serial, IsWindowEnabled(hwnd),
1482 IsWindowVisible(hwnd), GetWindowLongW(hwnd, GWL_STYLE), GetFocus(),
1483 GetActiveWindow(), GetForegroundWindow());
1485 if (can_activate_window(hwnd))
1487 /* simulate a mouse click on the caption to find out
1488 * whether the window wants to be activated */
1489 LRESULT ma = SendMessageW(hwnd, WM_MOUSEACTIVATE,
1490 (WPARAM)GetAncestor(hwnd, GA_ROOT),
1491 MAKELONG(HTCAPTION,WM_LBUTTONDOWN));
1492 if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE)
1494 TRACE("setting foreground window to %p\n", hwnd);
1495 SetForegroundWindow(hwnd);
1500 TRACE("win %p/%p rejecting focus\n", hwnd, event->window);
1501 macdrv_window_rejected_focus(event);
1505 /***********************************************************************
1506 * macdrv_window_lost_focus
1508 * Handler for WINDOW_LOST_FOCUS events.
1510 void macdrv_window_lost_focus(HWND hwnd, const macdrv_event *event)
1514 TRACE("win %p/%p fg %p\n", hwnd, event->window, GetForegroundWindow());
1516 if (hwnd == GetForegroundWindow())
1517 SendMessageW(hwnd, WM_CANCELMODE, 0, 0);
1521 /***********************************************************************
1522 * macdrv_app_deactivated
1524 * Handler for APP_DEACTIVATED events.
1526 void macdrv_app_deactivated(void)
1528 if (GetActiveWindow() == GetForegroundWindow())
1530 TRACE("setting fg to desktop\n");
1531 SetForegroundWindow(GetDesktopWindow());
1536 /***********************************************************************
1537 * macdrv_window_did_minimize
1539 * Handler for WINDOW_DID_MINIMIZE events.
1541 void macdrv_window_did_minimize(HWND hwnd)
1543 struct macdrv_win_data *data;
1546 TRACE("win %p\n", hwnd);
1548 if (!(data = get_win_data(hwnd))) return;
1549 if (data->minimized) goto done;
1551 style = GetWindowLongW(hwnd, GWL_STYLE);
1553 data->minimized = TRUE;
1554 if ((style & WS_MINIMIZEBOX) && !(style & WS_DISABLED))
1556 TRACE("minimizing win %p/%p\n", hwnd, data->cocoa_window);
1557 release_win_data(data);
1558 SendMessageW(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
1561 TRACE("not minimizing win %p/%p style %08x\n", hwnd, data->cocoa_window, style);
1564 release_win_data(data);
1568 /***********************************************************************
1569 * macdrv_window_did_unminimize
1571 * Handler for WINDOW_DID_UNMINIMIZE events.
1573 void macdrv_window_did_unminimize(HWND hwnd)
1575 struct macdrv_win_data *data;
1578 TRACE("win %p\n", hwnd);
1580 if (!(data = get_win_data(hwnd))) return;
1581 if (!data->minimized) goto done;
1583 style = GetWindowLongW(hwnd, GWL_STYLE);
1585 data->minimized = FALSE;
1586 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1588 TRACE("restoring win %p/%p\n", hwnd, data->cocoa_window);
1589 release_win_data(data);
1590 SendMessageW(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
1594 TRACE("not restoring win %p/%p style %08x\n", hwnd, data->cocoa_window, style);
1597 release_win_data(data);