2 * Server-side window handling
4 * Copyright (C) 2001 Alexandre Julliard
17 struct window
*parent
; /* parent window */
18 struct window
*owner
; /* owner of this window */
19 struct window
*first_child
; /* first child window */
20 struct window
*last_child
; /* last child window */
21 struct window
*next
; /* next window in Z-order */
22 struct window
*prev
; /* prev window in Z-order */
23 user_handle_t handle
; /* full handle for this window */
24 struct thread
*thread
; /* thread owning the window */
27 static struct window
*top_window
; /* top-level (desktop) window */
30 /* retrieve a pointer to a window from its handle */
31 inline static struct window
*get_window( user_handle_t handle
)
33 struct window
*ret
= get_user_object( handle
, USER_WINDOW
);
34 if (!ret
) set_error( STATUS_INVALID_HANDLE
);
38 /* link a window into the tree (or unlink it if the new parent is NULL) */
39 static void link_window( struct window
*win
, struct window
*parent
, struct window
*previous
)
41 if (win
->parent
) /* unlink it from the previous location */
43 if (win
->next
) win
->next
->prev
= win
->prev
;
44 else if (win
->parent
->last_child
== win
) win
->parent
->last_child
= win
->prev
;
45 if (win
->prev
) win
->prev
->next
= win
->next
;
46 else if (win
->parent
->first_child
== win
) win
->parent
->first_child
= win
->next
;
51 if ((win
->prev
= previous
))
53 if ((win
->next
= previous
->next
)) win
->next
->prev
= win
;
54 else if (win
->parent
->last_child
== previous
) win
->parent
->last_child
= win
;
55 win
->prev
->next
= win
;
59 if ((win
->next
= parent
->first_child
)) win
->next
->prev
= win
;
60 else win
->parent
->last_child
= win
;
61 parent
->first_child
= win
;
66 /* don't touch parent; an unlinked window still has a valid parent pointer */
67 win
->next
= win
->prev
= NULL
;
71 /* destroy a window */
72 static void destroy_window( struct window
*win
)
74 assert( win
!= top_window
);
76 /* destroy all children */
77 while (win
->first_child
) destroy_window( win
->first_child
);
79 /* reset siblings owner */
83 for (ptr
= win
->parent
->first_child
; ptr
; ptr
= ptr
->next
)
84 if (ptr
->owner
== win
) ptr
->owner
= NULL
;
87 if (win
->thread
->queue
) queue_cleanup_window( win
->thread
, win
->handle
);
88 free_user_handle( win
->handle
);
89 link_window( win
, NULL
, NULL
);
90 memset( win
, 0x55, sizeof(*win
) );
94 /* create a new window structure (note: the window is not linked in the window tree) */
95 static struct window
*create_window( struct window
*parent
, struct window
*owner
)
97 struct window
*win
= mem_alloc( sizeof(*win
) );
98 if (!win
) return NULL
;
100 if (!(win
->handle
= alloc_user_handle( win
, USER_WINDOW
)))
105 win
->parent
= parent
;
107 win
->first_child
= NULL
;
108 win
->last_child
= NULL
;
111 win
->thread
= current
;
115 /* destroy all windows belonging to a given thread */
116 void destroy_thread_windows( struct thread
*thread
)
118 user_handle_t handle
= 0;
121 while ((win
= next_user_handle( &handle
, USER_WINDOW
)))
123 if (win
->thread
!= thread
) continue;
124 destroy_window( win
);
128 /* check whether child is a descendant of parent */
129 int is_child_window( user_handle_t parent
, user_handle_t child
)
131 struct window
*child_ptr
= get_user_object( child
, USER_WINDOW
);
132 struct window
*parent_ptr
= get_user_object( parent
, USER_WINDOW
);
134 if (!child_ptr
|| !parent_ptr
) return 0;
135 while (child_ptr
->parent
)
137 if (child_ptr
->parent
== parent_ptr
) return 1;
138 child_ptr
= child_ptr
->parent
;
143 /* create a window */
144 DECL_HANDLER(create_window
)
147 if (!req
->parent
) /* return desktop window */
151 if (!(top_window
= create_window( NULL
, NULL
))) return;
152 top_window
->thread
= NULL
; /* no thread owns the desktop */
154 req
->handle
= top_window
->handle
;
158 struct window
*win
, *parent
, *owner
= NULL
;
160 if (!(parent
= get_window( req
->parent
))) return;
161 if (req
->owner
&& !(owner
= get_window( req
->owner
))) return;
162 if (!(win
= create_window( parent
, owner
))) return;
163 req
->handle
= win
->handle
;
168 /* link a window into the tree */
169 DECL_HANDLER(link_window
)
171 struct window
*win
, *parent
= NULL
, *previous
= NULL
;
173 if (!(win
= get_window( req
->handle
))) return;
174 if (req
->parent
&& !(parent
= get_window( req
->parent
))) return;
175 if (parent
&& req
->previous
)
177 if (req
->previous
== (user_handle_t
)1) /* special case: HWND_BOTTOM */
179 previous
= parent
->last_child
;
180 if (previous
== win
) return; /* nothing to do */
184 if (!(previous
= get_window( req
->previous
))) return;
185 /* previous must be a child of parent, and not win itself */
186 if (previous
->parent
!= parent
|| previous
== win
)
188 set_error( STATUS_INVALID_PARAMETER
);
193 link_window( win
, parent
, previous
);
197 /* destroy a window */
198 DECL_HANDLER(destroy_window
)
200 struct window
*win
= get_window( req
->handle
);
203 if (win
!= top_window
) destroy_window( win
);
204 else set_error( STATUS_ACCESS_DENIED
);
209 /* get information from a window handle */
210 DECL_HANDLER(get_window_info
)
212 struct window
*win
= get_window( req
->handle
);
214 req
->full_handle
= 0;
215 req
->tid
= req
->pid
= 0;
218 req
->full_handle
= win
->handle
;
221 req
->tid
= get_thread_id( win
->thread
);
222 req
->pid
= get_process_id( win
->thread
->process
);
228 /* get a list of the window parents, up to the root of the tree */
229 DECL_HANDLER(get_window_parents
)
231 struct window
*ptr
, *win
= get_window( req
->handle
);
235 if (win
) for (ptr
= win
->parent
; ptr
; ptr
= ptr
->parent
) total
++;
238 len
= min( get_req_data_size(req
), total
* sizeof(user_handle_t
) );
239 set_req_data_size( req
, len
);
242 user_handle_t
*data
= get_req_data(req
);
243 for (ptr
= win
->parent
; ptr
&& len
; ptr
= ptr
->parent
, len
-= sizeof(*data
))
244 *data
++ = ptr
->handle
;
249 /* get a list of the window children */
250 DECL_HANDLER(get_window_children
)
252 struct window
*ptr
, *parent
= get_window( req
->parent
);
257 for (ptr
= parent
->first_child
, total
= 0; ptr
; ptr
= ptr
->next
) total
++;
260 len
= min( get_req_data_size(req
), total
* sizeof(user_handle_t
) );
261 set_req_data_size( req
, len
);
264 user_handle_t
*data
= get_req_data(req
);
265 for (ptr
= parent
->first_child
; ptr
&& len
; ptr
= ptr
->next
, len
-= sizeof(*data
))
266 *data
++ = ptr
->handle
;
271 /* get window tree information from a window handle */
272 DECL_HANDLER(get_window_tree
)
274 struct window
*win
= get_window( req
->handle
);
280 struct window
*parent
= win
->parent
;
281 req
->parent
= parent
->handle
;
282 req
->owner
= win
->owner
? win
->owner
->handle
: 0;
283 req
->next_sibling
= win
->next
? win
->next
->handle
: 0;
284 req
->prev_sibling
= win
->prev
? win
->prev
->handle
: 0;
285 req
->first_sibling
= parent
->first_child
? parent
->first_child
->handle
: 0;
286 req
->last_sibling
= parent
->last_child
? parent
->last_child
->handle
: 0;
292 req
->next_sibling
= 0;
293 req
->prev_sibling
= 0;
294 req
->first_sibling
= 0;
295 req
->last_sibling
= 0;
297 req
->first_child
= win
->first_child
? win
->first_child
->handle
: 0;
298 req
->last_child
= win
->last_child
? win
->last_child
->handle
: 0;