Commit 618a7e58 authored by Alexandre Julliard's avatar Alexandre Julliard

Added support for window regions in the server.

parent 7e168ee7
...@@ -1657,20 +1657,6 @@ int X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) ...@@ -1657,20 +1657,6 @@ int X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
return FALSE; return FALSE;
} }
if (wndPtr->hrgnWnd == hrgn)
{
WIN_ReleasePtr( wndPtr );
return TRUE;
}
if (wndPtr->hrgnWnd)
{
/* delete previous region */
DeleteObject(wndPtr->hrgnWnd);
wndPtr->hrgnWnd = 0;
}
wndPtr->hrgnWnd = hrgn;
#ifdef HAVE_LIBXSHAPE #ifdef HAVE_LIBXSHAPE
{ {
Display *display = thread_display(); Display *display = thread_display();
...@@ -1706,7 +1692,6 @@ int X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) ...@@ -1706,7 +1692,6 @@ int X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
#endif /* HAVE_LIBXSHAPE */ #endif /* HAVE_LIBXSHAPE */
WIN_ReleasePtr( wndPtr ); WIN_ReleasePtr( wndPtr );
if (redraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE );
return TRUE; return TRUE;
} }
......
...@@ -2630,6 +2630,33 @@ struct get_visible_region_reply ...@@ -2630,6 +2630,33 @@ struct get_visible_region_reply
struct get_window_region_request
{
struct request_header __header;
user_handle_t window;
};
struct get_window_region_reply
{
struct reply_header __header;
size_t total_size;
/* VARARG(region,rectangles); */
};
struct set_window_region_request
{
struct request_header __header;
user_handle_t window;
/* VARARG(region,rectangles); */
};
struct set_window_region_reply
{
struct reply_header __header;
};
struct set_window_property_request struct set_window_property_request
{ {
struct request_header __header; struct request_header __header;
...@@ -3206,6 +3233,8 @@ enum request ...@@ -3206,6 +3233,8 @@ enum request
REQ_inc_window_paint_count, REQ_inc_window_paint_count,
REQ_get_windows_offset, REQ_get_windows_offset,
REQ_get_visible_region, REQ_get_visible_region,
REQ_get_window_region,
REQ_set_window_region,
REQ_set_window_property, REQ_set_window_property,
REQ_remove_window_property, REQ_remove_window_property,
REQ_get_window_property, REQ_get_window_property,
...@@ -3387,6 +3416,8 @@ union generic_request ...@@ -3387,6 +3416,8 @@ union generic_request
struct inc_window_paint_count_request inc_window_paint_count_request; struct inc_window_paint_count_request inc_window_paint_count_request;
struct get_windows_offset_request get_windows_offset_request; struct get_windows_offset_request get_windows_offset_request;
struct get_visible_region_request get_visible_region_request; struct get_visible_region_request get_visible_region_request;
struct get_window_region_request get_window_region_request;
struct set_window_region_request set_window_region_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;
struct get_window_property_request get_window_property_request; struct get_window_property_request get_window_property_request;
...@@ -3566,6 +3597,8 @@ union generic_reply ...@@ -3566,6 +3597,8 @@ union generic_reply
struct inc_window_paint_count_reply inc_window_paint_count_reply; struct inc_window_paint_count_reply inc_window_paint_count_reply;
struct get_windows_offset_reply get_windows_offset_reply; struct get_windows_offset_reply get_windows_offset_reply;
struct get_visible_region_reply get_visible_region_reply; struct get_visible_region_reply get_visible_region_reply;
struct get_window_region_reply get_window_region_reply;
struct set_window_region_reply set_window_region_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;
struct get_window_property_reply get_window_property_reply; struct get_window_property_reply get_window_property_reply;
...@@ -3593,6 +3626,6 @@ union generic_reply ...@@ -3593,6 +3626,6 @@ union generic_reply
struct set_global_windows_reply set_global_windows_reply; struct set_global_windows_reply set_global_windows_reply;
}; };
#define SERVER_PROTOCOL_VERSION 144 #define SERVER_PROTOCOL_VERSION 145
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -1849,6 +1849,22 @@ enum message_type ...@@ -1849,6 +1849,22 @@ enum message_type
@END @END
/* Get the window region */
@REQ(get_window_region)
user_handle_t window; /* handle to the window */
@REPLY
size_t total_size; /* total size of the resulting region */
VARARG(region,rectangles); /* list of rectangles for the region */
@END
/* Set the window region */
@REQ(set_window_region)
user_handle_t window; /* handle to the window */
VARARG(region,rectangles); /* list of rectangles for the region */
@END
/* Set a window property */ /* Set a window property */
@REQ(set_window_property) @REQ(set_window_property)
user_handle_t window; /* handle to the window */ user_handle_t window; /* handle to the window */
......
...@@ -99,6 +99,8 @@ typedef int (*overlap_func_t)( struct region *reg, const rectangle_t *r1, const ...@@ -99,6 +99,8 @@ typedef int (*overlap_func_t)( struct region *reg, const rectangle_t *r1, const
typedef int (*non_overlap_func_t)( struct region *reg, const rectangle_t *r, typedef int (*non_overlap_func_t)( struct region *reg, const rectangle_t *r,
const rectangle_t *rEnd, int top, int bottom ); const rectangle_t *rEnd, int top, int bottom );
static const rectangle_t empty_rect; /* all-zero rectangle for empty regions */
/* add a rectangle to a region */ /* add a rectangle to a region */
static inline rectangle_t *add_rect( struct region *reg ) static inline rectangle_t *add_rect( struct region *reg )
{ {
...@@ -578,6 +580,16 @@ struct region *create_region( const rectangle_t *rects, unsigned int nb_rects ) ...@@ -578,6 +580,16 @@ struct region *create_region( const rectangle_t *rects, unsigned int nb_rects )
return region; return region;
} }
/* create a region from request data */
struct region *create_region_from_req_data( const void *data, size_t size )
{
const rectangle_t *rects = data;
int nb_rects = size / sizeof(rectangle_t);
/* special case: empty region can be specified by a single all-zero rectangle */
if (nb_rects == 1 && !memcmp( rects, &empty_rect, sizeof(empty_rect) )) nb_rects = 0;
return create_region( rects, nb_rects );
}
/* free a region */ /* free a region */
void free_region( struct region *region ) void free_region( struct region *region )
...@@ -607,7 +619,12 @@ void set_region_rect( struct region *region, const rectangle_t *rect ) ...@@ -607,7 +619,12 @@ void set_region_rect( struct region *region, const rectangle_t *rect )
/* retrieve the region data for sending to the client */ /* retrieve the region data for sending to the client */
rectangle_t *get_region_data( const struct region *region, size_t *total_size ) rectangle_t *get_region_data( const struct region *region, size_t *total_size )
{ {
*total_size = region->num_rects * sizeof(rectangle_t); if (!(*total_size = region->num_rects * sizeof(rectangle_t)))
{
/* return a single empty rect for empty regions */
*total_size = sizeof(empty_rect);
return memdup( &empty_rect, sizeof(empty_rect) );
}
return memdup( region->rects, *total_size ); return memdup( region->rects, *total_size );
} }
...@@ -615,7 +632,13 @@ rectangle_t *get_region_data( const struct region *region, size_t *total_size ) ...@@ -615,7 +632,13 @@ rectangle_t *get_region_data( const struct region *region, size_t *total_size )
rectangle_t *get_region_data_and_free( struct region *region, size_t *total_size ) rectangle_t *get_region_data_and_free( struct region *region, size_t *total_size )
{ {
rectangle_t *ret = region->rects; rectangle_t *ret = region->rects;
*total_size = region->num_rects * sizeof(rectangle_t);
if (!(*total_size = region->num_rects * sizeof(rectangle_t)))
{
/* return a single empty rect for empty regions */
*total_size = sizeof(empty_rect);
ret = memdup( &empty_rect, sizeof(empty_rect) );
}
free( region ); free( region );
return ret; return ret;
} }
......
...@@ -252,6 +252,8 @@ DECL_HANDLER(set_window_text); ...@@ -252,6 +252,8 @@ DECL_HANDLER(set_window_text);
DECL_HANDLER(inc_window_paint_count); DECL_HANDLER(inc_window_paint_count);
DECL_HANDLER(get_windows_offset); DECL_HANDLER(get_windows_offset);
DECL_HANDLER(get_visible_region); DECL_HANDLER(get_visible_region);
DECL_HANDLER(get_window_region);
DECL_HANDLER(set_window_region);
DECL_HANDLER(set_window_property); DECL_HANDLER(set_window_property);
DECL_HANDLER(remove_window_property); DECL_HANDLER(remove_window_property);
DECL_HANDLER(get_window_property); DECL_HANDLER(get_window_property);
...@@ -432,6 +434,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = ...@@ -432,6 +434,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_inc_window_paint_count, (req_handler)req_inc_window_paint_count,
(req_handler)req_get_windows_offset, (req_handler)req_get_windows_offset,
(req_handler)req_get_visible_region, (req_handler)req_get_visible_region,
(req_handler)req_get_window_region,
(req_handler)req_set_window_region,
(req_handler)req_set_window_property, (req_handler)req_set_window_property,
(req_handler)req_remove_window_property, (req_handler)req_remove_window_property,
(req_handler)req_get_window_property, (req_handler)req_get_window_property,
......
...@@ -2190,6 +2190,25 @@ static void dump_get_visible_region_reply( const struct get_visible_region_reply ...@@ -2190,6 +2190,25 @@ static void dump_get_visible_region_reply( const struct get_visible_region_reply
dump_varargs_rectangles( cur_size ); dump_varargs_rectangles( cur_size );
} }
static void dump_get_window_region_request( const struct get_window_region_request *req )
{
fprintf( stderr, " window=%p", req->window );
}
static void dump_get_window_region_reply( const struct get_window_region_reply *req )
{
fprintf( stderr, " total_size=%d,", req->total_size );
fprintf( stderr, " region=" );
dump_varargs_rectangles( cur_size );
}
static void dump_set_window_region_request( const struct set_window_region_request *req )
{
fprintf( stderr, " window=%p,", req->window );
fprintf( stderr, " region=" );
dump_varargs_rectangles( cur_size );
}
static void dump_set_window_property_request( const struct set_window_property_request *req ) static void dump_set_window_property_request( const struct set_window_property_request *req )
{ {
fprintf( stderr, " window=%p,", req->window ); fprintf( stderr, " window=%p,", req->window );
...@@ -2660,6 +2679,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { ...@@ -2660,6 +2679,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_inc_window_paint_count_request, (dump_func)dump_inc_window_paint_count_request,
(dump_func)dump_get_windows_offset_request, (dump_func)dump_get_windows_offset_request,
(dump_func)dump_get_visible_region_request, (dump_func)dump_get_visible_region_request,
(dump_func)dump_get_window_region_request,
(dump_func)dump_set_window_region_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,
(dump_func)dump_get_window_property_request, (dump_func)dump_get_window_property_request,
...@@ -2837,6 +2858,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -2837,6 +2858,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)0, (dump_func)0,
(dump_func)dump_get_windows_offset_reply, (dump_func)dump_get_windows_offset_reply,
(dump_func)dump_get_visible_region_reply, (dump_func)dump_get_visible_region_reply,
(dump_func)dump_get_window_region_reply,
(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,
...@@ -3014,6 +3037,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = { ...@@ -3014,6 +3037,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"inc_window_paint_count", "inc_window_paint_count",
"get_windows_offset", "get_windows_offset",
"get_visible_region", "get_visible_region",
"get_window_region",
"set_window_region",
"set_window_property", "set_window_property",
"remove_window_property", "remove_window_property",
"get_window_property", "get_window_property",
......
...@@ -68,6 +68,7 @@ extern void post_message( user_handle_t win, unsigned int message, ...@@ -68,6 +68,7 @@ extern void post_message( user_handle_t win, unsigned int message,
/* region functions */ /* region functions */
extern struct region *create_region( const rectangle_t *rects, unsigned int nb_rects ); extern struct region *create_region( const rectangle_t *rects, unsigned int nb_rects );
extern struct region *create_region_from_req_data( const void *data, size_t size );
extern void free_region( struct region *region ); extern void free_region( struct region *region );
extern void set_region_rect( struct region *region, const rectangle_t *rect ); extern void set_region_rect( struct region *region, const rectangle_t *rect );
extern rectangle_t *get_region_data( const struct region *region, size_t *total_size ); extern rectangle_t *get_region_data( const struct region *region, size_t *total_size );
......
...@@ -68,6 +68,7 @@ struct window ...@@ -68,6 +68,7 @@ struct window
user_handle_t last_active; /* last active popup */ user_handle_t last_active; /* last active popup */
rectangle_t window_rect; /* window rectangle */ rectangle_t window_rect; /* window rectangle */
rectangle_t client_rect; /* client rectangle */ rectangle_t client_rect; /* client rectangle */
struct region *win_region; /* window region (for shaped windows) */
unsigned int style; /* window style */ unsigned int style; /* window style */
unsigned int ex_style; /* window extended style */ unsigned int ex_style; /* window extended style */
unsigned int id; /* window id */ unsigned int id; /* window id */
...@@ -261,6 +262,7 @@ static void destroy_window( struct window *win ) ...@@ -261,6 +262,7 @@ static void destroy_window( struct window *win )
free_user_handle( win->handle ); free_user_handle( win->handle );
destroy_properties( win ); destroy_properties( win );
unlink_window( win ); unlink_window( win );
if (win->win_region) free_region( win->win_region );
release_class( win->class ); release_class( win->class );
if (win->text) free( win->text ); if (win->text) free( win->text );
memset( win, 0x55, sizeof(*win) ); memset( win, 0x55, sizeof(*win) );
...@@ -299,6 +301,7 @@ static struct window *create_window( struct window *parent, struct window *owner ...@@ -299,6 +301,7 @@ static struct window *create_window( struct window *parent, struct window *owner
win->class = class; win->class = class;
win->atom = atom; win->atom = atom;
win->last_active = win->handle; win->last_active = win->handle;
win->win_region = NULL;
win->style = 0; win->style = 0;
win->ex_style = 0; win->ex_style = 0;
win->id = 0; win->id = 0;
...@@ -463,6 +466,18 @@ user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *threa ...@@ -463,6 +466,18 @@ user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *threa
} }
/* intersect the window region with the specified region, relative to the window parent */
static struct region *intersect_window_region( struct region *region, struct window *win )
{
/* make region relative to window rect */
offset_region( region, -win->window_rect.left, -win->window_rect.top );
if (!intersect_region( region, region, win->win_region )) return NULL;
/* make region relative to parent again */
offset_region( region, win->window_rect.left, win->window_rect.top );
return region;
}
/* clip all children of a given window out of the visible region */ /* clip all children of a given window out of the visible region */
static struct region *clip_children( struct window *parent, struct window *last, static struct region *clip_children( struct window *parent, struct window *last,
struct region *region, int offset_x, int offset_y ) struct region *region, int offset_x, int offset_y )
...@@ -476,6 +491,11 @@ static struct region *clip_children( struct window *parent, struct window *last, ...@@ -476,6 +491,11 @@ static struct region *clip_children( struct window *parent, struct window *last,
if (!(ptr->style & WS_VISIBLE)) continue; if (!(ptr->style & WS_VISIBLE)) continue;
if (ptr->ex_style & WS_EX_TRANSPARENT) continue; if (ptr->ex_style & WS_EX_TRANSPARENT) continue;
set_region_rect( tmp, &ptr->window_rect ); set_region_rect( tmp, &ptr->window_rect );
if (ptr->win_region && !intersect_window_region( tmp, ptr ))
{
free_region( tmp );
return NULL;
}
offset_region( tmp, offset_x, offset_y ); offset_region( tmp, offset_x, offset_y );
if (!(region = subtract_region( region, region, tmp ))) break; if (!(region = subtract_region( region, region, tmp ))) break;
if (is_region_empty( region )) break; if (is_region_empty( region )) break;
...@@ -491,7 +511,6 @@ static struct region *get_visible_region( struct window *win, struct window *top ...@@ -491,7 +511,6 @@ static struct region *get_visible_region( struct window *win, struct window *top
{ {
struct region *tmp, *region; struct region *tmp, *region;
struct window *ptr; struct window *ptr;
rectangle_t rect;
int offset_x, offset_y; int offset_x, offset_y;
if (!(region = create_empty_region())) return NULL; if (!(region = create_empty_region())) return NULL;
...@@ -501,32 +520,32 @@ static struct region *get_visible_region( struct window *win, struct window *top ...@@ -501,32 +520,32 @@ static struct region *get_visible_region( struct window *win, struct window *top
for (ptr = win; ptr != top_window; ptr = ptr->parent) for (ptr = win; ptr != top_window; ptr = ptr->parent)
if (!(ptr->style & WS_VISIBLE)) return region; /* empty region */ if (!(ptr->style & WS_VISIBLE)) return region; /* empty region */
/* retrieve window rectangle in parent coordinates */ /* create a region relative to the window itself */
if ((flags & DCX_PARENTCLIP) && win->parent) if ((flags & DCX_PARENTCLIP) && win->parent)
{ {
rectangle_t rect;
rect.left = rect.top = 0; rect.left = rect.top = 0;
rect.right = win->parent->client_rect.right - win->parent->client_rect.left; rect.right = win->parent->client_rect.right - win->parent->client_rect.left;
rect.bottom = win->parent->client_rect.bottom - win->parent->client_rect.top; rect.bottom = win->parent->client_rect.bottom - win->parent->client_rect.top;
set_region_rect( region, &rect );
offset_x = win->client_rect.left; offset_x = win->client_rect.left;
offset_y = win->client_rect.top; offset_y = win->client_rect.top;
} }
else if (flags & DCX_WINDOW) else if (flags & DCX_WINDOW)
{ {
rect = win->window_rect; set_region_rect( region, &win->window_rect );
if (win->win_region && !intersect_window_region( region, win )) goto error;
offset_x = win->window_rect.left; offset_x = win->window_rect.left;
offset_y = win->window_rect.top; offset_y = win->window_rect.top;
} }
else else
{ {
rect = win->client_rect; set_region_rect( region, &win->client_rect );
if (win->win_region && !intersect_window_region( region, win )) goto error;
offset_x = win->client_rect.left; offset_x = win->client_rect.left;
offset_y = win->client_rect.top; offset_y = win->client_rect.top;
} }
/* create a region relative to the window itself */
set_region_rect( region, &rect );
offset_region( region, -offset_x, -offset_y ); offset_region( region, -offset_x, -offset_y );
/* clip children */ /* clip children */
...@@ -557,7 +576,16 @@ static struct region *get_visible_region( struct window *win, struct window *top ...@@ -557,7 +576,16 @@ static struct region *get_visible_region( struct window *win, struct window *top
offset_y += win->client_rect.top; offset_y += win->client_rect.top;
offset_region( region, win->client_rect.left, win->client_rect.top ); offset_region( region, win->client_rect.left, win->client_rect.top );
set_region_rect( tmp, &win->client_rect ); set_region_rect( tmp, &win->client_rect );
if (!intersect_region( region, region, tmp )) goto error; if (win->win_region && !intersect_window_region( tmp, win ))
{
free_region( tmp );
goto error;
}
if (!intersect_region( region, region, tmp ))
{
free_region( tmp );
goto error;
}
if (is_region_empty( region )) break; if (is_region_empty( region )) break;
} }
offset_region( region, -offset_x, -offset_y ); /* make it relative to target window again */ offset_region( region, -offset_x, -offset_y ); /* make it relative to target window again */
...@@ -951,6 +979,40 @@ DECL_HANDLER(get_visible_region) ...@@ -951,6 +979,40 @@ DECL_HANDLER(get_visible_region)
} }
/* get the window region */
DECL_HANDLER(get_window_region)
{
struct window *win = get_window( req->window );
if (!win) return;
reply->total_size = 0;
if (win->win_region)
{
rectangle_t *data = get_region_data( win->win_region, &reply->total_size );
set_reply_data_ptr( data, min( reply->total_size, get_reply_max_size() ) );
}
}
/* set the window region */
DECL_HANDLER(set_window_region)
{
struct region *region = NULL;
struct window *win = get_window( req->window );
if (!win) return;
if (get_req_data_size()) /* no data means remove the region completely */
{
if (!(region = create_region_from_req_data( get_req_data(), get_req_data_size() )))
return;
}
if (win->win_region) free_region( win->win_region );
win->win_region = region;
}
/* set a window property */ /* set a window property */
DECL_HANDLER(set_window_property) DECL_HANDLER(set_window_property)
{ {
......
...@@ -172,21 +172,51 @@ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) ...@@ -172,21 +172,51 @@ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn ) int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
{ {
int nRet = ERROR; int nRet = ERROR;
WND *wndPtr = WIN_GetPtr( hwnd ); HRGN win_rgn = 0;
RGNDATA *data;
size_t size = 256;
BOOL retry = FALSE;
if (wndPtr == WND_OTHER_PROCESS) do
{ {
if (IsWindow( hwnd )) if (!(data = HeapAlloc( GetProcessHeap(), 0, sizeof(*data) + size - 1 )))
FIXME( "not supported on other process window %p\n", hwnd );
wndPtr = NULL;
}
if (!wndPtr)
{ {
SetLastError( ERROR_INVALID_WINDOW_HANDLE ); SetLastError( ERROR_OUTOFMEMORY );
return ERROR; return ERROR;
} }
if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY ); SERVER_START_REQ( get_window_region )
WIN_ReleasePtr( wndPtr ); {
req->window = hwnd;
wine_server_set_reply( req, data->Buffer, size );
if (!wine_server_call_err( req ))
{
if (!reply->total_size) retry = FALSE; /* no region at all */
else if (reply->total_size <= size)
{
size_t reply_size = wine_server_reply_size( reply );
data->rdh.dwSize = sizeof(data->rdh);
data->rdh.iType = RDH_RECTANGLES;
data->rdh.nCount = reply_size / sizeof(RECT);
data->rdh.nRgnSize = reply_size;
win_rgn = ExtCreateRegion( NULL, size, data );
retry = FALSE;
}
else
{
size = reply->total_size;
retry = TRUE;
}
}
}
SERVER_END_REQ;
HeapFree( GetProcessHeap(), 0, data );
} while (retry);
if (win_rgn)
{
nRet = CombineRgn( hrgn, win_rgn, 0, RGN_COPY );
DeleteObject( win_rgn );
}
return nRet; return nRet;
} }
...@@ -196,21 +226,49 @@ int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn ) ...@@ -196,21 +226,49 @@ int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
*/ */
int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw ) int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
{ {
RECT rect; static const RECT empty_rect;
WND *wndPtr; WND *wndPtr;
BOOL ret;
if (hrgn)
{
RGNDATA *data;
DWORD size;
if (hrgn) /* verify that region really exists */ if (!(size = GetRegionData( hrgn, 0, NULL ))) return FALSE;
if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
if (!GetRegionData( hrgn, size, data ))
{
HeapFree( GetProcessHeap(), 0, data );
return FALSE;
}
SERVER_START_REQ( set_window_region )
{
req->window = hwnd;
if (data->rdh.nCount)
wine_server_add_data( req, data->Buffer, data->rdh.nCount * sizeof(RECT) );
else
wine_server_add_data( req, &empty_rect, sizeof(empty_rect) );
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
}
else /* clear existing region */
{
SERVER_START_REQ( set_window_region )
{ {
if (GetRgnBox( hrgn, &rect ) == ERROR) return FALSE; req->window = hwnd;
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
} }
if (USER_Driver.pSetWindowRgn) if (!ret) return FALSE;
return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS) if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS)
{ {
if (IsWindow( hwnd )) if (IsWindow( hwnd ))
FIXME( "not supported on other process window %p\n", hwnd ); FIXME( "not properly supported on other process window %p\n", hwnd );
wndPtr = NULL; wndPtr = NULL;
} }
if (!wndPtr) if (!wndPtr)
...@@ -224,7 +282,6 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw ) ...@@ -224,7 +282,6 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
WIN_ReleasePtr( wndPtr ); WIN_ReleasePtr( wndPtr );
return TRUE; return TRUE;
} }
if (wndPtr->hrgnWnd) if (wndPtr->hrgnWnd)
{ {
/* delete previous region */ /* delete previous region */
...@@ -234,12 +291,11 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw ) ...@@ -234,12 +291,11 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
wndPtr->hrgnWnd = hrgn; wndPtr->hrgnWnd = hrgn;
WIN_ReleasePtr( wndPtr ); WIN_ReleasePtr( wndPtr );
/* Size the window to the rectangle of the new region (if it isn't NULL) */ if (USER_Driver.pSetWindowRgn)
if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top, ret = USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE | if (ret && bRedraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE );
SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) ); return ret;
return TRUE;
} }
......
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