Commit 8c518808 authored by Alexandre Julliard's avatar Alexandre Julliard

Put in place the basic infrastructure to allow supporting multiple

desktop windows.
parent 87458a5c
......@@ -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 (!(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 );
}
}
}
......
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