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
== top_window
) owner
= NULL
;
341 else if (owner
&& owner
->parent
!= parent
)
343 /* owner must be a sibling of the new window */
344 set_error( STATUS_ACCESS_DENIED
);
347 if (!(win
= create_window( parent
, owner
, req
->atom
))) return;
348 req
->handle
= win
->handle
;
353 /* link a window into the tree */
354 DECL_HANDLER(link_window
)
356 struct window
*win
, *parent
= NULL
, *previous
= NULL
;
358 if (!(win
= get_window( req
->handle
))) return;
359 if (req
->parent
&& !(parent
= get_window( req
->parent
))) return;
361 if (win
== top_window
)
363 set_error( STATUS_INVALID_PARAMETER
);
366 req
->full_parent
= parent
? parent
->handle
: 0;
367 if (parent
&& req
->previous
)
369 if (req
->previous
== (user_handle_t
)1) /* special case: HWND_BOTTOM */
371 previous
= parent
->last_child
;
372 if (previous
== win
) return; /* nothing to do */
376 if (!(previous
= get_window( req
->previous
))) return;
377 /* previous must be a child of parent, and not win itself */
378 if (previous
->parent
!= parent
|| previous
== win
)
380 set_error( STATUS_INVALID_PARAMETER
);
385 link_window( win
, parent
, previous
);
389 /* destroy a window */
390 DECL_HANDLER(destroy_window
)
392 struct window
*win
= get_window( req
->handle
);
395 if (win
!= top_window
) destroy_window( win
);
396 else set_error( STATUS_ACCESS_DENIED
);
401 /* set a window owner */
402 DECL_HANDLER(set_window_owner
)
404 struct window
*win
= get_window( req
->handle
);
405 struct window
*owner
= get_window( req
->owner
);
407 if (!win
|| !owner
) return;
408 if (owner
->parent
!= win
->parent
)
410 /* owner has to be a sibling of window */
411 set_error( STATUS_ACCESS_DENIED
);
415 req
->full_owner
= owner
->handle
;
419 /* get information from a window handle */
420 DECL_HANDLER(get_window_info
)
422 struct window
*win
= get_window( req
->handle
);
424 req
->full_handle
= 0;
425 req
->tid
= req
->pid
= 0;
428 req
->full_handle
= win
->handle
;
431 req
->tid
= get_thread_id( win
->thread
);
432 req
->pid
= get_process_id( win
->thread
->process
);
433 req
->atom
= win
->atom
;
439 /* set some information in a window */
440 DECL_HANDLER(set_window_info
)
442 struct window
*win
= get_window( req
->handle
);
444 req
->old_style
= win
->style
;
445 req
->old_ex_style
= win
->ex_style
;
446 req
->old_id
= win
->id
;
447 req
->old_instance
= win
->instance
;
448 req
->old_user_data
= win
->user_data
;
449 if (req
->flags
& SET_WIN_STYLE
) win
->style
= req
->style
;
450 if (req
->flags
& SET_WIN_EXSTYLE
) win
->ex_style
= req
->ex_style
;
451 if (req
->flags
& SET_WIN_ID
) win
->id
= req
->id
;
452 if (req
->flags
& SET_WIN_INSTANCE
) win
->instance
= req
->instance
;
453 if (req
->flags
& SET_WIN_USERDATA
) win
->user_data
= req
->user_data
;
457 /* get a list of the window parents, up to the root of the tree */
458 DECL_HANDLER(get_window_parents
)
460 struct window
*ptr
, *win
= get_window( req
->handle
);
464 if (win
) for (ptr
= win
->parent
; ptr
; ptr
= ptr
->parent
) total
++;
467 len
= min( get_req_data_size(req
), total
* sizeof(user_handle_t
) );
468 set_req_data_size( req
, len
);
471 user_handle_t
*data
= get_req_data(req
);
472 for (ptr
= win
->parent
; ptr
&& len
; ptr
= ptr
->parent
, len
-= sizeof(*data
))
473 *data
++ = ptr
->handle
;
478 /* get a list of the window children */
479 DECL_HANDLER(get_window_children
)
481 struct window
*ptr
, *parent
= get_window( req
->parent
);
486 for (ptr
= parent
->first_child
, total
= 0; ptr
; ptr
= ptr
->next
)
488 if (req
->atom
&& ptr
->atom
!= req
->atom
) continue;
489 if (req
->tid
&& get_thread_id(ptr
->thread
) != req
->tid
) continue;
494 len
= min( get_req_data_size(req
), total
* sizeof(user_handle_t
) );
495 set_req_data_size( req
, len
);
498 user_handle_t
*data
= get_req_data(req
);
499 for (ptr
= parent
->first_child
; ptr
&& len
; ptr
= ptr
->next
, len
-= sizeof(*data
))
501 if (req
->atom
&& ptr
->atom
!= req
->atom
) continue;
502 if (req
->tid
&& get_thread_id(ptr
->thread
) != req
->tid
) continue;
503 *data
++ = ptr
->handle
;
509 /* get window tree information from a window handle */
510 DECL_HANDLER(get_window_tree
)
512 struct window
*win
= get_window( req
->handle
);
518 struct window
*parent
= win
->parent
;
519 req
->parent
= parent
->handle
;
520 req
->owner
= win
->owner
? win
->owner
->handle
: 0;
521 req
->next_sibling
= win
->next
? win
->next
->handle
: 0;
522 req
->prev_sibling
= win
->prev
? win
->prev
->handle
: 0;
523 req
->first_sibling
= parent
->first_child
? parent
->first_child
->handle
: 0;
524 req
->last_sibling
= parent
->last_child
? parent
->last_child
->handle
: 0;
530 req
->next_sibling
= 0;
531 req
->prev_sibling
= 0;
532 req
->first_sibling
= 0;
533 req
->last_sibling
= 0;
535 req
->first_child
= win
->first_child
? win
->first_child
->handle
: 0;
536 req
->last_child
= win
->last_child
? win
->last_child
->handle
: 0;
540 /* set the window and client rectangles of a window */
541 DECL_HANDLER(set_window_rectangles
)
543 struct window
*win
= get_window( req
->handle
);
547 win
->window_rect
= req
->window
;
548 win
->client_rect
= req
->client
;
553 /* get the window and client rectangles of a window */
554 DECL_HANDLER(get_window_rectangles
)
556 struct window
*win
= get_window( req
->handle
);
560 req
->window
= win
->window_rect
;
561 req
->client
= win
->client_rect
;
566 /* get the coordinates offset between two windows */
567 DECL_HANDLER(get_windows_offset
)
574 if (!(win
= get_window( req
->from
))) return;
577 req
->x
+= win
->client_rect
.left
;
578 req
->y
+= win
->client_rect
.top
;
584 if (!(win
= get_window( req
->to
))) return;
587 req
->x
-= win
->client_rect
.left
;
588 req
->y
-= win
->client_rect
.top
;
595 /* set a window property */
596 DECL_HANDLER(set_window_property
)
598 struct window
*win
= get_window( req
->window
);
600 if (win
) set_property( win
, req
->atom
, req
->handle
,
601 req
->string
? PROP_TYPE_STRING
: PROP_TYPE_ATOM
);
605 /* remove a window property */
606 DECL_HANDLER(remove_window_property
)
608 struct window
*win
= get_window( req
->window
);
610 if (win
) req
->handle
= remove_property( win
, req
->atom
);
614 /* get a window property */
615 DECL_HANDLER(get_window_property
)
617 struct window
*win
= get_window( req
->window
);
619 if (win
) req
->handle
= get_property( win
, req
->atom
);
623 /* get the list of properties of a window */
624 DECL_HANDLER(get_window_properties
)
627 property_data_t
*data
= get_req_data(req
);
628 struct window
*win
= get_window( req
->window
);
630 if (win
) count
= enum_properties( win
, data
, get_req_data_size(req
) / sizeof(*data
) );
631 set_req_data_size( req
, count
* sizeof(*data
) );