Converted the window children lists to standard lists.
This commit is contained in:
parent
d12cb30693
commit
705909ac09
167
server/window.c
167
server/window.c
|
@ -56,11 +56,9 @@ struct window
|
||||||
{
|
{
|
||||||
struct window *parent; /* parent window */
|
struct window *parent; /* parent window */
|
||||||
user_handle_t owner; /* owner of this window */
|
user_handle_t owner; /* owner of this window */
|
||||||
struct window *first_child; /* first child in Z-order */
|
struct list children; /* list of children in Z-order */
|
||||||
struct window *last_child; /* last child in Z-order */
|
struct list unlinked; /* list of children not linked in the Z-order list */
|
||||||
struct window *first_unlinked; /* first child not linked in the Z-order list */
|
struct list entry; /* entry in parent's children list */
|
||||||
struct window *next; /* next window in Z-order */
|
|
||||||
struct window *prev; /* prev window in Z-order */
|
|
||||||
user_handle_t handle; /* full handle for this window */
|
user_handle_t handle; /* full handle for this window */
|
||||||
struct thread *thread; /* thread owning the window */
|
struct thread *thread; /* thread owning the window */
|
||||||
struct window_class *class; /* window class */
|
struct window_class *class; /* window class */
|
||||||
|
@ -112,52 +110,53 @@ inline static struct window *get_window( user_handle_t handle )
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unlink a window from the tree */
|
|
||||||
static void unlink_window( struct window *win )
|
|
||||||
{
|
|
||||||
struct window *parent = win->parent;
|
|
||||||
|
|
||||||
assert( parent );
|
|
||||||
|
|
||||||
if (win->next) win->next->prev = win->prev;
|
|
||||||
else if (parent->last_child == win) parent->last_child = win->prev;
|
|
||||||
|
|
||||||
if (win->prev) win->prev->next = win->next;
|
|
||||||
else if (parent->first_child == win) parent->first_child = win->next;
|
|
||||||
else if (parent->first_unlinked == win) parent->first_unlinked = win->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* link a window into the tree (or unlink it if the new parent is NULL) */
|
/* link a window into the tree (or unlink it if the new parent is NULL) */
|
||||||
static void link_window( struct window *win, struct window *parent, struct window *previous )
|
static void link_window( struct window *win, struct window *parent, struct window *previous )
|
||||||
{
|
{
|
||||||
unlink_window( win ); /* unlink it from the previous location */
|
list_remove( &win->entry ); /* unlink it from the previous location */
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
win->parent = parent;
|
win->parent = parent;
|
||||||
if ((win->prev = previous))
|
if (previous) list_add_after( &previous->entry, &win->entry );
|
||||||
{
|
else list_add_head( &parent->children, &win->entry );
|
||||||
if ((win->next = previous->next)) win->next->prev = win;
|
|
||||||
else if (win->parent->last_child == previous) win->parent->last_child = win;
|
|
||||||
win->prev->next = win;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((win->next = parent->first_child)) win->next->prev = win;
|
|
||||||
else win->parent->last_child = win;
|
|
||||||
parent->first_child = win;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else /* move it to parent unlinked list */
|
else /* move it to parent unlinked list */
|
||||||
{
|
{
|
||||||
parent = win->parent;
|
list_add_head( &win->parent->unlinked, &win->entry );
|
||||||
if ((win->next = parent->first_unlinked)) win->next->prev = win;
|
|
||||||
win->prev = NULL;
|
|
||||||
parent->first_unlinked = win;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get next window in Z-order list */
|
||||||
|
static inline struct window *get_next_window( struct window *win )
|
||||||
|
{
|
||||||
|
struct list *ptr = list_next( &win->parent->children, &win->entry );
|
||||||
|
if (ptr == &win->parent->unlinked) ptr = NULL;
|
||||||
|
return ptr ? LIST_ENTRY( ptr, struct window, entry ) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get previous window in Z-order list */
|
||||||
|
static inline struct window *get_prev_window( struct window *win )
|
||||||
|
{
|
||||||
|
struct list *ptr = list_prev( &win->parent->children, &win->entry );
|
||||||
|
if (ptr == &win->parent->unlinked) ptr = NULL;
|
||||||
|
return ptr ? LIST_ENTRY( ptr, struct window, entry ) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get first child in Z-order list */
|
||||||
|
static inline struct window *get_first_child( struct window *win )
|
||||||
|
{
|
||||||
|
struct list *ptr = list_head( &win->children );
|
||||||
|
return ptr ? LIST_ENTRY( ptr, struct window, entry ) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get last child in Z-order list */
|
||||||
|
static inline struct window *get_last_child( struct window *win )
|
||||||
|
{
|
||||||
|
struct list *ptr = list_tail( &win->children );
|
||||||
|
return ptr ? LIST_ENTRY( ptr, struct window, entry ) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* append a user handle to a handle array */
|
/* append a user handle to a handle array */
|
||||||
static int add_handle_to_array( struct user_handle_array *array, user_handle_t handle )
|
static int add_handle_to_array( struct user_handle_array *array, user_handle_t handle )
|
||||||
{
|
{
|
||||||
|
@ -279,8 +278,10 @@ static void destroy_window( struct window *win )
|
||||||
assert( win != top_window );
|
assert( win != top_window );
|
||||||
|
|
||||||
/* destroy all children */
|
/* destroy all children */
|
||||||
while (win->first_child) destroy_window( win->first_child );
|
while (!list_empty(&win->children))
|
||||||
while (win->first_unlinked) destroy_window( win->first_unlinked );
|
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 (win->thread->queue)
|
if (win->thread->queue)
|
||||||
{
|
{
|
||||||
|
@ -295,7 +296,7 @@ static void destroy_window( struct window *win )
|
||||||
if (win == taskman_window) taskman_window = NULL;
|
if (win == taskman_window) taskman_window = NULL;
|
||||||
free_user_handle( win->handle );
|
free_user_handle( win->handle );
|
||||||
destroy_properties( win );
|
destroy_properties( win );
|
||||||
unlink_window( win );
|
list_remove( &win->entry );
|
||||||
if (win->win_region) free_region( win->win_region );
|
if (win->win_region) free_region( win->win_region );
|
||||||
if (win->update_region) free_region( win->update_region );
|
if (win->update_region) free_region( win->update_region );
|
||||||
release_class( win->class );
|
release_class( win->class );
|
||||||
|
@ -329,9 +330,6 @@ static struct window *create_window( struct window *parent, struct window *owner
|
||||||
}
|
}
|
||||||
win->parent = parent;
|
win->parent = parent;
|
||||||
win->owner = owner ? owner->handle : 0;
|
win->owner = owner ? owner->handle : 0;
|
||||||
win->first_child = NULL;
|
|
||||||
win->last_child = NULL;
|
|
||||||
win->first_unlinked = NULL;
|
|
||||||
win->thread = current;
|
win->thread = current;
|
||||||
win->class = class;
|
win->class = class;
|
||||||
win->atom = atom;
|
win->atom = atom;
|
||||||
|
@ -350,14 +348,11 @@ static struct window *create_window( struct window *parent, struct window *owner
|
||||||
win->properties = NULL;
|
win->properties = NULL;
|
||||||
win->nb_extra_bytes = extra_bytes;
|
win->nb_extra_bytes = extra_bytes;
|
||||||
memset( win->extra_bytes, 0, extra_bytes );
|
memset( win->extra_bytes, 0, extra_bytes );
|
||||||
|
list_init( &win->children );
|
||||||
|
list_init( &win->unlinked );
|
||||||
|
|
||||||
if (parent) /* put it on parent unlinked list */
|
/* put it on parent unlinked list */
|
||||||
{
|
if (parent) list_add_head( &parent->unlinked, &win->entry );
|
||||||
if ((win->next = parent->first_unlinked)) win->next->prev = win;
|
|
||||||
win->prev = NULL;
|
|
||||||
parent->first_unlinked = win;
|
|
||||||
}
|
|
||||||
else win->next = win->prev = NULL;
|
|
||||||
|
|
||||||
/* if parent belongs to a different thread, attach the two threads */
|
/* if parent belongs to a different thread, attach the two threads */
|
||||||
if (parent && parent->thread && parent->thread != current)
|
if (parent && parent->thread && parent->thread != current)
|
||||||
|
@ -462,7 +457,7 @@ static struct window *child_window_from_point( struct window *parent, int x, int
|
||||||
{
|
{
|
||||||
struct window *ptr;
|
struct window *ptr;
|
||||||
|
|
||||||
for (ptr = parent->first_child; ptr; ptr = ptr->next)
|
LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry )
|
||||||
{
|
{
|
||||||
if (!is_point_in_window( ptr, x, y )) continue; /* skip it */
|
if (!is_point_in_window( ptr, x, y )) continue; /* skip it */
|
||||||
|
|
||||||
|
@ -485,7 +480,7 @@ static int get_window_children_from_point( struct window *parent, int x, int y,
|
||||||
{
|
{
|
||||||
struct window *ptr;
|
struct window *ptr;
|
||||||
|
|
||||||
for (ptr = parent->first_child; ptr; ptr = ptr->next)
|
LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry )
|
||||||
{
|
{
|
||||||
if (!is_point_in_window( ptr, x, y )) continue; /* skip it */
|
if (!is_point_in_window( ptr, x, y )) continue; /* skip it */
|
||||||
|
|
||||||
|
@ -565,19 +560,20 @@ static struct window *find_child_to_repaint( struct window *parent, struct threa
|
||||||
{
|
{
|
||||||
struct window *ptr, *ret = NULL;
|
struct window *ptr, *ret = NULL;
|
||||||
|
|
||||||
for (ptr = parent->first_child; ptr && !ret; ptr = ptr->next)
|
LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry )
|
||||||
{
|
{
|
||||||
if (!(ptr->style & WS_VISIBLE)) continue;
|
if (!(ptr->style & WS_VISIBLE)) continue;
|
||||||
if (ptr->thread == thread && win_needs_repaint( ptr ))
|
if (ptr->thread == thread && win_needs_repaint( ptr ))
|
||||||
ret = ptr;
|
ret = ptr;
|
||||||
else if (!(ptr->style & WS_MINIMIZE)) /* explore its children */
|
else if (!(ptr->style & WS_MINIMIZE)) /* explore its children */
|
||||||
ret = find_child_to_repaint( ptr, thread );
|
ret = find_child_to_repaint( ptr, thread );
|
||||||
|
if (ret) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret && (ret->ex_style & WS_EX_TRANSPARENT))
|
if (ret && (ret->ex_style & WS_EX_TRANSPARENT))
|
||||||
{
|
{
|
||||||
/* transparent window, check for non-transparent sibling to paint first */
|
/* transparent window, check for non-transparent sibling to paint first */
|
||||||
for (ptr = ret->next; ptr; ptr = ptr->next)
|
for (ptr = get_next_window(ret); ptr; ptr = get_next_window(ptr))
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
@ -628,8 +624,9 @@ static struct region *clip_children( struct window *parent, struct window *last,
|
||||||
struct region *tmp = create_empty_region();
|
struct region *tmp = create_empty_region();
|
||||||
|
|
||||||
if (!tmp) return NULL;
|
if (!tmp) return NULL;
|
||||||
for (ptr = parent->first_child; ptr && ptr != last; ptr = ptr->next)
|
LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry )
|
||||||
{
|
{
|
||||||
|
if (ptr == last) break;
|
||||||
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 );
|
||||||
|
@ -961,7 +958,7 @@ static void redraw_window( struct window *win, struct region *region, int frame,
|
||||||
|
|
||||||
if (flags & RDW_INVALIDATE) flags |= RDW_FRAME | RDW_ERASE;
|
if (flags & RDW_INVALIDATE) flags |= RDW_FRAME | RDW_ERASE;
|
||||||
|
|
||||||
for (child = win->first_child; child; child = child->next)
|
LIST_FOR_EACH_ENTRY( child, &win->children, struct window, entry )
|
||||||
{
|
{
|
||||||
if (!(child->style & WS_VISIBLE)) continue;
|
if (!(child->style & WS_VISIBLE)) continue;
|
||||||
if (!rect_in_region( tmp, &child->window_rect )) continue;
|
if (!rect_in_region( tmp, &child->window_rect )) continue;
|
||||||
|
@ -1005,7 +1002,7 @@ static unsigned int get_child_update_flags( struct window *win, unsigned int fla
|
||||||
struct window *ptr;
|
struct window *ptr;
|
||||||
unsigned int ret = 0;
|
unsigned int ret = 0;
|
||||||
|
|
||||||
for (ptr = win->first_child; ptr && !ret; ptr = ptr->next)
|
LIST_FOR_EACH_ENTRY( ptr, &win->children, struct window, entry )
|
||||||
{
|
{
|
||||||
if (!(ptr->style & WS_VISIBLE)) continue;
|
if (!(ptr->style & WS_VISIBLE)) continue;
|
||||||
if ((ret = get_update_flags( ptr, flags )) != 0)
|
if ((ret = get_update_flags( ptr, flags )) != 0)
|
||||||
|
@ -1021,7 +1018,9 @@ static unsigned int get_child_update_flags( struct window *win, unsigned int fla
|
||||||
*/
|
*/
|
||||||
if (!(flags & UPDATE_NOCHILDREN) &&
|
if (!(flags & UPDATE_NOCHILDREN) &&
|
||||||
((flags & UPDATE_ALLCHILDREN) || (ptr->style & WS_CLIPCHILDREN)))
|
((flags & UPDATE_ALLCHILDREN) || (ptr->style & WS_CLIPCHILDREN)))
|
||||||
ret = get_child_update_flags( ptr, flags, child );
|
{
|
||||||
|
if ((ret = get_child_update_flags( ptr, flags, child ))) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1202,7 +1201,7 @@ DECL_HANDLER(link_window)
|
||||||
{
|
{
|
||||||
if (req->previous == (user_handle_t)1) /* special case: HWND_BOTTOM */
|
if (req->previous == (user_handle_t)1) /* special case: HWND_BOTTOM */
|
||||||
{
|
{
|
||||||
previous = parent->last_child;
|
previous = get_last_child( parent );
|
||||||
if (previous == win) return; /* nothing to do */
|
if (previous == win) return; /* nothing to do */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1346,19 +1345,21 @@ DECL_HANDLER(get_window_children)
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
for (ptr = parent->first_child, total = 0; ptr; ptr = ptr->next)
|
{
|
||||||
|
LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry )
|
||||||
{
|
{
|
||||||
if (req->atom && get_class_atom(ptr->class) != req->atom) continue;
|
if (req->atom && get_class_atom(ptr->class) != req->atom) continue;
|
||||||
if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
|
if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
reply->count = total;
|
reply->count = total;
|
||||||
len = min( get_reply_max_size(), total * sizeof(user_handle_t) );
|
len = min( get_reply_max_size(), total * sizeof(user_handle_t) );
|
||||||
if (len && ((data = set_reply_data_size( len ))))
|
if (len && ((data = set_reply_data_size( len ))))
|
||||||
{
|
{
|
||||||
for (ptr = parent->first_child; ptr && len; ptr = ptr->next)
|
LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry )
|
||||||
{
|
{
|
||||||
|
if (len < sizeof(*data)) break;
|
||||||
if (req->atom && get_class_atom(ptr->class) != req->atom) continue;
|
if (req->atom && get_class_atom(ptr->class) != req->atom) continue;
|
||||||
if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
|
if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
|
||||||
*data++ = ptr->handle;
|
*data++ = ptr->handle;
|
||||||
|
@ -1392,31 +1393,31 @@ DECL_HANDLER(get_window_children_from_point)
|
||||||
/* get window tree information from a window handle */
|
/* get window tree information from a window handle */
|
||||||
DECL_HANDLER(get_window_tree)
|
DECL_HANDLER(get_window_tree)
|
||||||
{
|
{
|
||||||
struct window *win = get_window( req->handle );
|
struct window *ptr, *win = get_window( req->handle );
|
||||||
|
|
||||||
if (!win) return;
|
if (!win) return;
|
||||||
|
|
||||||
|
reply->parent = 0;
|
||||||
|
reply->owner = 0;
|
||||||
|
reply->next_sibling = 0;
|
||||||
|
reply->prev_sibling = 0;
|
||||||
|
reply->first_sibling = 0;
|
||||||
|
reply->last_sibling = 0;
|
||||||
|
reply->first_child = 0;
|
||||||
|
reply->last_child = 0;
|
||||||
|
|
||||||
if (win->parent)
|
if (win->parent)
|
||||||
{
|
{
|
||||||
struct window *parent = win->parent;
|
struct window *parent = win->parent;
|
||||||
reply->parent = parent->handle;
|
reply->parent = parent->handle;
|
||||||
reply->owner = win->owner;
|
reply->owner = win->owner;
|
||||||
reply->next_sibling = win->next ? win->next->handle : 0;
|
if ((ptr = get_next_window( win ))) reply->next_sibling = ptr->handle;
|
||||||
reply->prev_sibling = win->prev ? win->prev->handle : 0;
|
if ((ptr = get_prev_window( win ))) reply->prev_sibling = ptr->handle;
|
||||||
reply->first_sibling = parent->first_child ? parent->first_child->handle : 0;
|
if ((ptr = get_first_child( parent ))) reply->first_sibling = ptr->handle;
|
||||||
reply->last_sibling = parent->last_child ? parent->last_child->handle : 0;
|
if ((ptr = get_last_child( parent ))) reply->last_sibling = ptr->handle;
|
||||||
}
|
}
|
||||||
else
|
if ((ptr = get_first_child( win ))) reply->first_child = ptr->handle;
|
||||||
{
|
if ((ptr = get_last_child( win ))) reply->last_child = ptr->handle;
|
||||||
reply->parent = 0;
|
|
||||||
reply->owner = 0;
|
|
||||||
reply->next_sibling = 0;
|
|
||||||
reply->prev_sibling = 0;
|
|
||||||
reply->first_sibling = 0;
|
|
||||||
reply->last_sibling = 0;
|
|
||||||
}
|
|
||||||
reply->first_child = win->first_child ? win->first_child->handle : 0;
|
|
||||||
reply->last_child = win->last_child ? win->last_child->handle : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1441,11 +1442,11 @@ DECL_HANDLER(set_window_pos)
|
||||||
{
|
{
|
||||||
if (!req->previous) /* special case: HWND_TOP */
|
if (!req->previous) /* special case: HWND_TOP */
|
||||||
{
|
{
|
||||||
if (win->parent->first_child == win) flags |= SWP_NOZORDER;
|
if (get_first_child(win->parent) == win) flags |= SWP_NOZORDER;
|
||||||
}
|
}
|
||||||
else if (req->previous == (user_handle_t)1) /* special case: HWND_BOTTOM */
|
else if (req->previous == (user_handle_t)1) /* special case: HWND_BOTTOM */
|
||||||
{
|
{
|
||||||
previous = win->parent->last_child;
|
previous = get_last_child( win->parent );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue