winemac: Implement WINDOW_FRAME_CHANGED event to tell Wine when window is moved or resized.
This commit is contained in:
parent
b28aff0dd7
commit
6e59740e18
|
@ -207,6 +207,10 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w
|
|||
|
||||
[window setContentView:contentView];
|
||||
|
||||
/* In case Cocoa adjusted the frame we tried to set, generate a frame-changed
|
||||
event. The back end will ignore it if nothing actually changed. */
|
||||
[window windowDidResize:nil];
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
|
@ -297,6 +301,11 @@ - (BOOL) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next
|
|||
self.latentParentWindow = nil;
|
||||
}
|
||||
|
||||
/* Cocoa may adjust the frame when the window is ordered onto the screen.
|
||||
Generate a frame-changed event just in case. The back end will ignore
|
||||
it if nothing actually changed. */
|
||||
[self windowDidResize:nil];
|
||||
|
||||
if (![self isExcludedFromWindowsMenu])
|
||||
[NSApp addWindowsItem:self title:[self title] filename:NO];
|
||||
}
|
||||
|
@ -341,6 +350,10 @@ - (BOOL) setFrameIfOnScreen:(NSRect)contentRect
|
|||
[self setFrame:frame display:YES];
|
||||
}
|
||||
|
||||
/* In case Cocoa adjusted the frame we tried to set, generate a frame-changed
|
||||
event. The back end will ignore it if nothing actually changed. */
|
||||
[self windowDidResize:nil];
|
||||
|
||||
return on_screen;
|
||||
}
|
||||
|
||||
|
@ -435,6 +448,28 @@ - (BOOL) validateMenuItem:(NSMenuItem *)menuItem
|
|||
/*
|
||||
* ---------- NSWindowDelegate methods ----------
|
||||
*/
|
||||
- (void)windowDidMove:(NSNotification *)notification
|
||||
{
|
||||
[self windowDidResize:notification];
|
||||
}
|
||||
|
||||
- (void)windowDidResize:(NSNotification *)notification
|
||||
{
|
||||
macdrv_event event;
|
||||
NSRect frame = [self contentRectForFrameRect:[self frame]];
|
||||
|
||||
[[self class] flipRect:&frame];
|
||||
|
||||
/* Coalesce events by discarding any previous ones still in the queue. */
|
||||
[queue discardEventsMatchingMask:event_mask_for_type(WINDOW_FRAME_CHANGED)
|
||||
forWindow:self];
|
||||
|
||||
event.type = WINDOW_FRAME_CHANGED;
|
||||
event.window = (macdrv_window)[self retain];
|
||||
event.window_frame_changed.frame = NSRectToCGRect(frame);
|
||||
[queue postEvent:&event];
|
||||
}
|
||||
|
||||
- (BOOL)windowShouldClose:(id)sender
|
||||
{
|
||||
macdrv_event event;
|
||||
|
@ -611,6 +646,24 @@ int macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame)
|
|||
return on_screen;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_get_cocoa_window_frame
|
||||
*
|
||||
* Gets the frame of a Cocoa window.
|
||||
*/
|
||||
void macdrv_get_cocoa_window_frame(macdrv_window w, CGRect* out_frame)
|
||||
{
|
||||
WineWindow* window = (WineWindow*)w;
|
||||
|
||||
OnMainThread(^{
|
||||
NSRect frame;
|
||||
|
||||
frame = [window contentRectForFrameRect:[window frame]];
|
||||
[[window class] flipRect:&frame];
|
||||
*out_frame = NSRectToCGRect(frame);
|
||||
});
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_set_cocoa_parent_window
|
||||
*
|
||||
|
|
|
@ -33,6 +33,7 @@ static const char *dbgstr_event(int type)
|
|||
{
|
||||
static const char * const event_names[] = {
|
||||
"WINDOW_CLOSE_REQUESTED",
|
||||
"WINDOW_FRAME_CHANGED",
|
||||
};
|
||||
|
||||
if (0 <= type && type < NUM_EVENT_TYPES) return event_names[type];
|
||||
|
@ -50,7 +51,10 @@ static macdrv_event_mask get_event_mask(DWORD mask)
|
|||
if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return -1;
|
||||
|
||||
if (mask & QS_POSTMESSAGE)
|
||||
{
|
||||
event_mask |= event_mask_for_type(WINDOW_CLOSE_REQUESTED);
|
||||
event_mask |= event_mask_for_type(WINDOW_FRAME_CHANGED);
|
||||
}
|
||||
|
||||
return event_mask;
|
||||
}
|
||||
|
@ -76,6 +80,9 @@ void macdrv_handle_event(macdrv_event *event)
|
|||
case WINDOW_CLOSE_REQUESTED:
|
||||
macdrv_window_close_requested(hwnd);
|
||||
break;
|
||||
case WINDOW_FRAME_CHANGED:
|
||||
macdrv_window_frame_changed(hwnd, event->window_frame_changed.frame);
|
||||
break;
|
||||
default:
|
||||
TRACE(" ignoring\n");
|
||||
break;
|
||||
|
|
|
@ -118,5 +118,6 @@ static inline RECT rect_from_cgrect(CGRect cgrect)
|
|||
extern void set_surface_use_alpha(struct window_surface *window_surface, BOOL use_alpha) DECLSPEC_HIDDEN;
|
||||
|
||||
extern void macdrv_window_close_requested(HWND hwnd) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_window_frame_changed(HWND hwnd, CGRect frame) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif /* __WINE_MACDRV_H */
|
||||
|
|
|
@ -123,6 +123,7 @@
|
|||
/* event */
|
||||
enum {
|
||||
WINDOW_CLOSE_REQUESTED,
|
||||
WINDOW_FRAME_CHANGED,
|
||||
NUM_EVENT_TYPES
|
||||
};
|
||||
|
||||
|
@ -131,6 +132,11 @@
|
|||
typedef struct macdrv_event {
|
||||
int type;
|
||||
macdrv_window window;
|
||||
union {
|
||||
struct {
|
||||
CGRect frame;
|
||||
} window_frame_changed;
|
||||
};
|
||||
} macdrv_event;
|
||||
|
||||
static inline macdrv_event_mask event_mask_for_type(int type)
|
||||
|
@ -179,6 +185,7 @@ extern int macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev,
|
|||
macdrv_window next) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_hide_cocoa_window(macdrv_window w) DECLSPEC_HIDDEN;
|
||||
extern int macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_get_cocoa_window_frame(macdrv_window w, CGRect* out_frame) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_set_cocoa_parent_window(macdrv_window w, macdrv_window parent) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_set_window_surface(macdrv_window w, void *surface, pthread_mutex_t *mutex) DECLSPEC_HIDDEN;
|
||||
extern CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -949,6 +949,51 @@ void CDECL macdrv_SetWindowText(HWND hwnd, LPCWSTR text)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ShowWindow (MACDRV.@)
|
||||
*/
|
||||
UINT CDECL macdrv_ShowWindow(HWND hwnd, INT cmd, RECT *rect, UINT swp)
|
||||
{
|
||||
struct macdrv_thread_data *thread_data = macdrv_thread_data();
|
||||
struct macdrv_win_data *data = get_win_data(hwnd);
|
||||
CGRect frame;
|
||||
|
||||
if (!data || !data->cocoa_window) goto done;
|
||||
if (IsRectEmpty(rect)) goto done;
|
||||
if (GetWindowLongW(hwnd, GWL_STYLE) & WS_MINIMIZE)
|
||||
{
|
||||
if (rect->left != -32000 || rect->top != -32000)
|
||||
{
|
||||
OffsetRect(rect, -32000 - rect->left, -32000 - rect->top);
|
||||
swp &= ~(SWP_NOMOVE | SWP_NOCLIENTMOVE);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
if (!data->on_screen) goto done;
|
||||
|
||||
/* only fetch the new rectangle if the ShowWindow was a result of an external event */
|
||||
|
||||
if (!thread_data->current_event || thread_data->current_event->window != data->cocoa_window)
|
||||
goto done;
|
||||
|
||||
if (thread_data->current_event->type != WINDOW_FRAME_CHANGED)
|
||||
goto done;
|
||||
|
||||
TRACE("win %p/%p cmd %d at %s flags %08x\n",
|
||||
hwnd, data->cocoa_window, cmd, wine_dbgstr_rect(rect), swp);
|
||||
|
||||
macdrv_get_cocoa_window_frame(data->cocoa_window, &frame);
|
||||
*rect = rect_from_cgrect(frame);
|
||||
macdrv_mac_to_window_rect(data, rect);
|
||||
TRACE("rect %s -> %s\n", wine_dbgstr_cgrect(frame), wine_dbgstr_rect(rect));
|
||||
swp &= ~(SWP_NOMOVE | SWP_NOCLIENTMOVE | SWP_NOSIZE | SWP_NOCLIENTSIZE);
|
||||
|
||||
done:
|
||||
release_win_data(data);
|
||||
return swp;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* UpdateLayeredWindow (MACDRV.@)
|
||||
*/
|
||||
|
@ -1148,12 +1193,15 @@ void CDECL macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
|
|||
const RECT *visible_rect, const RECT *valid_rects,
|
||||
struct window_surface *surface)
|
||||
{
|
||||
struct macdrv_thread_data *thread_data;
|
||||
struct macdrv_win_data *data;
|
||||
DWORD new_style = GetWindowLongW(hwnd, GWL_STYLE);
|
||||
RECT old_window_rect, old_whole_rect, old_client_rect;
|
||||
|
||||
if (!(data = get_win_data(hwnd))) return;
|
||||
|
||||
thread_data = macdrv_thread_data();
|
||||
|
||||
old_window_rect = data->window_rect;
|
||||
old_whole_rect = data->whole_rect;
|
||||
old_client_rect = data->client_rect;
|
||||
|
@ -1224,8 +1272,14 @@ void CDECL macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
|
|||
show_window(data);
|
||||
}
|
||||
|
||||
sync_window_position(data, swp_flags);
|
||||
set_cocoa_window_properties(data);
|
||||
/* 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 ||
|
||||
thread_data->current_event->type != WINDOW_FRAME_CHANGED)
|
||||
{
|
||||
sync_window_position(data, swp_flags);
|
||||
set_cocoa_window_properties(data);
|
||||
}
|
||||
|
||||
done:
|
||||
release_win_data(data);
|
||||
|
@ -1279,3 +1333,55 @@ void macdrv_window_close_requested(HWND hwnd)
|
|||
PostMessageW(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_window_frame_changed
|
||||
*
|
||||
* Handler for WINDOW_FRAME_CHANGED events.
|
||||
*/
|
||||
void macdrv_window_frame_changed(HWND hwnd, CGRect frame)
|
||||
{
|
||||
struct macdrv_win_data *data;
|
||||
RECT rect;
|
||||
HWND parent;
|
||||
UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
|
||||
int width, height;
|
||||
|
||||
if (!hwnd) return;
|
||||
if (!(data = get_win_data(hwnd))) return;
|
||||
if (!data->on_screen) goto done;
|
||||
|
||||
/* Get geometry */
|
||||
|
||||
parent = GetAncestor(hwnd, GA_PARENT);
|
||||
|
||||
TRACE("win %p/%p new Cocoa frame %s\n", hwnd, data->cocoa_window, wine_dbgstr_cgrect(frame));
|
||||
|
||||
rect = rect_from_cgrect(frame);
|
||||
macdrv_mac_to_window_rect(data, &rect);
|
||||
MapWindowPoints(0, parent, (POINT *)&rect, 2);
|
||||
|
||||
width = rect.right - rect.left;
|
||||
height = rect.bottom - rect.top;
|
||||
|
||||
if (data->window_rect.left == rect.left && data->window_rect.top == rect.top)
|
||||
flags |= SWP_NOMOVE;
|
||||
else
|
||||
TRACE("%p moving from (%d,%d) to (%d,%d)\n", hwnd, data->window_rect.left,
|
||||
data->window_rect.top, rect.left, rect.top);
|
||||
|
||||
if ((data->window_rect.right - data->window_rect.left == width &&
|
||||
data->window_rect.bottom - data->window_rect.top == height) ||
|
||||
(IsRectEmpty(&data->window_rect) && width <= 0 && height <= 0))
|
||||
flags |= SWP_NOSIZE;
|
||||
else
|
||||
TRACE("%p resizing from (%dx%d) to (%dx%d)\n", hwnd, data->window_rect.right - data->window_rect.left,
|
||||
data->window_rect.bottom - data->window_rect.top, width, height);
|
||||
|
||||
done:
|
||||
release_win_data(data);
|
||||
|
||||
if (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE))
|
||||
SetWindowPos(hwnd, 0, rect.left, rect.top, width, height, flags);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
@ cdecl SetWindowRgn(long long long) macdrv_SetWindowRgn
|
||||
@ cdecl SetWindowStyle(ptr long ptr) macdrv_SetWindowStyle
|
||||
@ cdecl SetWindowText(long wstr) macdrv_SetWindowText
|
||||
@ cdecl ShowWindow(long long ptr long) macdrv_ShowWindow
|
||||
@ cdecl UpdateLayeredWindow(long ptr ptr) macdrv_UpdateLayeredWindow
|
||||
@ cdecl WindowMessage(long long long long) macdrv_WindowMessage
|
||||
@ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) macdrv_WindowPosChanged
|
||||
|
|
Loading…
Reference in New Issue