From: Rémi Bernon rbernon@codeweavers.com
In order to better distinguish them from the ConfigureNotify events sent by the WM.
Some window managers (openbox) send a sequence of ConfigureNotify to top-level window frames when restoring them from minimized state, for animation purposes, and they shouldn't be reflected on the Win32 side.
We do not need to update the Win32 state when top-level windows frame is being moved, as the WM will send us a ConfigureNotify later and we only need to keep track of its position for mouse event coordinates.
Handle the generated GravityNotify events for embedded windows only, to match their Win32 state/config with their X state/config. --- dlls/winex11.drv/event.c | 103 +++++++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 32 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 1008769f0b9..9b9d626fc9a 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -86,6 +86,7 @@ static BOOL X11DRV_Expose( HWND hwnd, XEvent *event ); static BOOL X11DRV_MapNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_UnmapNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_ReparentNotify( HWND hwnd, XEvent *event ); +static BOOL X11DRV_GravityNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *event ); static BOOL X11DRV_ClientMessage( HWND hwnd, XEvent *event ); @@ -118,7 +119,7 @@ static x11drv_event_handler handlers[MAX_EVENT_HANDLERS] = X11DRV_ReparentNotify, /* 21 ReparentNotify */ X11DRV_ConfigureNotify, /* 22 ConfigureNotify */ NULL, /* 23 ConfigureRequest */ - NULL, /* 24 GravityNotify */ + X11DRV_GravityNotify, /* 24 GravityNotify */ NULL, /* 25 ResizeRequest */ NULL, /* 26 CirculateNotify */ NULL, /* 27 CirculateRequest */ @@ -171,41 +172,24 @@ static inline void free_event_data( XEvent *event ) #endif }
-static void host_window_send_configure_events( struct host_window *win, Display *display, unsigned long serial, XEvent *previous ) +static void host_window_send_gravity_events( struct host_window *win, Display *display, unsigned long serial, XEvent *previous ) { - XConfigureEvent configure = {.type = ConfigureNotify, .serial = serial, .display = display}; + XGravityEvent event = {.type = GravityNotify, .serial = serial, .display = display}; unsigned int i;
for (i = 0; i < win->children_count; i++) { RECT rect = win->children[i].rect; - struct x11drv_win_data *data; - HWND hwnd; - - configure.event = win->children[i].window; - configure.window = configure.event; - configure.x = rect.left; - configure.y = rect.top; - configure.width = rect.right - rect.left; - configure.height = rect.bottom - rect.top; - configure.send_event = 0; - - /* Only send a fake event if we're not expecting one from a state/config request. - * We may know what was requested, but not what the WM will decide to reply, and our - * fake event might trigger some undesired changes before the real ConfigureNotify. - */ - if (!XFindContext( configure.display, configure.window, winContext, (char **)&hwnd ) && - (data = get_win_data( hwnd ))) - { - /* embedded windows won't receive synthetic ConfigureNotify and are positioned by the WM */ - BOOL has_serial = !data->embedded && (data->wm_state_serial || data->configure_serial); - release_win_data( data ); - if (has_serial) continue; - }
- if (previous->type == ConfigureNotify && previous->xconfigure.window == configure.window) continue; - TRACE( "generating ConfigureNotify for window %p/%lx, rect %s\n", hwnd, configure.window, wine_dbgstr_rect(&rect) ); - XPutBackEvent( configure.display, (XEvent *)&configure ); + event.event = win->children[i].window; + event.window = event.event; + event.x = rect.left; + event.y = rect.top; + event.send_event = 0; + + if (previous->type == ConfigureNotify && previous->xconfigure.window == event.window) continue; + TRACE( "generating GravityNotify for window %lx, rect %s\n", event.window, wine_dbgstr_rect(&rect) ); + XPutBackEvent( event.display, (XEvent *)&event ); } }
@@ -226,7 +210,7 @@ static BOOL host_window_filter_event( XEvent *event, XEvent *previous ) XReparentEvent *reparent = (XReparentEvent *)event; TRACE( "host window %p/%lx ReparentNotify, parent %lx\n", win, win->window, reparent->parent ); host_window_set_parent( win, reparent->parent ); - host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous ); + host_window_send_gravity_events( win, event->xany.display, event->xany.serial, previous ); break; } case GravityNotify: @@ -235,7 +219,7 @@ static BOOL host_window_filter_event( XEvent *event, XEvent *previous ) OffsetRect( &win->rect, gravity->x - win->rect.left, gravity->y - win->rect.top ); if (win->parent) win->rect = host_window_configure_child( win->parent, win->window, win->rect, FALSE ); TRACE( "host window %p/%lx GravityNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); - host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous ); + host_window_send_gravity_events( win, event->xany.display, event->xany.serial, previous ); break; } case ConfigureNotify: @@ -244,7 +228,7 @@ static BOOL host_window_filter_event( XEvent *event, XEvent *previous ) SetRect( &win->rect, configure->x, configure->y, configure->x + configure->width, configure->y + configure->height ); if (win->parent) win->rect = host_window_configure_child( win->parent, win->window, win->rect, configure->send_event ); TRACE( "host window %p/%lx ConfigureNotify, rect %s\n", win, win->window, wine_dbgstr_rect(&win->rect) ); - host_window_send_configure_events( win, event->xany.display, event->xany.serial, previous ); + host_window_send_gravity_events( win, event->xany.display, event->xany.serial, previous ); break; } } @@ -1109,6 +1093,7 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) if (!hwnd) return FALSE; if (!(data = get_win_data( hwnd ))) return FALSE;
+ /* update our view of the window tree for mouse event coordinate mapping */ if (data->whole_window && data->parent && !data->parent_invalid) { SetRect( &rect, event->x, event->y, event->x + event->width, event->y + event->height ); @@ -1142,6 +1127,60 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) return TRUE; }
+/*********************************************************************** + * X11DRV_GravityNotify + */ +static BOOL X11DRV_GravityNotify( HWND hwnd, XEvent *xev ) +{ + XGravityEvent *event = &xev->xgravity; + struct x11drv_win_data *data; + RECT rect; + POINT pos = {event->x, event->y}; + UINT config_cmd, state_cmd; + + if (!hwnd) return FALSE; + if (!(data = get_win_data( hwnd ))) return FALSE; + rect = data->rects.window; + + /* update our view of the window tree for mouse event coordinate mapping */ + if (data->whole_window && data->parent && !data->parent_invalid) + { + OffsetRect( &rect, event->x - rect.left, event->y - rect.top ); + host_window_configure_child( data->parent, data->whole_window, rect, event->send_event ); + } + + /* only handle GravityNotify events, that we generate ourselves, for embedded windows, + * top-level windows will receive the WM synthetic ConfigureNotify events instead. + */ + if (data->embedded) + { + /* synthetic events are already in absolute coordinates */ + if (!event->send_event) pos = host_window_map_point( data->parent, event->x, event->y ); + else if (is_virtual_desktop()) FIXME( "synthetic event mapping not implemented\n" ); + + pos = root_to_virtual_screen( pos.x, pos.y ); + OffsetRect( &rect, pos.x - rect.left, pos.y - rect.top ); + window_configure_notify( data, event->serial, &rect ); + } + + release_win_data( data ); + + if (!get_window_state_updates( hwnd, &state_cmd, &config_cmd, &rect )) return FALSE; + + if (state_cmd) + { + if (LOWORD(state_cmd) == SC_RESTORE && HIWORD(state_cmd)) NtUserSetActiveWindow( hwnd ); + send_message( hwnd, WM_SYSCOMMAND, LOWORD(state_cmd), 0 ); + } + + if (config_cmd) + { + if (LOWORD(config_cmd) == SC_MOVE) NtUserSetRawWindowPos( hwnd, rect, HIWORD(config_cmd), FALSE ); + else send_message( hwnd, WM_SYSCOMMAND, LOWORD(config_cmd), 0 ); + } + + return TRUE; +}
/*********************************************************************** * get_window_wm_state