mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 20:59:54 +00:00
server: Infrastructure for having a thread own the desktop window.
This commit is contained in:
parent
19a3adb958
commit
251be542ac
@ -54,8 +54,6 @@ struct window_class
|
||||
char extra_bytes[1]; /* extra bytes storage */
|
||||
};
|
||||
|
||||
static struct window_class *desktop_class;
|
||||
|
||||
static struct window_class *create_class( struct process *process, int extra_bytes, int local )
|
||||
{
|
||||
struct window_class *class;
|
||||
@ -75,24 +73,6 @@ static struct window_class *create_class( struct process *process, int extra_byt
|
||||
return class;
|
||||
}
|
||||
|
||||
static struct window_class *get_desktop_class(void)
|
||||
{
|
||||
if (!desktop_class)
|
||||
{
|
||||
if (!(desktop_class = mem_alloc( sizeof(*desktop_class) - 1 ))) return NULL;
|
||||
desktop_class->process = NULL;
|
||||
desktop_class->count = 0;
|
||||
desktop_class->local = 0;
|
||||
desktop_class->nb_extra_bytes = 0;
|
||||
desktop_class->atom = DESKTOP_ATOM;
|
||||
desktop_class->instance = NULL;
|
||||
desktop_class->style = CS_DBLCLKS;
|
||||
desktop_class->win_extra = 0;
|
||||
desktop_class->client_ptr = NULL;
|
||||
}
|
||||
return desktop_class;
|
||||
}
|
||||
|
||||
static void destroy_class( struct window_class *class )
|
||||
{
|
||||
list_remove( &class->entry );
|
||||
@ -121,7 +101,6 @@ static struct window_class *find_class( struct process *process, atom_t atom, vo
|
||||
if (class->atom != atom) continue;
|
||||
if (!instance || !class->local || class->instance == instance) return class;
|
||||
}
|
||||
if (atom == DESKTOP_ATOM) return get_desktop_class();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -144,6 +123,11 @@ void release_class( struct window_class *class )
|
||||
class->count--;
|
||||
}
|
||||
|
||||
int is_desktop_class( struct window_class *class )
|
||||
{
|
||||
return (class->atom == DESKTOP_ATOM && !class->local);
|
||||
}
|
||||
|
||||
atom_t get_class_atom( struct window_class *class )
|
||||
{
|
||||
return class->atom;
|
||||
@ -160,9 +144,6 @@ DECL_HANDLER(create_class)
|
||||
struct window_class *class;
|
||||
struct winstation *winstation;
|
||||
|
||||
if (!req->local && req->atom == DESKTOP_ATOM)
|
||||
return; /* silently ignore attempts to create the desktop class */
|
||||
|
||||
class = find_class( current->process, req->atom, req->instance );
|
||||
if (class && !class->local == !req->local)
|
||||
{
|
||||
@ -210,7 +191,7 @@ DECL_HANDLER(destroy_class)
|
||||
else
|
||||
{
|
||||
reply->client_ptr = class->client_ptr;
|
||||
if (class != desktop_class) destroy_class( class );
|
||||
destroy_class( class );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,7 @@ extern void destroy_process_classes( struct process *process );
|
||||
extern struct window_class *grab_class( struct process *process, atom_t atom,
|
||||
void *instance, int *extra_bytes );
|
||||
extern void release_class( struct window_class *class );
|
||||
extern int is_desktop_class( struct window_class *class );
|
||||
extern atom_t get_class_atom( struct window_class *class );
|
||||
extern void *get_class_client_ptr( struct window_class *class );
|
||||
|
||||
|
@ -297,23 +297,37 @@ inline static void destroy_properties( struct window *win )
|
||||
free( win->properties );
|
||||
}
|
||||
|
||||
/* destroy a window */
|
||||
void destroy_window( struct window *win )
|
||||
/* detach a window from its owner thread but keep the window around */
|
||||
static void detach_window_thread( struct window *win )
|
||||
{
|
||||
struct thread *thread = win->thread;
|
||||
|
||||
/* destroy all children */
|
||||
while (!list_empty(&win->children))
|
||||
destroy_window( LIST_ENTRY( list_head(&win->children), struct window, entry ));
|
||||
while (!list_empty(&win->unlinked))
|
||||
destroy_window( LIST_ENTRY( list_head(&win->unlinked), struct window, entry ));
|
||||
|
||||
if (thread && thread->queue)
|
||||
if (!thread) return;
|
||||
if (thread->queue)
|
||||
{
|
||||
if (win->update_region) inc_queue_paint_count( thread, -1 );
|
||||
if (win->paint_flags & PAINT_INTERNAL) inc_queue_paint_count( thread, -1 );
|
||||
queue_cleanup_window( thread, win->handle );
|
||||
}
|
||||
assert( thread->desktop_users > 0 );
|
||||
thread->desktop_users--;
|
||||
release_class( win->class );
|
||||
win->class = NULL;
|
||||
|
||||
/* don't hold a reference to the desktop so that the desktop window can be */
|
||||
/* destroyed when the desktop ref count reaches zero */
|
||||
release_object( win->desktop );
|
||||
win->thread = NULL;
|
||||
}
|
||||
|
||||
/* destroy a window */
|
||||
void destroy_window( struct window *win )
|
||||
{
|
||||
/* destroy all children */
|
||||
while (!list_empty(&win->children))
|
||||
destroy_window( LIST_ENTRY( list_head(&win->children), struct window, entry ));
|
||||
while (!list_empty(&win->unlinked))
|
||||
destroy_window( LIST_ENTRY( list_head(&win->unlinked), struct window, entry ));
|
||||
|
||||
/* reset global window pointers, if the corresponding window is destroyed */
|
||||
if (win == shell_window) shell_window = NULL;
|
||||
@ -323,16 +337,16 @@ void destroy_window( struct window *win )
|
||||
free_user_handle( win->handle );
|
||||
destroy_properties( win );
|
||||
list_remove( &win->entry );
|
||||
if (is_desktop_window(win))
|
||||
{
|
||||
assert( win->desktop->top_window == win );
|
||||
win->desktop->top_window = NULL;
|
||||
}
|
||||
detach_window_thread( win );
|
||||
if (win->win_region) free_region( win->win_region );
|
||||
if (win->update_region) free_region( win->update_region );
|
||||
release_class( win->class );
|
||||
if (win->class) release_class( win->class );
|
||||
if (win->text) free( win->text );
|
||||
if (!is_desktop_window(win))
|
||||
{
|
||||
assert( thread->desktop_users > 0 );
|
||||
thread->desktop_users--;
|
||||
release_object( win->desktop );
|
||||
}
|
||||
memset( win, 0x55, sizeof(*win) + win->nb_extra_bytes - 1 );
|
||||
free( win );
|
||||
}
|
||||
@ -354,13 +368,7 @@ static struct window *create_window( struct window *parent, struct window *owner
|
||||
return NULL;
|
||||
}
|
||||
|
||||
win = mem_alloc( sizeof(*win) + extra_bytes - 1 );
|
||||
if (!win)
|
||||
{
|
||||
release_object( desktop );
|
||||
release_class( class );
|
||||
return NULL;
|
||||
}
|
||||
if (!(win = mem_alloc( sizeof(*win) + extra_bytes - 1 ))) goto failed;
|
||||
if (!(win->handle = alloc_user_handle( win, USER_WINDOW ))) goto failed;
|
||||
|
||||
win->parent = parent;
|
||||
@ -395,6 +403,13 @@ static struct window *create_window( struct window *parent, struct window *owner
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* if no parent, class must be the desktop */
|
||||
if (!parent && !is_desktop_class( class ))
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* if parent belongs to a different thread, attach the two threads */
|
||||
if (parent && parent->thread && parent->thread != current)
|
||||
{
|
||||
@ -407,16 +422,24 @@ static struct window *create_window( struct window *parent, struct window *owner
|
||||
|
||||
/* put it on parent unlinked list */
|
||||
if (parent) list_add_head( &parent->unlinked, &win->entry );
|
||||
else list_init( &win->entry );
|
||||
else
|
||||
{
|
||||
list_init( &win->entry );
|
||||
assert( !desktop->top_window );
|
||||
desktop->top_window = win;
|
||||
}
|
||||
|
||||
current->desktop_users++;
|
||||
return win;
|
||||
|
||||
failed:
|
||||
if (win)
|
||||
{
|
||||
if (win->handle) free_user_handle( win->handle );
|
||||
free( win );
|
||||
}
|
||||
release_object( desktop );
|
||||
release_class( class );
|
||||
free( win );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -429,7 +452,8 @@ void destroy_thread_windows( struct thread *thread )
|
||||
while ((win = next_user_handle( &handle, USER_WINDOW )))
|
||||
{
|
||||
if (win->thread != thread) continue;
|
||||
destroy_window( win );
|
||||
if (is_desktop_window( win )) detach_window_thread( win );
|
||||
else destroy_window( win );
|
||||
}
|
||||
}
|
||||
|
||||
@ -445,13 +469,8 @@ static struct window *get_desktop_window( struct thread *thread, int create )
|
||||
{
|
||||
if ((top_window = create_window( NULL, NULL, DESKTOP_ATOM, 0 )))
|
||||
{
|
||||
current->desktop_users--;
|
||||
top_window->thread = NULL; /* no thread owns the desktop */
|
||||
detach_window_thread( top_window );
|
||||
top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||
desktop->top_window = top_window;
|
||||
/* don't hold a reference to the desktop so that the desktop window can be */
|
||||
/* destroyed when the desktop ref count reaches zero */
|
||||
release_object( top_window->desktop );
|
||||
}
|
||||
}
|
||||
release_object( desktop );
|
||||
@ -677,7 +696,9 @@ user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *threa
|
||||
|
||||
if (!top_window) return 0;
|
||||
|
||||
win = find_child_to_repaint( top_window, thread );
|
||||
if (top_window->thread == thread && win_needs_repaint( top_window )) win = top_window;
|
||||
else win = find_child_to_repaint( top_window, thread );
|
||||
|
||||
if (win && parent)
|
||||
{
|
||||
/* check that it is a child of the specified parent */
|
||||
@ -859,6 +880,7 @@ struct window_class* get_window_class( user_handle_t window )
|
||||
{
|
||||
struct window *win;
|
||||
if (!(win = get_window( window ))) return NULL;
|
||||
if (!win->class) set_error( STATUS_ACCESS_DENIED );
|
||||
return win->class;
|
||||
}
|
||||
|
||||
@ -1361,7 +1383,9 @@ DECL_HANDLER(create_window)
|
||||
|
||||
reply->handle = 0;
|
||||
|
||||
if (!(parent = get_window( req->parent ))) return;
|
||||
if (!req->parent) parent = get_desktop_window( current, 0 );
|
||||
else if (!(parent = get_window( req->parent ))) return;
|
||||
|
||||
if (req->owner)
|
||||
{
|
||||
if (!(owner = get_window( req->owner ))) return;
|
||||
@ -1411,6 +1435,7 @@ DECL_HANDLER(destroy_window)
|
||||
if (win)
|
||||
{
|
||||
if (!is_desktop_window(win)) destroy_window( win );
|
||||
else if (win->thread == current) detach_window_thread( win );
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
}
|
||||
@ -1460,7 +1485,7 @@ DECL_HANDLER(get_window_info)
|
||||
{
|
||||
reply->tid = get_thread_id( win->thread );
|
||||
reply->pid = get_process_id( win->thread->process );
|
||||
reply->atom = get_class_atom( win->class );
|
||||
reply->atom = win->class ? get_class_atom( win->class ) : DESKTOP_ATOM;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1472,7 +1497,7 @@ DECL_HANDLER(set_window_info)
|
||||
struct window *win = get_window( req->handle );
|
||||
|
||||
if (!win) return;
|
||||
if (req->flags && is_desktop_window(win))
|
||||
if (req->flags && is_desktop_window(win) && win->thread != current)
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user