Commit 5054c798 authored by Alexandre Julliard's avatar Alexandre Julliard

Try to always keep the server window Z-order in sync with the X11 one

using a heuristic based on mouse and expose events.
parent 9c7932d4
...@@ -68,7 +68,7 @@ POINT cursor_pos; ...@@ -68,7 +68,7 @@ POINT cursor_pos;
* *
* get the coordinates of a mouse event * get the coordinates of a mouse event
*/ */
static inline void get_coords( HWND hwnd, Window window, int x, int y, POINT *pt ) static inline void get_coords( HWND hwnd, int x, int y, POINT *pt )
{ {
struct x11drv_win_data *data = X11DRV_get_win_data( hwnd ); struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
...@@ -84,7 +84,7 @@ static inline void get_coords( HWND hwnd, Window window, int x, int y, POINT *pt ...@@ -84,7 +84,7 @@ static inline void get_coords( HWND hwnd, Window window, int x, int y, POINT *pt
* *
* Update the button state with what X provides us * Update the button state with what X provides us
*/ */
static void update_button_state( unsigned int state ) static inline void update_button_state( unsigned int state )
{ {
key_state_table[VK_LBUTTON] = (state & Button1Mask ? 0x80 : 0); key_state_table[VK_LBUTTON] = (state & Button1Mask ? 0x80 : 0);
key_state_table[VK_MBUTTON] = (state & Button2Mask ? 0x80 : 0); key_state_table[VK_MBUTTON] = (state & Button2Mask ? 0x80 : 0);
...@@ -97,7 +97,7 @@ static void update_button_state( unsigned int state ) ...@@ -97,7 +97,7 @@ static void update_button_state( unsigned int state )
* *
* Update the key state with what X provides us * Update the key state with what X provides us
*/ */
static void update_key_state( unsigned int state ) static inline void update_key_state( unsigned int state )
{ {
key_state_table[VK_SHIFT] = (state & ShiftMask ? 0x80 : 0); key_state_table[VK_SHIFT] = (state & ShiftMask ? 0x80 : 0);
key_state_table[VK_CONTROL] = (state & ControlMask ? 0x80 : 0); key_state_table[VK_CONTROL] = (state & ControlMask ? 0x80 : 0);
...@@ -105,6 +105,48 @@ static void update_key_state( unsigned int state ) ...@@ -105,6 +105,48 @@ static void update_key_state( unsigned int state )
/*********************************************************************** /***********************************************************************
* update_mouse_state
*
* Update the various window states on a mouse event.
*/
static void update_mouse_state( HWND hwnd, Window window, int x, int y, unsigned int state, POINT *pt )
{
struct x11drv_thread_data *data = x11drv_thread_data();
get_coords( hwnd, x, y, pt );
update_key_state( state );
/* update the cursor */
if (data->cursor_window != window)
{
data->cursor_window = window;
wine_tsx11_lock();
if (data->cursor) XDefineCursor( data->display, window, data->cursor );
wine_tsx11_unlock();
}
/* update the wine server Z-order */
if (window != data->grab_window &&
/* ignore event if a button is pressed, since the mouse is then grabbed too */
!(state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)))
{
SERVER_START_REQ( update_window_zorder )
{
req->window = hwnd;
req->rect.left = pt->x;
req->rect.top = pt->y;
req->rect.right = pt->x + 1;
req->rect.bottom = pt->y + 1;
wine_server_call( req );
}
SERVER_END_REQ;
}
}
/***********************************************************************
* get_key_state * get_key_state
*/ */
static WORD get_key_state(void) static WORD get_key_state(void)
...@@ -287,25 +329,6 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y, ...@@ -287,25 +329,6 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
/*********************************************************************** /***********************************************************************
* update_cursor
*
* Update the cursor of a window on a mouse event.
*/
static void update_cursor( HWND hwnd, Window win )
{
struct x11drv_thread_data *data = x11drv_thread_data();
if (data->cursor_window != win)
{
data->cursor_window = win;
wine_tsx11_lock();
if (data->cursor) XDefineCursor( data->display, win, data->cursor );
wine_tsx11_unlock();
}
}
/***********************************************************************
* create_cursor * create_cursor
* *
* Create an X cursor from a Windows one. * Create an X cursor from a Windows one.
...@@ -693,9 +716,6 @@ void X11DRV_ButtonPress( HWND hwnd, XEvent *xev ) ...@@ -693,9 +716,6 @@ void X11DRV_ButtonPress( HWND hwnd, XEvent *xev )
if (buttonNum >= NB_BUTTONS) return; if (buttonNum >= NB_BUTTONS) return;
if (!hwnd) return; if (!hwnd) return;
update_cursor( hwnd, event->window );
get_coords( hwnd, event->window, event->x, event->y, &pt );
switch (buttonNum) switch (buttonNum)
{ {
case 3: case 3:
...@@ -705,7 +725,9 @@ void X11DRV_ButtonPress( HWND hwnd, XEvent *xev ) ...@@ -705,7 +725,9 @@ void X11DRV_ButtonPress( HWND hwnd, XEvent *xev )
wData = -WHEEL_DELTA; wData = -WHEEL_DELTA;
break; break;
} }
update_key_state( event->state );
update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
X11DRV_send_mouse_input( hwnd, button_down_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE, X11DRV_send_mouse_input( hwnd, button_down_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, wData, EVENT_x11_time_to_win32_time(event->time), 0, 0 ); pt.x, pt.y, wData, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
} }
...@@ -723,9 +745,8 @@ void X11DRV_ButtonRelease( HWND hwnd, XEvent *xev ) ...@@ -723,9 +745,8 @@ void X11DRV_ButtonRelease( HWND hwnd, XEvent *xev )
if (buttonNum >= NB_BUTTONS || !button_up_flags[buttonNum]) return; if (buttonNum >= NB_BUTTONS || !button_up_flags[buttonNum]) return;
if (!hwnd) return; if (!hwnd) return;
update_cursor( hwnd, event->window ); update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
get_coords( hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
X11DRV_send_mouse_input( hwnd, button_up_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE, X11DRV_send_mouse_input( hwnd, button_up_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 ); pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
} }
...@@ -743,9 +764,8 @@ void X11DRV_MotionNotify( HWND hwnd, XEvent *xev ) ...@@ -743,9 +764,8 @@ void X11DRV_MotionNotify( HWND hwnd, XEvent *xev )
if (!hwnd) return; if (!hwnd) return;
update_cursor( hwnd, event->window ); update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
get_coords( hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
X11DRV_send_mouse_input( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, X11DRV_send_mouse_input( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 ); pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
} }
...@@ -765,9 +785,8 @@ void X11DRV_EnterNotify( HWND hwnd, XEvent *xev ) ...@@ -765,9 +785,8 @@ void X11DRV_EnterNotify( HWND hwnd, XEvent *xev )
if (event->detail == NotifyVirtual || event->detail == NotifyNonlinearVirtual) return; if (event->detail == NotifyVirtual || event->detail == NotifyNonlinearVirtual) return;
/* simulate a mouse motion event */ /* simulate a mouse motion event */
update_cursor( hwnd, event->window ); update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
get_coords( hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
X11DRV_send_mouse_input( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, X11DRV_send_mouse_input( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 ); pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
} }
......
...@@ -159,9 +159,19 @@ void X11DRV_Expose( HWND hwnd, XEvent *xev ) ...@@ -159,9 +159,19 @@ void X11DRV_Expose( HWND hwnd, XEvent *xev )
rect.right > data->client_rect.right || rect.right > data->client_rect.right ||
rect.bottom > data->client_rect.bottom) flags |= RDW_FRAME; rect.bottom > data->client_rect.bottom) flags |= RDW_FRAME;
SERVER_START_REQ( update_window_zorder )
{
req->window = hwnd;
req->rect.left = rect.left + data->whole_rect.left;
req->rect.top = rect.top + data->whole_rect.top;
req->rect.right = rect.right + data->whole_rect.left;
req->rect.bottom = rect.bottom + data->whole_rect.top;
wine_server_call( req );
}
SERVER_END_REQ;
/* make position relative to client area instead of window */ /* make position relative to client area instead of window */
OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top ); OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top );
RedrawWindow( hwnd, &rect, 0, flags ); RedrawWindow( hwnd, &rect, 0, flags );
} }
...@@ -1606,7 +1616,7 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) ...@@ -1606,7 +1616,7 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
BOOL grab; BOOL grab;
Window parent_win, whole_win; Window parent_win, whole_win;
Display *old_gdi_display = NULL; Display *old_gdi_display = NULL;
Display *display = thread_display(); struct x11drv_thread_data *thread_data = x11drv_thread_data();
struct x11drv_win_data *data; struct x11drv_win_data *data;
pt.x = (short)LOWORD(dwPoint); pt.x = (short)LOWORD(dwPoint);
...@@ -1732,21 +1742,22 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) ...@@ -1732,21 +1742,22 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
{ {
wine_tsx11_lock(); wine_tsx11_lock();
XSync( gdi_display, False ); XSync( gdi_display, False );
XGrabServer( display ); XGrabServer( thread_data->display );
XSync( display, False ); XSync( thread_data->display, False );
/* switch gdi display to the thread display, since the server is grabbed */ /* switch gdi display to the thread display, since the server is grabbed */
old_gdi_display = gdi_display; old_gdi_display = gdi_display;
gdi_display = display; gdi_display = thread_data->display;
wine_tsx11_unlock(); wine_tsx11_unlock();
} }
whole_win = X11DRV_get_whole_window( GetAncestor(hwnd,GA_ROOT) ); whole_win = X11DRV_get_whole_window( GetAncestor(hwnd,GA_ROOT) );
parent_win = parent ? X11DRV_get_whole_window( GetAncestor(parent,GA_ROOT) ) : root_window; parent_win = parent ? X11DRV_get_whole_window( GetAncestor(parent,GA_ROOT) ) : root_window;
wine_tsx11_lock(); wine_tsx11_lock();
XGrabPointer( display, whole_win, False, XGrabPointer( thread_data->display, whole_win, False,
PointerMotionMask | ButtonPressMask | ButtonReleaseMask, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync, parent_win, None, CurrentTime ); GrabModeAsync, GrabModeAsync, parent_win, None, CurrentTime );
wine_tsx11_unlock(); wine_tsx11_unlock();
thread_data->grab_window = whole_win;
while(1) while(1)
{ {
...@@ -1846,15 +1857,16 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) ...@@ -1846,15 +1857,16 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
ReleaseDC( parent, hdc ); ReleaseDC( parent, hdc );
wine_tsx11_lock(); wine_tsx11_lock();
XUngrabPointer( display, CurrentTime ); XUngrabPointer( thread_data->display, CurrentTime );
if (grab) if (grab)
{ {
XSync( display, False ); XSync( thread_data->display, False );
XUngrabServer( display ); XUngrabServer( thread_data->display );
XSync( display, False ); XSync( thread_data->display, False );
gdi_display = old_gdi_display; gdi_display = old_gdi_display;
} }
wine_tsx11_unlock(); wine_tsx11_unlock();
thread_data->grab_window = None;
if (HOOK_CallHooks( WH_CBT, HCBT_MOVESIZE, (WPARAM)hwnd, (LPARAM)&sizingRect, TRUE )) if (HOOK_CallHooks( WH_CBT, HCBT_MOVESIZE, (WPARAM)hwnd, (LPARAM)&sizingRect, TRUE ))
moved = FALSE; moved = FALSE;
......
...@@ -62,7 +62,7 @@ static void SetPrimaryDIB(HBITMAP hBmp) ...@@ -62,7 +62,7 @@ static void SetPrimaryDIB(HBITMAP hBmp)
static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
Display *display = thread_display(); struct x11drv_thread_data *data = x11drv_thread_data();
if(message != X11DRV_DD_GrabMessage) if(message != X11DRV_DD_GrabMessage)
return CallWindowProcA(X11DRV_DD_GrabOldProcedure, hWnd, message, wParam, lParam); return CallWindowProcA(X11DRV_DD_GrabOldProcedure, hWnd, message, wParam, lParam);
...@@ -80,14 +80,16 @@ static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM ...@@ -80,14 +80,16 @@ static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
} }
wine_tsx11_lock(); wine_tsx11_lock();
XGrabPointer(display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); XGrabPointer(data->display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
wine_tsx11_unlock(); wine_tsx11_unlock();
data->grab_window = win;
} }
else else
{ {
wine_tsx11_lock(); wine_tsx11_lock();
XUngrabPointer(display, CurrentTime); XUngrabPointer(data->display, CurrentTime);
wine_tsx11_unlock(); wine_tsx11_unlock();
data->grab_window = None;
} }
return 0; return 0;
...@@ -98,7 +100,11 @@ static void GrabPointer(BOOL grab) ...@@ -98,7 +100,11 @@ static void GrabPointer(BOOL grab)
if(grab) { if(grab) {
Window window = X11DRV_get_whole_window(GetFocus()); Window window = X11DRV_get_whole_window(GetFocus());
if(window) if(window)
{
wine_tsx11_lock();
XSetInputFocus(thread_display(), window, RevertToParent, CurrentTime); XSetInputFocus(thread_display(), window, RevertToParent, CurrentTime);
wine_tsx11_unlock();
}
} }
if(!X11DRV_DD_GrabMessage) if(!X11DRV_DD_GrabMessage)
...@@ -107,7 +113,7 @@ static void GrabPointer(BOOL grab) ...@@ -107,7 +113,7 @@ static void GrabPointer(BOOL grab)
X11DRV_DD_GrabOldProcedure = (WNDPROC)SetWindowLongPtrA(X11DRV_DD_PrimaryWnd, X11DRV_DD_GrabOldProcedure = (WNDPROC)SetWindowLongPtrA(X11DRV_DD_PrimaryWnd,
GWLP_WNDPROC, (LONG_PTR)GrabWndProc); GWLP_WNDPROC, (LONG_PTR)GrabWndProc);
SendMessageA(X11DRV_DD_PrimaryWnd, X11DRV_DD_GrabMessage, grab ? 1 : 0, 0); SendMessageW(X11DRV_DD_PrimaryWnd, X11DRV_DD_GrabMessage, grab, 0);
if(SetWindowLongPtrA(X11DRV_DD_PrimaryWnd, GWLP_WNDPROC, if(SetWindowLongPtrA(X11DRV_DD_PrimaryWnd, GWLP_WNDPROC,
(LONG_PTR)X11DRV_DD_GrabOldProcedure) != (LONG_PTR)GrabWndProc) (LONG_PTR)X11DRV_DD_GrabOldProcedure) != (LONG_PTR)GrabWndProc)
......
...@@ -504,6 +504,7 @@ struct x11drv_thread_data ...@@ -504,6 +504,7 @@ struct x11drv_thread_data
int process_event_count; /* recursion count for event processing */ int process_event_count; /* recursion count for event processing */
Cursor cursor; /* current cursor */ Cursor cursor; /* current cursor */
Window cursor_window; /* current window that contains the cursor */ Window cursor_window; /* current window that contains the cursor */
Window grab_window; /* window that currentl grabs the mouse */
HWND last_focus; /* last window that had focus */ HWND last_focus; /* last window that had focus */
XIM xim; /* input method */ XIM xim; /* input method */
Window selection_wnd; /* window used for selection interactions */ Window selection_wnd; /* window used for selection interactions */
......
...@@ -488,6 +488,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) ...@@ -488,6 +488,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
data->process_event_count = 0; data->process_event_count = 0;
data->cursor = None; data->cursor = None;
data->cursor_window = None; data->cursor_window = None;
data->grab_window = None;
data->last_focus = 0; data->last_focus = 0;
data->selection_wnd = 0; data->selection_wnd = 0;
NtCurrentTeb()->driver_data = data; NtCurrentTeb()->driver_data = data;
......
...@@ -2720,6 +2720,19 @@ struct get_update_region_reply ...@@ -2720,6 +2720,19 @@ struct get_update_region_reply
struct update_window_zorder_request
{
struct request_header __header;
user_handle_t window;
rectangle_t rect;
};
struct update_window_zorder_reply
{
struct reply_header __header;
};
struct redraw_window_request struct redraw_window_request
{ {
struct request_header __header; struct request_header __header;
...@@ -3372,6 +3385,7 @@ enum request ...@@ -3372,6 +3385,7 @@ enum request
REQ_get_window_region, REQ_get_window_region,
REQ_set_window_region, REQ_set_window_region,
REQ_get_update_region, REQ_get_update_region,
REQ_update_window_zorder,
REQ_redraw_window, REQ_redraw_window,
REQ_set_window_property, REQ_set_window_property,
REQ_remove_window_property, REQ_remove_window_property,
...@@ -3562,6 +3576,7 @@ union generic_request ...@@ -3562,6 +3576,7 @@ union generic_request
struct get_window_region_request get_window_region_request; struct get_window_region_request get_window_region_request;
struct set_window_region_request set_window_region_request; struct set_window_region_request set_window_region_request;
struct get_update_region_request get_update_region_request; struct get_update_region_request get_update_region_request;
struct update_window_zorder_request update_window_zorder_request;
struct redraw_window_request redraw_window_request; struct redraw_window_request redraw_window_request;
struct set_window_property_request set_window_property_request; struct set_window_property_request set_window_property_request;
struct remove_window_property_request remove_window_property_request; struct remove_window_property_request remove_window_property_request;
...@@ -3750,6 +3765,7 @@ union generic_reply ...@@ -3750,6 +3765,7 @@ union generic_reply
struct get_window_region_reply get_window_region_reply; struct get_window_region_reply get_window_region_reply;
struct set_window_region_reply set_window_region_reply; struct set_window_region_reply set_window_region_reply;
struct get_update_region_reply get_update_region_reply; struct get_update_region_reply get_update_region_reply;
struct update_window_zorder_reply update_window_zorder_reply;
struct redraw_window_reply redraw_window_reply; struct redraw_window_reply redraw_window_reply;
struct set_window_property_reply set_window_property_reply; struct set_window_property_reply set_window_property_reply;
struct remove_window_property_reply remove_window_property_reply; struct remove_window_property_reply remove_window_property_reply;
...@@ -3781,6 +3797,6 @@ union generic_reply ...@@ -3781,6 +3797,6 @@ union generic_reply
struct duplicate_token_reply duplicate_token_reply; struct duplicate_token_reply duplicate_token_reply;
}; };
#define SERVER_PROTOCOL_VERSION 161 #define SERVER_PROTOCOL_VERSION 162
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -1916,6 +1916,13 @@ enum message_type ...@@ -1916,6 +1916,13 @@ enum message_type
#define UPDATE_NOREGION 0x40 /* don't return a region, only the flags */ #define UPDATE_NOREGION 0x40 /* don't return a region, only the flags */
/* Update the z order of a window so that a given rectangle is fully visible */
@REQ(update_window_zorder)
user_handle_t window; /* handle to the window */
rectangle_t rect; /* rectangle that must be visible */
@END
/* Mark parts of a window as needing a redraw */ /* Mark parts of a window as needing a redraw */
@REQ(redraw_window) @REQ(redraw_window)
user_handle_t window; /* handle to the window */ user_handle_t window; /* handle to the window */
......
...@@ -257,6 +257,7 @@ DECL_HANDLER(get_visible_region); ...@@ -257,6 +257,7 @@ DECL_HANDLER(get_visible_region);
DECL_HANDLER(get_window_region); DECL_HANDLER(get_window_region);
DECL_HANDLER(set_window_region); DECL_HANDLER(set_window_region);
DECL_HANDLER(get_update_region); DECL_HANDLER(get_update_region);
DECL_HANDLER(update_window_zorder);
DECL_HANDLER(redraw_window); DECL_HANDLER(redraw_window);
DECL_HANDLER(set_window_property); DECL_HANDLER(set_window_property);
DECL_HANDLER(remove_window_property); DECL_HANDLER(remove_window_property);
...@@ -446,6 +447,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = ...@@ -446,6 +447,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_window_region, (req_handler)req_get_window_region,
(req_handler)req_set_window_region, (req_handler)req_set_window_region,
(req_handler)req_get_update_region, (req_handler)req_get_update_region,
(req_handler)req_update_window_zorder,
(req_handler)req_redraw_window, (req_handler)req_redraw_window,
(req_handler)req_set_window_property, (req_handler)req_set_window_property,
(req_handler)req_remove_window_property, (req_handler)req_remove_window_property,
......
...@@ -2302,6 +2302,13 @@ static void dump_get_update_region_reply( const struct get_update_region_reply * ...@@ -2302,6 +2302,13 @@ static void dump_get_update_region_reply( const struct get_update_region_reply *
dump_varargs_rectangles( cur_size ); dump_varargs_rectangles( cur_size );
} }
static void dump_update_window_zorder_request( const struct update_window_zorder_request *req )
{
fprintf( stderr, " window=%p,", req->window );
fprintf( stderr, " rect=" );
dump_rectangle( &req->rect );
}
static void dump_redraw_window_request( const struct redraw_window_request *req ) static void dump_redraw_window_request( const struct redraw_window_request *req )
{ {
fprintf( stderr, " window=%p,", req->window ); fprintf( stderr, " window=%p,", req->window );
...@@ -2839,6 +2846,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { ...@@ -2839,6 +2846,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_window_region_request, (dump_func)dump_get_window_region_request,
(dump_func)dump_set_window_region_request, (dump_func)dump_set_window_region_request,
(dump_func)dump_get_update_region_request, (dump_func)dump_get_update_region_request,
(dump_func)dump_update_window_zorder_request,
(dump_func)dump_redraw_window_request, (dump_func)dump_redraw_window_request,
(dump_func)dump_set_window_property_request, (dump_func)dump_set_window_property_request,
(dump_func)dump_remove_window_property_request, (dump_func)dump_remove_window_property_request,
...@@ -3027,6 +3035,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -3027,6 +3035,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_update_region_reply, (dump_func)dump_get_update_region_reply,
(dump_func)0, (dump_func)0,
(dump_func)0, (dump_func)0,
(dump_func)0,
(dump_func)dump_remove_window_property_reply, (dump_func)dump_remove_window_property_reply,
(dump_func)dump_get_window_property_reply, (dump_func)dump_get_window_property_reply,
(dump_func)dump_get_window_properties_reply, (dump_func)dump_get_window_properties_reply,
...@@ -3211,6 +3220,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { ...@@ -3211,6 +3220,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_window_region", "get_window_region",
"set_window_region", "set_window_region",
"get_update_region", "get_update_region",
"update_window_zorder",
"redraw_window", "redraw_window",
"set_window_property", "set_window_property",
"remove_window_property", "remove_window_property",
......
...@@ -645,15 +645,23 @@ static struct region *clip_children( struct window *parent, struct window *last, ...@@ -645,15 +645,23 @@ static struct region *clip_children( struct window *parent, struct window *last,
} }
/* compute the intersection of two rectangles; return 0 if the result is empty */
static inline int intersect_rect( rectangle_t *dst, const rectangle_t *src1, const rectangle_t *src2 )
{
dst->left = max( src1->left, src2->left );
dst->top = max( src1->top, src2->top );
dst->right = min( src1->right, src2->right );
dst->bottom = min( src1->bottom, src2->bottom );
return (dst->left < dst->right && dst->top < dst->bottom);
}
/* set the region to the client rect clipped by the window rect, in parent-relative coordinates */ /* set the region to the client rect clipped by the window rect, in parent-relative coordinates */
static void set_region_client_rect( struct region *region, struct window *win ) static void set_region_client_rect( struct region *region, struct window *win )
{ {
rectangle_t rect; rectangle_t rect;
rect.left = max( win->window_rect.left, win->client_rect.left ); intersect_rect( &rect, &win->window_rect, &win->client_rect );
rect.top = max( win->window_rect.top, win->client_rect.top );
rect.right = min( win->window_rect.right, win->client_rect.right );
rect.bottom = min( win->window_rect.bottom, win->client_rect.bottom );
set_region_rect( region, &rect ); set_region_rect( region, &rect );
} }
...@@ -1667,6 +1675,29 @@ DECL_HANDLER(get_update_region) ...@@ -1667,6 +1675,29 @@ DECL_HANDLER(get_update_region)
} }
/* update the z order of a window so that a given rectangle is fully visible */
DECL_HANDLER(update_window_zorder)
{
rectangle_t tmp;
struct window *ptr, *win = get_window( req->window );
if (!win || !win->parent || !is_visible( win )) return; /* nothing to do */
LIST_FOR_EACH_ENTRY( ptr, &win->parent->children, struct window, entry )
{
if (ptr == win) break;
if (!(ptr->style & WS_VISIBLE)) continue;
if (ptr->ex_style & WS_EX_TRANSPARENT) continue;
if (!intersect_rect( &tmp, &ptr->visible_rect, &req->rect )) continue;
if (ptr->win_region && !rect_in_region( ptr->win_region, &req->rect )) continue;
/* found a window obscuring the rectangle, now move win above this one */
list_remove( &win->entry );
list_add_before( &ptr->entry, &win->entry );
break;
}
}
/* mark parts of a window as needing a redraw */ /* mark parts of a window as needing a redraw */
DECL_HANDLER(redraw_window) DECL_HANDLER(redraw_window)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment