2 * Server-side window handling
4 * Copyright (C) 2001 Alexandre Julliard
15 /* a window property */
18 unsigned short type
; /* property type (see below) */
19 atom_t atom
; /* property atom */
20 handle_t handle
; /* property handle (user-defined storage) */
25 PROP_TYPE_FREE
, /* free entry */
26 PROP_TYPE_STRING
, /* atom that was originally a string */
27 PROP_TYPE_ATOM
/* plain atom */
33 struct window
*parent
; /* parent window */
34 struct window
*owner
; /* owner of this window */
35 struct window
*first_child
; /* first child in Z-order */
36 struct window
*last_child
; /* last child in Z-order */
37 struct window
*first_unlinked
; /* first child not linked in the Z-order list */
38 struct window
*next
; /* next window in Z-order */
39 struct window
*prev
; /* prev window in Z-order */
40 user_handle_t handle
; /* full handle for this window */
41 struct thread
*thread
; /* thread owning the window */
42 atom_t atom
; /* class atom */
43 rectangle_t window_rect
; /* window rectangle */
44 rectangle_t client_rect
; /* client rectangle */
45 unsigned int style
; /* window style */
46 unsigned int ex_style
; /* window extended style */
47 unsigned int id
; /* window id */
48 void* instance
; /* creator instance */
49 void* user_data
; /* user-specific data */
50 int prop_inuse
; /* number of in-use window properties */
51 int prop_alloc
; /* number of allocated window properties */
52 struct property
*properties
; /* window properties array */
55 static struct window
*top_window
; /* top-level (desktop) window */
58 /* retrieve a pointer to a window from its handle */
59 inline static struct window
*get_window( user_handle_t handle
)
61 struct window
*ret
= get_user_object( handle
, USER_WINDOW
);
62 if (!ret
) set_error( STATUS_INVALID_HANDLE
);
66 /* unlink a window from the tree */
67 static void unlink_window( struct window
*win
)
69 struct window
*parent
= win
->parent
;
73 if (win
->next
) win
->next
->prev
= win
->prev
;
74 else if (parent
->last_child
== win
) parent
->last_child
= win
->prev
;
76 if (win
->prev
) win
->prev
->next
= win
->next
;
77 else if (parent
->first_child
== win
) parent
->first_child
= win
->next
;
78 else if (parent
->first_unlinked
== win
) parent
->first_unlinked
= win
->next
;
82 /* link a window into the tree (or unlink it if the new parent is NULL) */
83 static void link_window( struct window
*win
, struct window
*parent
, struct window
*previous
)
85 unlink_window( win
); /* unlink it from the previous location */
89 if (win
->parent
!= parent
)
91 win
->owner
= NULL
; /* reset owner if changing parent */
94 if ((win
->prev
= previous
))
96 if ((win
->next
= previous
->next
)) win
->next
->prev
= win
;
97 else if (win
->parent
->last_child
== previous
) win
->parent
->last_child
= win
;
98 win
->prev
->next
= win
;
102 if ((win
->next
= parent
->first_child
)) win
->next
->prev
= win
;
103 else win
->parent
->last_child
= win
;
104 parent
->first_child
= win
;
107 else /* move it to parent unlinked list */
109 parent
= win
->parent
;
110 if ((win
->next
= parent
->first_unlinked
)) win
->next
->prev
= win
;
112 parent
->first_unlinked
= win
;
116 /* set a window property */
117 static void set_property( struct window
*win
, atom_t atom
, handle_t handle
,
118 enum property_type type
)
121 struct property
*new_props
;
123 /* check if it exists already */
124 for (i
= 0; i
< win
->prop_inuse
; i
++)
126 if (win
->properties
[i
].type
== PROP_TYPE_FREE
)
131 if (win
->properties
[i
].atom
== atom
)
133 win
->properties
[i
].type
= type
;
134 win
->properties
[i
].handle
= handle
;
139 /* need to add an entry */
140 if (!grab_global_atom( atom
)) return;
144 if (win
->prop_inuse
>= win
->prop_alloc
)
146 /* need to grow the array */
147 if (!(new_props
= realloc( win
->properties
,
148 sizeof(*new_props
) * (win
->prop_alloc
+ 16) )))
150 set_error( STATUS_NO_MEMORY
);
151 release_global_atom( atom
);
154 win
->prop_alloc
+= 16;
155 win
->properties
= new_props
;
157 free
= win
->prop_inuse
++;
159 win
->properties
[free
].atom
= atom
;
160 win
->properties
[free
].type
= type
;
161 win
->properties
[free
].handle
= handle
;
164 /* remove a window property */
165 static handle_t
remove_property( struct window
*win
, atom_t atom
)
169 for (i
= 0; i
< win
->prop_inuse
; i
++)
171 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
172 if (win
->properties
[i
].atom
== atom
)
174 release_global_atom( atom
);
175 win
->properties
[i
].type
= PROP_TYPE_FREE
;
176 return win
->properties
[i
].handle
;
179 /* FIXME: last error? */
183 /* find a window property */
184 static handle_t
get_property( struct window
*win
, atom_t atom
)
188 for (i
= 0; i
< win
->prop_inuse
; i
++)
190 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
191 if (win
->properties
[i
].atom
== atom
) return win
->properties
[i
].handle
;
193 /* FIXME: last error? */
197 /* destroy all properties of a window */
198 inline static void destroy_properties( struct window
*win
)
202 if (!win
->properties
) return;
203 for (i
= 0; i
< win
->prop_inuse
; i
++)
205 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
206 release_global_atom( win
->properties
[i
].atom
);
208 free( win
->properties
);
211 /* enum all properties into the data array */
212 static int enum_properties( struct window
*win
, property_data_t
*data
, int max
)
216 for (i
= count
= 0; i
< win
->prop_inuse
&& count
< max
; i
++)
218 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
219 data
->atom
= win
->properties
[i
].atom
;
220 data
->string
= (win
->properties
[i
].type
== PROP_TYPE_STRING
);
221 data
->handle
= win
->properties
[i
].handle
;
228 /* destroy a window */
229 static void destroy_window( struct window
*win
)
231 assert( win
!= top_window
);
233 /* destroy all children */
234 while (win
->first_child
) destroy_window( win
->first_child
);
235 while (win
->first_unlinked
) destroy_window( win
->first_unlinked
);
237 /* reset siblings owner */
241 for (ptr
= win
->parent
->first_child
; ptr
; ptr
= ptr
->next
)
242 if (ptr
->owner
== win
) ptr
->owner
= NULL
;
243 for (ptr
= win
->parent
->first_unlinked
; ptr
; ptr
= ptr
->next
)
244 if (ptr
->owner
== win
) ptr
->owner
= NULL
;
247 if (win
->thread
->queue
) queue_cleanup_window( win
->thread
, win
->handle
);
248 free_user_handle( win
->handle
);
249 destroy_properties( win
);
250 unlink_window( win
);
251 memset( win
, 0x55, sizeof(*win
) );
255 /* create a new window structure (note: the window is not linked in the window tree) */
256 static struct window
*create_window( struct window
*parent
, struct window
*owner
, atom_t atom
)
258 struct window
*win
= mem_alloc( sizeof(*win
) );
259 if (!win
) return NULL
;
261 if (!(win
->handle
= alloc_user_handle( win
, USER_WINDOW
)))
266 win
->parent
= parent
;
268 win
->first_child
= NULL
;
269 win
->last_child
= NULL
;
270 win
->first_unlinked
= NULL
;
271 win
->thread
= current
;
276 win
->instance
= NULL
;
277 win
->user_data
= NULL
;
280 win
->properties
= NULL
;
282 if (parent
) /* put it on parent unlinked list */
284 if ((win
->next
= parent
->first_unlinked
)) win
->next
->prev
= win
;
286 parent
->first_unlinked
= win
;
288 else win
->next
= win
->prev
= NULL
;
293 /* destroy all windows belonging to a given thread */
294 void destroy_thread_windows( struct thread
*thread
)
296 user_handle_t handle
= 0;
299 while ((win
= next_user_handle( &handle
, USER_WINDOW
)))
301 if (win
->thread
!= thread
) continue;
302 destroy_window( win
);
306 /* check whether child is a descendant of parent */
307 int is_child_window( user_handle_t parent
, user_handle_t child
)
309 struct window
*child_ptr
= get_user_object( child
, USER_WINDOW
);
310 struct window
*parent_ptr
= get_user_object( parent
, USER_WINDOW
);
312 if (!child_ptr
|| !parent_ptr
) return 0;
313 while (child_ptr
->parent
)
315 if (child_ptr
->parent
== parent_ptr
) return 1;
316 child_ptr
= child_ptr
->parent
;
321 /* create a window */
322 DECL_HANDLER(create_window
)
325 if (!req
->parent
) /* return desktop window */
329 if (!(top_window
= create_window( NULL
, NULL
, req
->atom
))) return;
330 top_window
->thread
= NULL
; /* no thread owns the desktop */
332 req
->handle
= top_window
->handle
;
336 struct window
*win
, *parent
, *owner
= NULL
;
338 if (!(parent
= get_window( req
->parent
))) return;
339 if (req
->owner
&& !(owner
= get_window( req
->owner
))) return;
340 if (owner
&& owner
->parent
!= parent
)
342 /* owner must be a sibling of the new window */
343 set_error( STATUS_ACCESS_DENIED
);
346 if (!(win
= create_window( parent
, owner
, req
->atom
))) return;
347 req
->handle
= win
->handle
;
352 /* link a window into the tree */
353 DECL_HANDLER(link_window
)
355 struct window
*win
, *parent
= NULL
, *previous
= NULL
;
357 if (!(win
= get_window( req
->handle
))) return;
358 if (req
->parent
&& !(parent
= get_window( req
->parent
))) return;
360 if (win
== top_window
)
362 set_error( STATUS_INVALID_PARAMETER
);
365 req
->full_parent
= parent
? parent
->handle
: 0;
366 if (parent
&& req
->previous
)
368 if (req
->previous
== (user_handle_t
)1) /* special case: HWND_BOTTOM */
370 previous
= parent
->last_child
;
371 if (previous
== win
) return; /* nothing to do */
375 if (!(previous
= get_window( req
->previous
))) return;
376 /* previous must be a child of parent, and not win itself */
377 if (previous
->parent
!= parent
|| previous
== win
)
379 set_error( STATUS_INVALID_PARAMETER
);
384 link_window( win
, parent
, previous
);
388 /* destroy a window */
389 DECL_HANDLER(destroy_window
)
391 struct window
*win
= get_window( req
->handle
);
394 if (win
!= top_window
) destroy_window( win
);
395 else set_error( STATUS_ACCESS_DENIED
);
400 /* set a window owner */
401 DECL_HANDLER(set_window_owner
)
403 struct window
*win
= get_window( req
->handle
);
404 struct window
*owner
= get_window( req
->owner
);
406 if (!win
|| !owner
) return;
407 if (owner
->parent
!= win
->parent
)
409 /* owner has to be a sibling of window */
410 set_error( STATUS_ACCESS_DENIED
);
414 req
->full_owner
= owner
->handle
;
418 /* get information from a window handle */
419 DECL_HANDLER(get_window_info
)
421 struct window
*win
= get_window( req
->handle
);
423 req
->full_handle
= 0;
424 req
->tid
= req
->pid
= 0;
427 req
->full_handle
= win
->handle
;
430 req
->tid
= get_thread_id( win
->thread
);
431 req
->pid
= get_process_id( win
->thread
->process
);
432 req
->atom
= win
->atom
;
438 /* set some information in a window */
439 DECL_HANDLER(set_window_info
)
441 struct window
*win
= get_window( req
->handle
);
443 req
->old_style
= win
->style
;
444 req
->old_ex_style
= win
->ex_style
;
445 req
->old_id
= win
->id
;
446 req
->old_instance
= win
->instance
;
447 req
->old_user_data
= win
->user_data
;
448 if (req
->flags
& SET_WIN_STYLE
) win
->style
= req
->style
;
449 if (req
->flags
& SET_WIN_EXSTYLE
) win
->ex_style
= req
->ex_style
;
450 if (req
->flags
& SET_WIN_ID
) win
->id
= req
->id
;
451 if (req
->flags
& SET_WIN_INSTANCE
) win
->instance
= req
->instance
;
452 if (req
->flags
& SET_WIN_USERDATA
) win
->user_data
= req
->user_data
;
456 /* get a list of the window parents, up to the root of the tree */
457 DECL_HANDLER(get_window_parents
)
459 struct window
*ptr
, *win
= get_window( req
->handle
);
463 if (win
) for (ptr
= win
->parent
; ptr
; ptr
= ptr
->parent
) total
++;
466 len
= min( get_req_data_size(req
), total
* sizeof(user_handle_t
) );
467 set_req_data_size( req
, len
);
470 user_handle_t
*data
= get_req_data(req
);
471 for (ptr
= win
->parent
; ptr
&& len
; ptr
= ptr
->parent
, len
-= sizeof(*data
))
472 *data
++ = ptr
->handle
;
477 /* get a list of the window children */
478 DECL_HANDLER(get_window_children
)
480 struct window
*ptr
, *parent
= get_window( req
->parent
);
485 for (ptr
= parent
->first_child
, total
= 0; ptr
; ptr
= ptr
->next
)
487 if (req
->atom
&& ptr
->atom
!= req
->atom
) continue;
488 if (req
->tid
&& get_thread_id(ptr
->thread
) != req
->tid
) continue;
493 len
= min( get_req_data_size(req
), total
* sizeof(user_handle_t
) );
494 set_req_data_size( req
, len
);
497 user_handle_t
*data
= get_req_data(req
);
498 for (ptr
= parent
->first_child
; ptr
&& len
; ptr
= ptr
->next
, len
-= sizeof(*data
))
500 if (req
->atom
&& ptr
->atom
!= req
->atom
) continue;
501 if (req
->tid
&& get_thread_id(ptr
->thread
) != req
->tid
) continue;
502 *data
++ = ptr
->handle
;
508 /* get window tree information from a window handle */
509 DECL_HANDLER(get_window_tree
)
511 struct window
*win
= get_window( req
->handle
);
517 struct window
*parent
= win
->parent
;
518 req
->parent
= parent
->handle
;
519 req
->owner
= win
->owner
? win
->owner
->handle
: 0;
520 req
->next_sibling
= win
->next
? win
->next
->handle
: 0;
521 req
->prev_sibling
= win
->prev
? win
->prev
->handle
: 0;
522 req
->first_sibling
= parent
->first_child
? parent
->first_child
->handle
: 0;
523 req
->last_sibling
= parent
->last_child
? parent
->last_child
->handle
: 0;
529 req
->next_sibling
= 0;
530 req
->prev_sibling
= 0;
531 req
->first_sibling
= 0;
532 req
->last_sibling
= 0;
534 req
->first_child
= win
->first_child
? win
->first_child
->handle
: 0;
535 req
->last_child
= win
->last_child
? win
->last_child
->handle
: 0;
539 /* set the window and client rectangles of a window */
540 DECL_HANDLER(set_window_rectangles
)
542 struct window
*win
= get_window( req
->handle
);
546 win
->window_rect
= req
->window
;
547 win
->client_rect
= req
->client
;
552 /* get the window and client rectangles of a window */
553 DECL_HANDLER(get_window_rectangles
)
555 struct window
*win
= get_window( req
->handle
);
559 req
->window
= win
->window_rect
;
560 req
->client
= win
->client_rect
;
565 /* get the coordinates offset between two windows */
566 DECL_HANDLER(get_windows_offset
)
573 if (!(win
= get_window( req
->from
))) return;
576 req
->x
+= win
->client_rect
.left
;
577 req
->y
+= win
->client_rect
.top
;
583 if (!(win
= get_window( req
->to
))) return;
586 req
->x
-= win
->client_rect
.left
;
587 req
->y
-= win
->client_rect
.top
;
594 /* set a window property */
595 DECL_HANDLER(set_window_property
)
597 struct window
*win
= get_window( req
->window
);
599 if (win
) set_property( win
, req
->atom
, req
->handle
,
600 req
->string
? PROP_TYPE_STRING
: PROP_TYPE_ATOM
);
604 /* remove a window property */
605 DECL_HANDLER(remove_window_property
)
607 struct window
*win
= get_window( req
->window
);
609 if (win
) req
->handle
= remove_property( win
, req
->atom
);
613 /* get a window property */
614 DECL_HANDLER(get_window_property
)
616 struct window
*win
= get_window( req
->window
);
618 if (win
) req
->handle
= get_property( win
, req
->atom
);
622 /* get the list of properties of a window */
623 DECL_HANDLER(get_window_properties
)
626 property_data_t
*data
= get_req_data(req
);
627 struct window
*win
= get_window( req
->window
);
629 if (win
) count
= enum_properties( win
, data
, get_req_data_size(req
) / sizeof(*data
) );
630 set_req_data_size( req
, count
* sizeof(*data
) );