From 8c518808b8664a35a9489288e2f5ce0a7d594414 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 8 Jul 2005 11:37:40 +0000 Subject: [PATCH] Put in place the basic infrastructure to allow supporting multiple desktop windows. --- dlls/user/user_main.c | 3 -- dlls/user/user_private.h | 3 +- dlls/user/win.c | 50 +++++------------ dlls/user/winstation.c | 2 + include/win.h | 1 - include/wine/server_protocol.h | 17 +++++- server/protocol.def | 7 +++ server/request.h | 2 + server/trace.c | 12 +++++ server/user.h | 2 + server/window.c | 99 ++++++++++++++++++++-------------- 11 files changed, 115 insertions(+), 83 deletions(-) diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c index 35407d02f05..523d0407db0 100644 --- a/dlls/user/user_main.c +++ b/dlls/user/user_main.c @@ -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; } diff --git a/dlls/user/user_private.h b/dlls/user/user_private.h index 0aad38bb88b..c294cac69fb 100644 --- a/dlls/user/user_private.h +++ b/dlls/user/user_private.h @@ -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) diff --git a/dlls/user/win.c b/dlls/user/win.c index cfa2e6fed95..7317da58798 100644 --- a/dlls/user/win.c +++ b/dlls/user/win.c @@ -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; } diff --git a/dlls/user/winstation.c b/dlls/user/winstation.c index 99ae96feb91..9e7214646f9 100644 --- a/dlls/user/winstation.c +++ b/dlls/user/winstation.c @@ -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; } diff --git a/include/win.h b/include/win.h index b7112457f80..a1714761c14 100644 --- a/include/win.h +++ b/include/win.h @@ -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 ); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 7f93ea2938a..bbd4fa6df94 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -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 */ diff --git a/server/protocol.def b/server/protocol.def index d79d5efe148..7d2c62d0a2b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -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 */ diff --git a/server/request.h b/server/request.h index b8cd447968c..ca98368be06 100644 --- a/server/request.h +++ b/server/request.h @@ -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, diff --git a/server/trace.c b/server/trace.c index 4f8d7849681..bb80613fd74 100644 --- a/server/trace.c +++ b/server/trace.c @@ -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", diff --git a/server/user.h b/server/user.h index 44d8f389c54..5bf3735e3a5 100644 --- a/server/user.h +++ b/server/user.h @@ -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 ); diff --git a/server/window.c b/server/window.c index 1d6dbdc30d7..0a4cdfafbda 100644 --- a/server/window.c +++ b/server/window.c @@ -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 (!(parent = get_window( req->parent ))) return; + 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 ); } } }