Commit bc75f2f6 authored by Alexandre Julliard's avatar Alexandre Julliard

Return the coordinates information needed to setup the DC parameters

in the get_visible_region request instead of requiring the client to compute it again.
parent 7c342b4c
...@@ -86,21 +86,33 @@ static void dump_cache(void) ...@@ -86,21 +86,33 @@ static void dump_cache(void)
/*********************************************************************** /***********************************************************************
* get_server_visible_region * update_visible_region
*
* Set the visible region and X11 drawable for the DC associated to
* a given window.
*/ */
static HRGN get_server_visible_region( HWND hwnd, UINT flags ) static void update_visible_region( struct dce *dce )
{ {
RGNDATA *data;
NTSTATUS status; NTSTATUS status;
HRGN ret = 0; HRGN vis_rgn = 0;
HWND top = 0;
struct x11drv_escape_set_drawable escape;
struct x11drv_win_data *data;
DWORD flags = dce->flags;
size_t size = 256; size_t size = 256;
/* don't clip siblings if using parent clip region */
if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS;
/* fetch the visible region from the server */
do do
{ {
if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) + size - 1 ))) return 0; RGNDATA *data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) + size - 1 );
if (!data) return;
SERVER_START_REQ( get_visible_region ) SERVER_START_REQ( get_visible_region )
{ {
req->window = hwnd; req->window = dce->hwnd;
req->flags = flags; req->flags = flags;
wine_server_set_reply( req, data->Buffer, size ); wine_server_set_reply( req, data->Buffer, size );
if (!(status = wine_server_call( req ))) if (!(status = wine_server_call( req )))
...@@ -110,7 +122,13 @@ static HRGN get_server_visible_region( HWND hwnd, UINT flags ) ...@@ -110,7 +122,13 @@ static HRGN get_server_visible_region( HWND hwnd, UINT flags )
data->rdh.iType = RDH_RECTANGLES; data->rdh.iType = RDH_RECTANGLES;
data->rdh.nCount = reply_size / sizeof(RECT); data->rdh.nCount = reply_size / sizeof(RECT);
data->rdh.nRgnSize = reply_size; data->rdh.nRgnSize = reply_size;
ret = ExtCreateRegion( NULL, size, data ); vis_rgn = ExtCreateRegion( NULL, size, data );
top = reply->top_win;
escape.org.x = reply->win_org_x - reply->top_org_x;
escape.org.y = reply->win_org_y - reply->top_org_y;
escape.drawable_org.x = reply->top_org_x;
escape.drawable_org.y = reply->top_org_y;
} }
else size = reply->total_size; else size = reply->total_size;
} }
...@@ -118,119 +136,27 @@ static HRGN get_server_visible_region( HWND hwnd, UINT flags ) ...@@ -118,119 +136,27 @@ static HRGN get_server_visible_region( HWND hwnd, UINT flags )
HeapFree( GetProcessHeap(), 0, data ); HeapFree( GetProcessHeap(), 0, data );
} while (status == STATUS_BUFFER_OVERFLOW); } while (status == STATUS_BUFFER_OVERFLOW);
if (status) SetLastError( RtlNtStatusToDosError(status) ); if (status || !vis_rgn) return;
return ret;
}
if (dce->clip_rgn) CombineRgn( vis_rgn, vis_rgn, dce->clip_rgn,
(flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
/*********************************************************************** if (top == dce->hwnd && ((data = X11DRV_get_win_data( dce->hwnd )) != NULL) &&
* get_top_clipping_window IsIconic( dce->hwnd ) && data->icon_window)
* escape.drawable = data->icon_window;
* Get the top window to clip against (i.e. the top parent that has
* an associated X window).
*/
static HWND get_top_clipping_window( HWND hwnd )
{
HWND ret = GetAncestor( hwnd, GA_ROOT );
if (!ret) ret = GetDesktopWindow();
return ret;
}
/***********************************************************************
* set_drawable
*
* Set the drawable, origin and dimensions for the DC associated to
* a given window.
*/
static void set_drawable( struct dce *dce, BOOL update_visrgn )
{
HWND top = get_top_clipping_window( dce->hwnd );
struct x11drv_escape_set_drawable escape;
struct x11drv_win_data *data;
DWORD flags = dce->flags;
escape.mode = IncludeInferiors;
/* don't clip siblings if using parent clip region */
if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS;
if (top != dce->hwnd || !(data = X11DRV_get_win_data( dce->hwnd )))
{
POINT client_offset;
if (flags & DCX_WINDOW)
{
RECT rect;
GetWindowRect( dce->hwnd, &rect );
escape.org.x = rect.left;
escape.org.y = rect.top;
MapWindowPoints( 0, top, &escape.org, 1 );
escape.drawable_org.x = rect.left - escape.org.x;
escape.drawable_org.y = rect.top - escape.org.y;
}
else
{
escape.org.x = escape.org.y = 0;
escape.drawable_org.x = escape.drawable_org.y = 0;
MapWindowPoints( dce->hwnd, top, &escape.org, 1 );
MapWindowPoints( top, 0, &escape.drawable_org, 1 );
}
/* now make origins relative to the X window and not the client area */
client_offset = X11DRV_get_client_area_offset( top );
escape.org.x += client_offset.x;
escape.org.y += client_offset.y;
escape.drawable_org.x -= client_offset.x;
escape.drawable_org.y -= client_offset.y;
escape.drawable = X11DRV_get_whole_window( top );
}
else else
{ escape.drawable = X11DRV_get_whole_window( top );
if (IsIconic( dce->hwnd ))
{
escape.drawable = data->icon_window ? data->icon_window : data->whole_window;
escape.org.x = 0;
escape.org.y = 0;
escape.drawable_org = escape.org;
MapWindowPoints( dce->hwnd, 0, &escape.drawable_org, 1 );
}
else
{
escape.drawable = data->whole_window;
escape.drawable_org.x = data->whole_rect.left;
escape.drawable_org.y = data->whole_rect.top;
if (flags & DCX_WINDOW)
{
escape.org.x = data->window_rect.left - data->whole_rect.left;
escape.org.y = data->window_rect.top - data->whole_rect.top;
}
else
{
escape.org.x = data->client_rect.left;
escape.org.y = data->client_rect.top;
}
}
}
escape.code = X11DRV_SET_DRAWABLE; escape.code = X11DRV_SET_DRAWABLE;
escape.mode = IncludeInferiors;
ExtEscape( dce->hdc, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); ExtEscape( dce->hdc, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL );
if (update_visrgn) /* map region to DC coordinates */
{ OffsetRgn( vis_rgn,
/* need to recompute the visible region */ -(escape.drawable_org.x + escape.org.x),
HRGN visRgn = get_server_visible_region( dce->hwnd, flags ); -(escape.drawable_org.y + escape.org.y) );
SelectVisRgn16( HDC_16(dce->hdc), HRGN_16(vis_rgn) );
if (dce->clip_rgn) DeleteObject( vis_rgn );
CombineRgn( visRgn, visRgn, dce->clip_rgn,
(flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
/* map region to DC coordinates */
OffsetRgn( visRgn, -(escape.org.x + escape.drawable_org.x),
-(escape.org.y + escape.drawable_org.y) );
SelectVisRgn16( HDC_16(dce->hdc), HRGN_16(visRgn) );
DeleteObject( visRgn );
}
} }
...@@ -619,7 +545,7 @@ HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -619,7 +545,7 @@ HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
if (SetHookFlags16( HDC_16(dce->hdc), DCHF_VALIDATEVISRGN )) if (SetHookFlags16( HDC_16(dce->hdc), DCHF_VALIDATEVISRGN ))
bUpdateVisRgn = TRUE; /* DC was dirty */ bUpdateVisRgn = TRUE; /* DC was dirty */
set_drawable( dce, bUpdateVisRgn ); if (bUpdateVisRgn) update_visible_region( dce );
if (!(flags & DCX_NORESETATTRS)) if (!(flags & DCX_NORESETATTRS))
{ {
...@@ -678,7 +604,7 @@ static BOOL16 CALLBACK dc_hook( HDC16 hDC, WORD code, DWORD data, LPARAM lParam ...@@ -678,7 +604,7 @@ static BOOL16 CALLBACK dc_hook( HDC16 hDC, WORD code, DWORD data, LPARAM lParam
* DC is dirty (usually after SetHookFlags()). This * DC is dirty (usually after SetHookFlags()). This
* means that we have to recompute the visible region. * means that we have to recompute the visible region.
*/ */
if (dce->count) set_drawable( dce, TRUE ); if (dce->count) update_visible_region( dce );
else /* non-fatal but shouldn't happen */ else /* non-fatal but shouldn't happen */
WARN("DC is not in use!\n"); WARN("DC is not in use!\n");
break; break;
......
...@@ -2675,6 +2675,11 @@ struct get_visible_region_request ...@@ -2675,6 +2675,11 @@ struct get_visible_region_request
struct get_visible_region_reply struct get_visible_region_reply
{ {
struct reply_header __header; struct reply_header __header;
user_handle_t top_win;
int top_org_x;
int top_org_y;
int win_org_x;
int win_org_y;
size_t total_size; size_t total_size;
/* VARARG(region,rectangles); */ /* VARARG(region,rectangles); */
}; };
...@@ -3872,6 +3877,6 @@ union generic_reply ...@@ -3872,6 +3877,6 @@ union generic_reply
struct set_mailslot_info_reply set_mailslot_info_reply; struct set_mailslot_info_reply set_mailslot_info_reply;
}; };
#define SERVER_PROTOCOL_VERSION 165 #define SERVER_PROTOCOL_VERSION 166
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -1882,8 +1882,13 @@ enum message_type ...@@ -1882,8 +1882,13 @@ enum message_type
user_handle_t window; /* handle to the window */ user_handle_t window; /* handle to the window */
unsigned int flags; /* DCX flags */ unsigned int flags; /* DCX flags */
@REPLY @REPLY
user_handle_t top_win; /* top window to clip against */
int top_org_x; /* top window visible rect origin in screen coords */
int top_org_y;
int win_org_x; /* window rect origin in screen coords */
int win_org_y;
size_t total_size; /* total size of the resulting region */ size_t total_size; /* total size of the resulting region */
VARARG(region,rectangles); /* list of rectangles for the region */ VARARG(region,rectangles); /* list of rectangles for the region (in screen coords) */
@END @END
......
...@@ -2268,6 +2268,11 @@ static void dump_get_visible_region_request( const struct get_visible_region_req ...@@ -2268,6 +2268,11 @@ static void dump_get_visible_region_request( const struct get_visible_region_req
static void dump_get_visible_region_reply( const struct get_visible_region_reply *req ) static void dump_get_visible_region_reply( const struct get_visible_region_reply *req )
{ {
fprintf( stderr, " top_win=%p,", req->top_win );
fprintf( stderr, " top_org_x=%d,", req->top_org_x );
fprintf( stderr, " top_org_y=%d,", req->top_org_y );
fprintf( stderr, " win_org_x=%d,", req->win_org_x );
fprintf( stderr, " win_org_y=%d,", req->win_org_y );
fprintf( stderr, " total_size=%d,", req->total_size ); fprintf( stderr, " total_size=%d,", req->total_size );
fprintf( stderr, " region=" ); fprintf( stderr, " region=" );
dump_varargs_rectangles( cur_size ); dump_varargs_rectangles( cur_size );
......
...@@ -633,17 +633,22 @@ static struct region *intersect_window_region( struct region *region, struct win ...@@ -633,17 +633,22 @@ static struct region *intersect_window_region( struct region *region, struct win
} }
/* convert coordinates from client to screen coords */
static inline void client_to_screen( struct window *win, int *x, int *y )
{
for ( ; win; win = win->parent)
{
*x += win->client_rect.left;
*y += win->client_rect.top;
}
}
/* map the region from window to screen coordinates */ /* map the region from window to screen coordinates */
static inline void map_win_region_to_screen( struct window *win, struct region *region ) static inline void map_win_region_to_screen( struct window *win, struct region *region )
{ {
int x = win->window_rect.left; int x = win->window_rect.left;
int y = win->window_rect.top; int y = win->window_rect.top;
client_to_screen( win->parent, &x, &y );
for (win = win->parent; win; win = win->parent)
{
x += win->client_rect.left;
y += win->client_rect.top;
}
offset_region( region, x, y ); offset_region( region, x, y );
} }
...@@ -706,11 +711,10 @@ static inline struct window *get_top_clipping_window( struct window *win ) ...@@ -706,11 +711,10 @@ static inline struct window *get_top_clipping_window( struct window *win )
/* compute the visible region of a window, in window coordinates */ /* compute the visible region of a window, in window coordinates */
static struct region *get_visible_region( struct window *win, unsigned int flags ) static struct region *get_visible_region( struct window *win, struct window *top, unsigned int flags )
{ {
struct region *tmp, *region; struct region *tmp, *region;
int offset_x, offset_y; int offset_x, offset_y;
struct window *top = get_top_clipping_window( win );
if (!(region = create_empty_region())) return NULL; if (!(region = create_empty_region())) return NULL;
...@@ -1069,11 +1073,10 @@ static unsigned int get_child_update_flags( struct window *win, unsigned int fla ...@@ -1069,11 +1073,10 @@ static unsigned int get_child_update_flags( struct window *win, unsigned int fla
/* expose a region of a window, looking for the top most parent that needs to be exposed */ /* expose a region of a window, looking for the top most parent that needs to be exposed */
/* the region is in window coordinates */ /* the region is in window coordinates */
static void expose_window( struct window *win, struct region *region ) static void expose_window( struct window *win, struct window *top, struct region *region )
{ {
struct window *parent, *ptr; struct window *parent, *ptr;
int offset_x, offset_y; int offset_x, offset_y;
struct window *top = get_top_clipping_window( win );
/* find the top most parent that doesn't clip either siblings or children */ /* find the top most parent that doesn't clip either siblings or children */
for (parent = ptr = win; ptr != top; ptr = ptr->parent) for (parent = ptr = win; ptr != top; ptr = ptr->parent)
...@@ -1107,11 +1110,12 @@ static void set_window_pos( struct window *win, struct window *previous, ...@@ -1107,11 +1110,12 @@ static void set_window_pos( struct window *win, struct window *previous,
const rectangle_t old_window_rect = win->window_rect; const rectangle_t old_window_rect = win->window_rect;
const rectangle_t old_visible_rect = win->visible_rect; const rectangle_t old_visible_rect = win->visible_rect;
const rectangle_t old_client_rect = win->client_rect; const rectangle_t old_client_rect = win->client_rect;
struct window *top = get_top_clipping_window( win );
int visible = (win->style & WS_VISIBLE) || (swp_flags & SWP_SHOWWINDOW); int visible = (win->style & WS_VISIBLE) || (swp_flags & SWP_SHOWWINDOW);
if (win->parent && !is_visible( win->parent )) visible = 0; if (win->parent && !is_visible( win->parent )) visible = 0;
if (visible && !(old_vis_rgn = get_visible_region( win, DCX_WINDOW ))) return; if (visible && !(old_vis_rgn = get_visible_region( win, top, DCX_WINDOW ))) return;
/* set the new window info before invalidating anything */ /* set the new window info before invalidating anything */
...@@ -1130,7 +1134,7 @@ static void set_window_pos( struct window *win, struct window *previous, ...@@ -1130,7 +1134,7 @@ static void set_window_pos( struct window *win, struct window *previous,
/* if the window is not visible, everything is easy */ /* if the window is not visible, everything is easy */
if (!visible) return; if (!visible) return;
if (!(new_vis_rgn = get_visible_region( win, DCX_WINDOW ))) if (!(new_vis_rgn = get_visible_region( win, top, DCX_WINDOW )))
{ {
free_region( old_vis_rgn ); free_region( old_vis_rgn );
clear_error(); /* ignore error since the window info has been modified already */ clear_error(); /* ignore error since the window info has been modified already */
...@@ -1144,7 +1148,7 @@ static void set_window_pos( struct window *win, struct window *previous, ...@@ -1144,7 +1148,7 @@ static void set_window_pos( struct window *win, struct window *previous,
offset_region( old_vis_rgn, old_window_rect.left - window_rect->left, offset_region( old_vis_rgn, old_window_rect.left - window_rect->left,
old_window_rect.top - window_rect->top ); old_window_rect.top - window_rect->top );
if (xor_region( new_vis_rgn, old_vis_rgn, new_vis_rgn )) if (xor_region( new_vis_rgn, old_vis_rgn, new_vis_rgn ))
expose_window( win, new_vis_rgn ); expose_window( win, top, new_vis_rgn );
} }
free_region( old_vis_rgn ); free_region( old_vis_rgn );
...@@ -1580,17 +1584,25 @@ DECL_HANDLER(get_windows_offset) ...@@ -1580,17 +1584,25 @@ DECL_HANDLER(get_windows_offset)
DECL_HANDLER(get_visible_region) DECL_HANDLER(get_visible_region)
{ {
struct region *region; struct region *region;
struct window *win = get_window( req->window ); struct window *top, *win = get_window( req->window );
if (!win) return; if (!win) return;
if ((region = get_visible_region( win, req->flags ))) top = get_top_clipping_window( win );
if ((region = get_visible_region( win, top, req->flags )))
{ {
rectangle_t *data; rectangle_t *data;
map_win_region_to_screen( win, region ); map_win_region_to_screen( win, region );
data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size ); data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size );
if (data) set_reply_data_ptr( data, reply->total_size ); if (data) set_reply_data_ptr( data, reply->total_size );
} }
reply->top_win = top->handle;
reply->top_org_x = top->visible_rect.left;
reply->top_org_y = top->visible_rect.top;
reply->win_org_x = (req->flags & DCX_WINDOW) ? win->window_rect.left : win->client_rect.left;
reply->win_org_y = (req->flags & DCX_WINDOW) ? win->window_rect.top : win->client_rect.top;
client_to_screen( top->parent, &reply->top_org_x, &reply->top_org_y );
client_to_screen( win->parent, &reply->win_org_x, &reply->win_org_y );
} }
......
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