diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index b6b4819c0d7..bfdffc86283 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -129,12 +129,12 @@ static inline RECT rect_from_cgrect(CGRect cgrect) { HWND hwnd; /* hwnd that this private data belongs to */ macdrv_window cocoa_window; + macdrv_view cocoa_view; + macdrv_view client_cocoa_view; RECT window_rect; /* USER window rectangle relative to parent */ RECT whole_rect; /* Mac window rectangle for the whole window relative to parent */ RECT client_rect; /* client area relative to parent */ int pixel_format; /* pixel format for GL */ - macdrv_view gl_view; /* view for GL */ - RECT gl_rect; /* GL view rectangle relative to whole_rect */ COLORREF color_key; /* color key for layered window; CLR_INVALID is not color keyed */ unsigned int on_screen : 1; /* is window ordered in? (minimized or not) */ unsigned int shaped : 1; /* is window using a custom region shape? */ @@ -206,8 +206,7 @@ static inline RECT rect_from_cgrect(CGRect cgrect) extern BOOL query_drag_drop(macdrv_query* query) DECLSPEC_HIDDEN; extern struct opengl_funcs *macdrv_wine_get_wgl_driver(PHYSDEV dev, UINT version) DECLSPEC_HIDDEN; -extern void sync_gl_view(struct macdrv_win_data *data) DECLSPEC_HIDDEN; -extern void set_gl_view_parent(HWND hwnd, HWND parent) DECLSPEC_HIDDEN; +extern void sync_gl_view(struct macdrv_win_data* data, const RECT* old_whole_rect, const RECT* old_client_rect) DECLSPEC_HIDDEN; extern CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP hbmColor, unsigned char *color_bits, int color_size, HBITMAP hbmMask, diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c index 0e067d4765c..a4b8e346084 100644 --- a/dlls/winemac.drv/opengl.c +++ b/dlls/winemac.drv/opengl.c @@ -1549,76 +1549,6 @@ static BOOL create_context(struct wgl_context *context, CGLContextObj share, uns } -static BOOL get_gl_view_window_rect(struct macdrv_win_data *data, macdrv_window *window, RECT *rect) -{ - BOOL ret = TRUE; - *rect = data->client_rect; - - if (data->cocoa_window) - { - if (window) - *window = data->cocoa_window; - OffsetRect(rect, -data->whole_rect.left, -data->whole_rect.top); - } - else - { - HWND top = GetAncestor(data->hwnd, GA_ROOT); - HWND parent = GetAncestor(data->hwnd, GA_PARENT); - struct macdrv_win_data *top_data = get_win_data(top); - - if (top_data && top_data->cocoa_window) - { - if (window) - *window = top_data->cocoa_window; - MapWindowPoints(parent, 0, (POINT*)rect, 2); - OffsetRect(rect, -top_data->whole_rect.left, -top_data->whole_rect.top); - } - else - ret = FALSE; - - release_win_data(top_data); - } - - return ret; -} - - -/*********************************************************************** - * set_win_format - */ -static BOOL set_win_format(struct macdrv_win_data *data, int format) -{ - TRACE("hwnd %p format %d\n", data->hwnd, format); - - if (!data->gl_view) - { - macdrv_window cocoa_window; - - if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect)) - { - ERR("no top-level parent with Cocoa window in this process\n"); - return FALSE; - } - - data->gl_view = macdrv_create_view(cgrect_from_rect(data->gl_rect)); - if (!data->gl_view) - { - WARN("failed to create GL view for window %p rect %s\n", cocoa_window, wine_dbgstr_rect(&data->gl_rect)); - return FALSE; - } - macdrv_set_view_hidden(data->gl_view, FALSE); - macdrv_set_view_superview(data->gl_view, NULL, cocoa_window, NULL, NULL); - - TRACE("created GL view %p in window %p at %s\n", data->gl_view, cocoa_window, - wine_dbgstr_rect(&data->gl_rect)); - } - - data->pixel_format = format; - - return TRUE; -} - - /********************************************************************** * set_pixel_format * @@ -1665,11 +1595,7 @@ static BOOL set_pixel_format(HDC hdc, int fmt, BOOL allow_reset) goto done; } - if (!set_win_format(data, fmt)) - { - WARN("Couldn't set format of the window, returning failure\n"); - goto done; - } + data->pixel_format = fmt; TRACE("pixel format:\n"); TRACE(" window: %u\n", (unsigned int)pf->window); @@ -1712,40 +1638,6 @@ static void mark_contexts_for_moved_view(macdrv_view view) } -/********************************************************************** - * set_gl_view_parent - */ -void set_gl_view_parent(HWND hwnd, HWND parent) -{ - struct macdrv_win_data *data; - - if (!(data = get_win_data(hwnd))) return; - - if (data->gl_view) - { - macdrv_window cocoa_window; - - TRACE("moving GL view %p to parent %p\n", data->gl_view, parent); - - if (!get_gl_view_window_rect(data, &cocoa_window, &data->gl_rect)) - { - ERR("no top-level parent with Cocoa window in this process\n"); - macdrv_dispose_view(data->gl_view); - data->gl_view = NULL; - release_win_data(data); - __wine_set_pixel_format( hwnd, 0 ); - return; - } - - macdrv_set_view_superview(data->gl_view, NULL, cocoa_window, NULL, NULL); - macdrv_set_view_frame(data->gl_view, cgrect_from_rect(data->gl_rect)); - mark_contexts_for_moved_view(data->gl_view); - } - - release_win_data(data); -} - - /********************************************************************** * sync_context_rect */ @@ -1756,11 +1648,15 @@ static BOOL sync_context_rect(struct wgl_context *context) { struct macdrv_win_data *data = get_win_data(context->draw_hwnd); - if (data && data->gl_view && data->gl_view == context->draw_view && - memcmp(&context->draw_rect, &data->gl_rect, sizeof(context->draw_rect))) + if (data && data->client_cocoa_view == context->draw_view) { - context->draw_rect = data->gl_rect; - ret = TRUE; + RECT rect = data->client_rect; + OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top); + if (memcmp(&context->draw_rect, &rect, sizeof(context->draw_rect))) + { + context->draw_rect = rect; + ret = TRUE; + } } release_win_data(data); } @@ -3652,8 +3548,9 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w set_swap_interval(context, data->swap_interval); context->draw_hwnd = hwnd; - context->draw_view = data->gl_view; - context->draw_rect = data->gl_rect; + context->draw_view = data->client_cocoa_view; + context->draw_rect = data->client_rect; + OffsetRect(&context->draw_rect, -data->whole_rect.left, -data->whole_rect.top); context->draw_pbuffer = NULL; release_win_data(data); } @@ -3699,10 +3596,11 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w { if ((data = get_win_data(hwnd))) { - if (data->gl_view != context->draw_view) + if (data->client_cocoa_view != context->draw_view) { - context->read_view = data->gl_view; - context->read_rect = data->gl_rect; + context->read_view = data->client_cocoa_view; + context->read_rect = data->client_rect; + OffsetRect(&context->read_rect, -data->whole_rect.left, -data->whole_rect.top); } release_win_data(data); } @@ -4421,20 +4319,19 @@ failed: * Synchronize the Mac GL view position with the Windows child window * position. */ -void sync_gl_view(struct macdrv_win_data *data) +void sync_gl_view(struct macdrv_win_data* data, const RECT* old_whole_rect, const RECT* old_client_rect) { - RECT rect; - - TRACE("hwnd %p gl_view %p\n", data->hwnd, data->gl_view); - - if (!data->gl_view) return; - - if (get_gl_view_window_rect(data, NULL, &rect) && memcmp(&data->gl_rect, &rect, sizeof(rect))) + if (data->client_cocoa_view && data->pixel_format) { - TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect)); - macdrv_set_view_frame(data->gl_view, cgrect_from_rect(rect)); - data->gl_rect = rect; - mark_contexts_for_moved_view(data->gl_view); + RECT old = *old_client_rect, new = data->client_rect; + + OffsetRect(&old, -old_whole_rect->left, -old_whole_rect->top); + OffsetRect(&new, -data->whole_rect.left, -data->whole_rect.top); + if (memcmp(&old, &new, sizeof(old))) + { + TRACE("GL view %p changed position; marking contexts\n", data->client_cocoa_view); + mark_contexts_for_moved_view(data->client_cocoa_view); + } } } @@ -4696,7 +4593,7 @@ static BOOL macdrv_wglSwapBuffers(HDC hdc) return FALSE; } - if (context && context->draw_view == data->gl_view) + if (context && context->draw_view == data->client_cocoa_view) match = TRUE; release_win_data(data); diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 0d6ef53e4a9..59d7763d923 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -294,6 +294,36 @@ macdrv_window macdrv_get_cocoa_window(HWND hwnd, BOOL require_on_screen) } +/*********************************************************************** + * macdrv_get_cocoa_view + * + * Return the Cocoa view associated with a window + */ +macdrv_view macdrv_get_cocoa_view(HWND hwnd) +{ + struct macdrv_win_data *data = get_win_data(hwnd); + macdrv_view ret = data ? data->cocoa_view : NULL; + + release_win_data(data); + return ret; +} + + +/*********************************************************************** + * macdrv_get_client_cocoa_view + * + * Return the Cocoa view associated with a window's client area + */ +macdrv_view macdrv_get_client_cocoa_view(HWND hwnd) +{ + struct macdrv_win_data *data = get_win_data(hwnd); + macdrv_view ret = data ? data->client_cocoa_view : NULL; + + release_win_data(data); + return ret; +} + + /*********************************************************************** * set_cocoa_window_properties * @@ -603,6 +633,27 @@ static void sync_window_min_max_info(HWND hwnd) } +/********************************************************************** + * create_client_cocoa_view + * + * Create the Cocoa view for a window's client area + */ +static void create_client_cocoa_view(struct macdrv_win_data *data) +{ + RECT rect = data->client_rect; + OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top); + + if (data->client_cocoa_view) + macdrv_set_view_frame(data->client_cocoa_view, cgrect_from_rect(rect)); + else + { + data->client_cocoa_view = macdrv_create_view(cgrect_from_rect(rect)); + macdrv_set_view_hidden(data->client_cocoa_view, FALSE); + } + macdrv_set_view_superview(data->client_cocoa_view, data->cocoa_view, data->cocoa_window, NULL, NULL); +} + + /********************************************************************** * create_cocoa_window * @@ -646,6 +697,7 @@ static void create_cocoa_window(struct macdrv_win_data *data) data->cocoa_window = macdrv_create_cocoa_window(&wf, frame, data->hwnd, thread_data->queue); if (!data->cocoa_window) goto done; + create_client_cocoa_view(data); set_cocoa_window_properties(data); @@ -687,6 +739,41 @@ static void destroy_cocoa_window(struct macdrv_win_data *data) } +/********************************************************************** + * create_cocoa_view + * + * Create the Cocoa view for a given Windows child window + */ +static void create_cocoa_view(struct macdrv_win_data *data) +{ + data->shaped = FALSE; + data->whole_rect = data->window_rect; + + TRACE("creating %p window %s whole %s client %s\n", data->hwnd, wine_dbgstr_rect(&data->window_rect), + wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect)); + + data->cocoa_view = macdrv_create_view(cgrect_from_rect(data->whole_rect)); + create_client_cocoa_view(data); +} + + +/********************************************************************** + * destroy_cocoa_view + * + * Destroy the Cocoa view for a given window. + */ +static void destroy_cocoa_view(struct macdrv_win_data *data) +{ + if (!data->cocoa_view) return; + + TRACE("win %p Cocoa view %p\n", data->hwnd, data->cocoa_view); + + macdrv_dispose_view(data->cocoa_view); + data->cocoa_view = NULL; + data->on_screen = FALSE; +} + + /*********************************************************************** * macdrv_create_win_data * @@ -721,6 +808,13 @@ static struct macdrv_win_data *macdrv_create_win_data(HWND hwnd, const RECT *win hwnd, data->cocoa_window, wine_dbgstr_rect(&data->window_rect), wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect)); } + else + { + create_cocoa_view(data); + TRACE("win %p/%p window %s whole %s client %s\n", + hwnd, data->cocoa_view, wine_dbgstr_rect(&data->window_rect), + wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect)); + } return data; } @@ -768,6 +862,13 @@ static void show_window(struct macdrv_win_data *data) if (activate) activate_on_focus_time = 0; } + else + { + TRACE("win %p/%p showing view\n", data->hwnd, data->cocoa_view); + + macdrv_set_view_hidden(data->cocoa_view, FALSE); + data->on_screen = TRUE; + } } @@ -780,6 +881,8 @@ static void hide_window(struct macdrv_win_data *data) if (data->cocoa_window) macdrv_hide_cocoa_window(data->cocoa_window); + else + macdrv_set_view_hidden(data->cocoa_view, TRUE); data->on_screen = FALSE; } @@ -789,7 +892,41 @@ static void hide_window(struct macdrv_win_data *data) */ static void sync_window_z_order(struct macdrv_win_data *data) { - if (data->on_screen) + if (data->cocoa_view) + { + HWND parent = GetAncestor(data->hwnd, GA_PARENT); + macdrv_view superview = macdrv_get_client_cocoa_view(parent); + macdrv_window window = NULL; + HWND prev; + HWND next = NULL; + macdrv_view prev_view = NULL; + macdrv_view next_view = NULL; + + if (!superview) + { + window = macdrv_get_cocoa_window(parent, FALSE); + if (!window) + WARN("hwnd %p/%p parent %p has no Cocoa window or view in this process\n", data->hwnd, data->cocoa_view, parent); + } + + /* find window that this one must be after */ + prev = GetWindow(data->hwnd, GW_HWNDPREV); + while (prev && !(prev_view = macdrv_get_cocoa_view(prev))) + prev = GetWindow(prev, GW_HWNDPREV); + if (!prev_view) + { + /* find window that this one must be before */ + next = GetWindow(data->hwnd, GW_HWNDNEXT); + while (next && !(next_view = macdrv_get_cocoa_view(next))) + next = GetWindow(next, GW_HWNDNEXT); + } + + TRACE("win %p/%p below %p/%p above %p/%p\n", + data->hwnd, data->cocoa_view, prev, prev_view, next, next_view); + + macdrv_set_view_superview(data->cocoa_view, superview, window, prev_view, next_view); + } + else if (data->on_screen) show_window(data); } @@ -869,24 +1006,35 @@ RGNDATA *get_region_data(HRGN hrgn, HDC hdc_lptodp) static void sync_window_position(struct macdrv_win_data *data, UINT swp_flags, const RECT *old_window_rect, const RECT *old_whole_rect) { - CGRect frame; + CGRect frame = cgrect_from_rect(data->whole_rect); + RECT rect; - if (data->minimized) return; + if (data->cocoa_window) + { + if (data->minimized) return; - frame = cgrect_from_rect(data->whole_rect); - constrain_window_frame(&frame); - if (frame.size.width < 1 || frame.size.height < 1) - frame.size.width = frame.size.height = 1; + constrain_window_frame(&frame); + if (frame.size.width < 1 || frame.size.height < 1) + frame.size.width = frame.size.height = 1; + + macdrv_set_cocoa_window_frame(data->cocoa_window, &frame); + } + else + macdrv_set_view_frame(data->cocoa_view, frame); + + rect = data->client_rect; + OffsetRect(&rect, -data->whole_rect.left, -data->whole_rect.top); + macdrv_set_view_frame(data->client_cocoa_view, cgrect_from_rect(rect)); - macdrv_set_cocoa_window_frame(data->cocoa_window, &frame); if (old_window_rect && old_whole_rect && (IsRectEmpty(old_window_rect) != IsRectEmpty(&data->window_rect) || old_window_rect->left - old_whole_rect->left != data->window_rect.left - data->whole_rect.left || old_window_rect->top - old_whole_rect->top != data->window_rect.top - data->whole_rect.top)) sync_window_region(data, (HRGN)1); - TRACE("win %p/%p whole_rect %s frame %s\n", data->hwnd, data->cocoa_window, - wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_cgrect(frame)); + TRACE("win %p/%p whole_rect %s frame %s client %s\n", data->hwnd, + data->cocoa_window ? (void*)data->cocoa_window : (void*)data->cocoa_view, + wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_cgrect(frame), wine_dbgstr_rect(&rect)); if (!(swp_flags & SWP_NOZORDER) || (swp_flags & SWP_SHOWWINDOW)) sync_window_z_order(data); @@ -1290,8 +1438,9 @@ void CDECL macdrv_DestroyWindow(HWND hwnd) if (hwnd == GetCapture()) macdrv_SetCapture(0, 0); - if (data->gl_view) macdrv_dispose_view(data->gl_view); destroy_cocoa_window(data); + destroy_cocoa_view(data); + if (data->client_cocoa_view) macdrv_dispose_view(data->client_cocoa_view); CFDictionaryRemoveValue(win_datas, hwnd); release_win_data(data); @@ -1375,13 +1524,27 @@ void CDECL macdrv_SetParent(HWND hwnd, HWND parent, HWND old_parent) { /* destroy the old Mac window */ destroy_cocoa_window(data); + create_cocoa_view(data); + } + else + { + struct macdrv_win_data *parent_data = get_win_data(parent); + macdrv_window cocoa_window = parent_data ? parent_data->cocoa_window : NULL; + macdrv_view superview = parent_data ? parent_data->client_cocoa_view : NULL; + + if (!cocoa_window && !superview) + WARN("hwnd %p new parent %p has no Cocoa window or view in this process\n", hwnd, parent); + + macdrv_set_view_superview(data->cocoa_view, superview, cocoa_window, NULL, NULL); + release_win_data(parent_data); } } else /* new top level window */ + { + destroy_cocoa_view(data); create_cocoa_window(data); + } release_win_data(data); - - set_gl_view_parent(hwnd, parent); } @@ -1862,9 +2025,9 @@ void CDECL macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, } } - sync_gl_view(data); + sync_gl_view(data, &old_whole_rect, &old_client_rect); - if (!data->cocoa_window) goto done; + if (!data->cocoa_window && !data->cocoa_view) goto done; if (data->on_screen) { @@ -1874,22 +2037,28 @@ void CDECL macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, /* check if we are currently processing an event relevant to this window */ if (!thread_data || !thread_data->current_event || - thread_data->current_event->window != data->cocoa_window || + !data->cocoa_window || thread_data->current_event->window != data->cocoa_window || (thread_data->current_event->type != WINDOW_FRAME_CHANGED && thread_data->current_event->type != WINDOW_DID_UNMINIMIZE)) { sync_window_position(data, swp_flags, &old_window_rect, &old_whole_rect); - set_cocoa_window_properties(data); + if (data->cocoa_window) + set_cocoa_window_properties(data); } if (new_style & WS_VISIBLE) { - if (!data->on_screen || (swp_flags & (SWP_FRAMECHANGED|SWP_STATECHANGED))) - set_cocoa_window_properties(data); + if (data->cocoa_window) + { + if (!data->on_screen || (swp_flags & (SWP_FRAMECHANGED|SWP_STATECHANGED))) + set_cocoa_window_properties(data); - /* layered windows are not shown until their attributes are set */ - if (!data->on_screen && - (data->layered || !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED))) + /* layered windows are not shown until their attributes are set */ + if (!data->on_screen && + (data->layered || !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED))) + show_window(data); + } + else if (!data->on_screen) show_window(data); }