Put in place the basic infrastructure to allow supporting multiple
desktop windows.
This commit is contained in:
parent
87458a5ccf
commit
8c518808b8
|
@ -279,9 +279,6 @@ static BOOL process_attach(void)
|
|||
/* Initialize message spying */
|
||||
if (!SPY_Init()) return FALSE;
|
||||
|
||||
/* Create desktop window */
|
||||
if (!WIN_CreateDesktopWindow()) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -177,7 +177,8 @@ struct user_thread_info
|
|||
HCURSOR cursor; /* 20 Current cursor */
|
||||
INT cursor_count; /* 24 Cursor show count */
|
||||
UINT active_hooks; /* 28 Bitmap of active hooks */
|
||||
/* 2c-7c Available for more data */
|
||||
HWND desktop; /* 2c Desktop window */
|
||||
/* 30-7c Available for more data */
|
||||
};
|
||||
|
||||
static inline struct user_thread_info *get_user_thread_info(void)
|
||||
|
|
|
@ -47,9 +47,6 @@ WINE_DECLARE_DEBUG_CHANNEL(msg);
|
|||
|
||||
/**********************************************************************/
|
||||
|
||||
/* Desktop window */
|
||||
static HWND hwndDesktop;
|
||||
|
||||
static WORD wDragWidth = 4;
|
||||
static WORD wDragHeight= 3;
|
||||
|
||||
|
@ -313,7 +310,7 @@ WND *WIN_GetPtr( HWND hwnd )
|
|||
return ptr;
|
||||
ptr = NULL;
|
||||
}
|
||||
else if (index == USER_HANDLE_TO_INDEX(hwndDesktop))
|
||||
else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
|
||||
{
|
||||
if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
|
||||
else ptr = NULL;
|
||||
|
@ -606,34 +603,6 @@ void WIN_DestroyThreadWindows( HWND hwnd )
|
|||
HeapFree( GetProcessHeap(), 0, list );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WIN_CreateDesktopWindow
|
||||
*
|
||||
* Create the desktop window.
|
||||
*/
|
||||
BOOL WIN_CreateDesktopWindow(void)
|
||||
{
|
||||
TRACE("Creating desktop window\n");
|
||||
|
||||
SERVER_START_REQ( create_window )
|
||||
{
|
||||
req->parent = 0;
|
||||
req->owner = 0;
|
||||
req->atom = LOWORD(DESKTOP_CLASS_ATOM);
|
||||
req->instance = 0;
|
||||
if (!wine_server_call_err( req )) hwndDesktop = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (!hwndDesktop)
|
||||
{
|
||||
ERR( "error %ld creating desktop window\n", GetLastError() );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return USER_Driver.pCreateDesktopWindow( hwndDesktop );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WIN_FixCoordinates
|
||||
|
@ -1571,10 +1540,19 @@ HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
|
|||
*/
|
||||
HWND WINAPI GetDesktopWindow(void)
|
||||
{
|
||||
if (hwndDesktop) return hwndDesktop;
|
||||
ERR( "Wine init error: either you're trying to use an invalid native USER.EXE config, or some graphics/GUI libraries or DLLs didn't initialize properly. Aborting.\n" );
|
||||
ExitProcess(1);
|
||||
return 0;
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
|
||||
if (!thread_info->desktop)
|
||||
{
|
||||
SERVER_START_REQ( get_desktop_window )
|
||||
{
|
||||
if (!wine_server_call( req )) thread_info->desktop = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!thread_info->desktop || !USER_Driver.pCreateDesktopWindow( thread_info->desktop ))
|
||||
ERR( "failed to create desktop window\n" );
|
||||
}
|
||||
return thread_info->desktop;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "wine/server.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/debug.h"
|
||||
#include "user_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(winstation);
|
||||
|
||||
|
@ -359,6 +360,7 @@ BOOL WINAPI SetThreadDesktop( HDESK handle )
|
|||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret) get_user_thread_info()->desktop = 0; /* reset the desktop window */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,6 @@ extern ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits );
|
|||
extern BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient );
|
||||
extern LRESULT WIN_DestroyWindow( HWND hwnd );
|
||||
extern void WIN_DestroyThreadWindows( HWND hwnd );
|
||||
extern BOOL WIN_CreateDesktopWindow(void);
|
||||
extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL );
|
||||
extern HWND *WIN_ListChildren( HWND hwnd );
|
||||
extern void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id );
|
||||
|
|
|
@ -2503,6 +2503,18 @@ struct destroy_window_reply
|
|||
|
||||
|
||||
|
||||
struct get_desktop_window_request
|
||||
{
|
||||
struct request_header __header;
|
||||
};
|
||||
struct get_desktop_window_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
user_handle_t handle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct set_window_owner_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -3705,6 +3717,7 @@ enum request
|
|||
REQ_get_named_pipe_info,
|
||||
REQ_create_window,
|
||||
REQ_destroy_window,
|
||||
REQ_get_desktop_window,
|
||||
REQ_set_window_owner,
|
||||
REQ_get_window_info,
|
||||
REQ_set_window_info,
|
||||
|
@ -3916,6 +3929,7 @@ union generic_request
|
|||
struct get_named_pipe_info_request get_named_pipe_info_request;
|
||||
struct create_window_request create_window_request;
|
||||
struct destroy_window_request destroy_window_request;
|
||||
struct get_desktop_window_request get_desktop_window_request;
|
||||
struct set_window_owner_request set_window_owner_request;
|
||||
struct get_window_info_request get_window_info_request;
|
||||
struct set_window_info_request set_window_info_request;
|
||||
|
@ -4125,6 +4139,7 @@ union generic_reply
|
|||
struct get_named_pipe_info_reply get_named_pipe_info_reply;
|
||||
struct create_window_reply create_window_reply;
|
||||
struct destroy_window_reply destroy_window_reply;
|
||||
struct get_desktop_window_reply get_desktop_window_reply;
|
||||
struct set_window_owner_reply set_window_owner_reply;
|
||||
struct get_window_info_reply get_window_info_reply;
|
||||
struct set_window_info_reply set_window_info_reply;
|
||||
|
@ -4191,6 +4206,6 @@ union generic_reply
|
|||
struct set_mailslot_info_reply set_mailslot_info_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 180
|
||||
#define SERVER_PROTOCOL_VERSION 181
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -1769,6 +1769,13 @@ enum message_type
|
|||
@END
|
||||
|
||||
|
||||
/* Retrieve the desktop window for the current thread */
|
||||
@REQ(get_desktop_window)
|
||||
@REPLY
|
||||
user_handle_t handle; /* handle to the desktop window */
|
||||
@END
|
||||
|
||||
|
||||
/* Set a window owner */
|
||||
@REQ(set_window_owner)
|
||||
user_handle_t handle; /* handle to the window */
|
||||
|
|
|
@ -243,6 +243,7 @@ DECL_HANDLER(disconnect_named_pipe);
|
|||
DECL_HANDLER(get_named_pipe_info);
|
||||
DECL_HANDLER(create_window);
|
||||
DECL_HANDLER(destroy_window);
|
||||
DECL_HANDLER(get_desktop_window);
|
||||
DECL_HANDLER(set_window_owner);
|
||||
DECL_HANDLER(get_window_info);
|
||||
DECL_HANDLER(set_window_info);
|
||||
|
@ -453,6 +454,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_get_named_pipe_info,
|
||||
(req_handler)req_create_window,
|
||||
(req_handler)req_destroy_window,
|
||||
(req_handler)req_get_desktop_window,
|
||||
(req_handler)req_set_window_owner,
|
||||
(req_handler)req_get_window_info,
|
||||
(req_handler)req_set_window_info,
|
||||
|
|
|
@ -2226,6 +2226,15 @@ static void dump_destroy_window_request( const struct destroy_window_request *re
|
|||
fprintf( stderr, " handle=%p", req->handle );
|
||||
}
|
||||
|
||||
static void dump_get_desktop_window_request( const struct get_desktop_window_request *req )
|
||||
{
|
||||
}
|
||||
|
||||
static void dump_get_desktop_window_reply( const struct get_desktop_window_reply *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%p", req->handle );
|
||||
}
|
||||
|
||||
static void dump_set_window_owner_request( const struct set_window_owner_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%p,", req->handle );
|
||||
|
@ -3206,6 +3215,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_named_pipe_info_request,
|
||||
(dump_func)dump_create_window_request,
|
||||
(dump_func)dump_destroy_window_request,
|
||||
(dump_func)dump_get_desktop_window_request,
|
||||
(dump_func)dump_set_window_owner_request,
|
||||
(dump_func)dump_get_window_info_request,
|
||||
(dump_func)dump_set_window_info_request,
|
||||
|
@ -3413,6 +3423,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_named_pipe_info_reply,
|
||||
(dump_func)dump_create_window_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_desktop_window_reply,
|
||||
(dump_func)dump_set_window_owner_reply,
|
||||
(dump_func)dump_get_window_info_reply,
|
||||
(dump_func)dump_set_window_info_reply,
|
||||
|
@ -3620,6 +3631,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"get_named_pipe_info",
|
||||
"create_window",
|
||||
"destroy_window",
|
||||
"get_desktop_window",
|
||||
"set_window_owner",
|
||||
"get_window_info",
|
||||
"set_window_info",
|
||||
|
|
|
@ -38,6 +38,8 @@ enum user_object
|
|||
USER_HOOK
|
||||
};
|
||||
|
||||
#define DESKTOP_ATOM ((atom_t)32769)
|
||||
|
||||
/* user handles functions */
|
||||
|
||||
extern user_handle_t alloc_user_handle( void *ptr, enum user_object type );
|
||||
|
|
|
@ -96,8 +96,6 @@ struct user_handle_array
|
|||
int total;
|
||||
};
|
||||
|
||||
static struct window *top_window; /* top-level (desktop) window */
|
||||
|
||||
/* global window pointers */
|
||||
static struct window *shell_window;
|
||||
static struct window *shell_listview;
|
||||
|
@ -175,6 +173,12 @@ static inline struct window *get_last_child( struct window *win )
|
|||
return ptr ? LIST_ENTRY( ptr, struct window, entry ) : NULL;
|
||||
}
|
||||
|
||||
/* check if window is the desktop */
|
||||
static inline int is_desktop_window( const struct window *win )
|
||||
{
|
||||
return !win->parent; /* only desktop windows have no parent */
|
||||
}
|
||||
|
||||
/* append a user handle to a handle array */
|
||||
static int add_handle_to_array( struct user_handle_array *array, user_handle_t handle )
|
||||
{
|
||||
|
@ -293,8 +297,6 @@ inline static void destroy_properties( struct window *win )
|
|||
/* destroy a window */
|
||||
static void destroy_window( struct window *win )
|
||||
{
|
||||
assert( win != top_window );
|
||||
|
||||
/* destroy all children */
|
||||
while (!list_empty(&win->children))
|
||||
destroy_window( LIST_ENTRY( list_head(&win->children), struct window, entry ));
|
||||
|
@ -403,6 +405,21 @@ void destroy_thread_windows( struct thread *thread )
|
|||
}
|
||||
}
|
||||
|
||||
/* get the desktop window */
|
||||
static struct window *get_desktop_window( int create )
|
||||
{
|
||||
static struct window *top_window; /* FIXME: should be part of the desktop object */
|
||||
|
||||
if (!top_window && create)
|
||||
{
|
||||
if (!(top_window = create_window( NULL, NULL, DESKTOP_ATOM, 0 ))) return NULL;
|
||||
current->desktop_users--;
|
||||
top_window->thread = NULL; /* no thread owns the desktop */
|
||||
top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||
}
|
||||
return top_window;
|
||||
}
|
||||
|
||||
/* check whether child is a descendant of parent */
|
||||
int is_child_window( user_handle_t parent, user_handle_t child )
|
||||
{
|
||||
|
@ -422,7 +439,7 @@ int is_child_window( user_handle_t parent, user_handle_t child )
|
|||
int is_top_level_window( user_handle_t window )
|
||||
{
|
||||
struct window *win = get_user_object( window, USER_WINDOW );
|
||||
return (win && win->parent == top_window);
|
||||
return (win && win->parent && is_desktop_window(win->parent));
|
||||
}
|
||||
|
||||
/* make a window active if possible */
|
||||
|
@ -447,7 +464,7 @@ static inline void inc_window_paint_count( struct window *win, int incr )
|
|||
/* check if window and all its ancestors are visible */
|
||||
static int is_visible( const struct window *win )
|
||||
{
|
||||
while (win && win != top_window)
|
||||
while (win && win->parent)
|
||||
{
|
||||
if (!(win->style & WS_VISIBLE)) return 0;
|
||||
win = win->parent;
|
||||
|
@ -533,9 +550,9 @@ static int get_window_children_from_point( struct window *parent, int x, int y,
|
|||
/* find window containing point (in absolute coords) */
|
||||
user_handle_t window_from_point( int x, int y )
|
||||
{
|
||||
struct window *ret;
|
||||
struct window *ret, *top_window;
|
||||
|
||||
if (!top_window) return 0;
|
||||
if (!(top_window = get_desktop_window(0))) return 0;
|
||||
ret = child_window_from_point( top_window, x, y );
|
||||
return ret->handle;
|
||||
}
|
||||
|
@ -546,7 +563,7 @@ static int all_windows_from_point( struct window *top, int x, int y, struct user
|
|||
struct window *ptr;
|
||||
|
||||
/* make point relative to top window */
|
||||
for (ptr = top->parent; ptr && ptr != top_window; ptr = ptr->parent)
|
||||
for (ptr = top->parent; ptr; ptr = ptr->parent)
|
||||
{
|
||||
x -= ptr->client_rect.left;
|
||||
y -= ptr->client_rect.top;
|
||||
|
@ -618,8 +635,11 @@ static struct window *find_child_to_repaint( struct window *parent, struct threa
|
|||
/* find a window that needs to receive a WM_PAINT; also clear its internal paint flag */
|
||||
user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread )
|
||||
{
|
||||
struct window *ptr, *win = find_child_to_repaint( top_window, thread );
|
||||
struct window *ptr, *win, *top_window = get_desktop_window(0);
|
||||
|
||||
if (!top_window) return 0;
|
||||
|
||||
win = find_child_to_repaint( top_window, thread );
|
||||
if (win && parent)
|
||||
{
|
||||
/* check that it is a child of the specified parent */
|
||||
|
@ -718,7 +738,7 @@ static void set_region_client_rect( struct region *region, struct window *win )
|
|||
/* get the top-level window to clip against for a given window */
|
||||
static inline struct window *get_top_clipping_window( struct window *win )
|
||||
{
|
||||
while (win->parent && win->parent != top_window) win = win->parent;
|
||||
while (win->parent && !is_desktop_window(win->parent)) win = win->parent;
|
||||
return win;
|
||||
}
|
||||
|
||||
|
@ -916,7 +936,7 @@ static void validate_parents( struct window *child )
|
|||
|
||||
if (!child->update_region) return;
|
||||
|
||||
while (win->parent && win->parent != top_window)
|
||||
while (win->parent)
|
||||
{
|
||||
/* map to parent client coords */
|
||||
offset_x += win->window_rect.left;
|
||||
|
@ -1095,7 +1115,7 @@ static unsigned int get_window_update_flags( struct window *win, struct window *
|
|||
/* if some parent is not visible start from the next sibling */
|
||||
|
||||
if (!is_visible( win )) return 0;
|
||||
for (ptr = from_child; ptr && ptr != top_window; ptr = ptr->parent)
|
||||
for (ptr = from_child; ptr; ptr = ptr->parent)
|
||||
{
|
||||
if (!(ptr->style & WS_VISIBLE) || (ptr->style & WS_MINIMIZE)) from_sibling = ptr;
|
||||
if (ptr == win) break;
|
||||
|
@ -1106,15 +1126,14 @@ static unsigned int get_window_update_flags( struct window *win, struct window *
|
|||
|
||||
if ((flags & UPDATE_NONCLIENT) && !(flags & (UPDATE_PAINT|UPDATE_INTERNALPAINT)))
|
||||
{
|
||||
for (ptr = win->parent; ptr && ptr != top_window; ptr = ptr->parent)
|
||||
for (ptr = win->parent; ptr; ptr = ptr->parent)
|
||||
{
|
||||
if (!(ptr->style & WS_CLIPCHILDREN) && win_needs_repaint( ptr ))
|
||||
return 0;
|
||||
}
|
||||
if (from_child && !(flags & UPDATE_ALLCHILDREN))
|
||||
{
|
||||
for (ptr = from_sibling ? from_sibling : from_child;
|
||||
ptr && ptr != top_window; ptr = ptr->parent)
|
||||
for (ptr = from_sibling ? from_sibling : from_child; ptr; ptr = ptr->parent)
|
||||
{
|
||||
if (!(ptr->style & WS_CLIPCHILDREN) && win_needs_repaint( ptr )) from_sibling = ptr;
|
||||
if (ptr == win) break;
|
||||
|
@ -1300,35 +1319,24 @@ done:
|
|||
/* create a window */
|
||||
DECL_HANDLER(create_window)
|
||||
{
|
||||
struct window *win;
|
||||
struct window *win, *parent, *owner = NULL;
|
||||
|
||||
reply->handle = 0;
|
||||
if (!req->parent) /* return desktop window */
|
||||
{
|
||||
if (!top_window)
|
||||
{
|
||||
if (!(top_window = create_window( NULL, NULL, req->atom, req->instance ))) return;
|
||||
current->desktop_users--;
|
||||
top_window->thread = NULL; /* no thread owns the desktop */
|
||||
top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||
}
|
||||
win = top_window;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct window *parent, *owner = NULL;
|
||||
|
||||
if (!(parent = get_window( req->parent ))) return;
|
||||
if (req->owner && !(owner = get_window( req->owner ))) return;
|
||||
if (owner == top_window) owner = NULL;
|
||||
else if (owner && parent != top_window)
|
||||
if (req->owner)
|
||||
{
|
||||
if (!(owner = get_window( req->owner ))) return;
|
||||
if (is_desktop_window(owner)) owner = NULL;
|
||||
else if (!is_desktop_window(parent))
|
||||
{
|
||||
/* an owned window must be created as top-level */
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
}
|
||||
if (!(win = create_window( parent, owner, req->atom, req->instance ))) return;
|
||||
}
|
||||
if (!(win = create_window( parent, owner, req->atom, req->instance ))) return;
|
||||
|
||||
reply->handle = win->handle;
|
||||
reply->extra = win->nb_extra_bytes;
|
||||
reply->class_ptr = get_class_client_ptr( win->class );
|
||||
|
@ -1343,7 +1351,7 @@ DECL_HANDLER(set_parent)
|
|||
if (!(win = get_window( req->handle ))) return;
|
||||
if (req->parent && !(parent = get_window( req->parent ))) return;
|
||||
|
||||
if (win == top_window)
|
||||
if (is_desktop_window(win))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
|
@ -1360,12 +1368,21 @@ DECL_HANDLER(destroy_window)
|
|||
struct window *win = get_window( req->handle );
|
||||
if (win)
|
||||
{
|
||||
if (win != top_window) destroy_window( win );
|
||||
if (!is_desktop_window(win)) destroy_window( win );
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* retrieve the desktop window for the current thread */
|
||||
DECL_HANDLER(get_desktop_window)
|
||||
{
|
||||
struct window *win = get_desktop_window(1);
|
||||
|
||||
if (win) reply->handle = win->handle;
|
||||
}
|
||||
|
||||
|
||||
/* set a window owner */
|
||||
DECL_HANDLER(set_window_owner)
|
||||
{
|
||||
|
@ -1374,7 +1391,7 @@ DECL_HANDLER(set_window_owner)
|
|||
|
||||
if (!win) return;
|
||||
if (req->owner && !(owner = get_window( req->owner ))) return;
|
||||
if (win == top_window)
|
||||
if (is_desktop_window(win))
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
|
@ -1413,7 +1430,7 @@ DECL_HANDLER(set_window_info)
|
|||
struct window *win = get_window( req->handle );
|
||||
|
||||
if (!win) return;
|
||||
if (req->flags && win == top_window)
|
||||
if (req->flags && is_desktop_window(win))
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
|
@ -1805,7 +1822,7 @@ DECL_HANDLER(get_update_region)
|
|||
{
|
||||
win->paint_flags &= ~PAINT_ERASE;
|
||||
/* desktop window only gets erased, not repainted */
|
||||
if (win == top_window) validate_whole_window( win );
|
||||
if (is_desktop_window(win)) validate_whole_window( win );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue