2 * Server-side window handling
4 * Copyright (C) 2001 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
39 /* a window property */
42 unsigned short type
; /* property type (see below) */
43 atom_t atom
; /* property atom */
44 obj_handle_t handle
; /* property handle (user-defined storage) */
49 PROP_TYPE_FREE
, /* free entry */
50 PROP_TYPE_STRING
, /* atom that was originally a string */
51 PROP_TYPE_ATOM
/* plain atom */
57 struct window
*parent
; /* parent window */
58 user_handle_t owner
; /* owner of this window */
59 struct window
*first_child
; /* first child in Z-order */
60 struct window
*last_child
; /* last child in Z-order */
61 struct window
*first_unlinked
; /* first child not linked in the Z-order list */
62 struct window
*next
; /* next window in Z-order */
63 struct window
*prev
; /* prev window in Z-order */
64 user_handle_t handle
; /* full handle for this window */
65 struct thread
*thread
; /* thread owning the window */
66 struct window_class
*class; /* window class */
67 atom_t atom
; /* class atom */
68 user_handle_t last_active
; /* last active popup */
69 rectangle_t window_rect
; /* window rectangle (relative to parent client area) */
70 rectangle_t client_rect
; /* client rectangle (relative to parent client area) */
71 struct region
*win_region
; /* region for shaped windows (relative to window rect) */
72 unsigned int style
; /* window style */
73 unsigned int ex_style
; /* window extended style */
74 unsigned int id
; /* window id */
75 void* instance
; /* creator instance */
76 void* user_data
; /* user-specific data */
77 WCHAR
*text
; /* window caption text */
78 int paint_count
; /* count of pending paints for this window */
79 int prop_inuse
; /* number of in-use window properties */
80 int prop_alloc
; /* number of allocated window properties */
81 struct property
*properties
; /* window properties array */
82 int nb_extra_bytes
; /* number of extra bytes */
83 char extra_bytes
[1]; /* extra bytes storage */
86 /* growable array of user handles */
87 struct user_handle_array
89 user_handle_t
*handles
;
94 static struct window
*top_window
; /* top-level (desktop) window */
96 /* global window pointers */
97 static struct window
*shell_window
;
98 static struct window
*shell_listview
;
99 static struct window
*progman_window
;
100 static struct window
*taskman_window
;
102 /* retrieve a pointer to a window from its handle */
103 inline static struct window
*get_window( user_handle_t handle
)
105 struct window
*ret
= get_user_object( handle
, USER_WINDOW
);
106 if (!ret
) set_error( STATUS_INVALID_HANDLE
);
110 /* unlink a window from the tree */
111 static void unlink_window( struct window
*win
)
113 struct window
*parent
= win
->parent
;
117 if (win
->next
) win
->next
->prev
= win
->prev
;
118 else if (parent
->last_child
== win
) parent
->last_child
= win
->prev
;
120 if (win
->prev
) win
->prev
->next
= win
->next
;
121 else if (parent
->first_child
== win
) parent
->first_child
= win
->next
;
122 else if (parent
->first_unlinked
== win
) parent
->first_unlinked
= win
->next
;
126 /* link a window into the tree (or unlink it if the new parent is NULL) */
127 static void link_window( struct window
*win
, struct window
*parent
, struct window
*previous
)
129 unlink_window( win
); /* unlink it from the previous location */
133 win
->parent
= parent
;
134 if ((win
->prev
= previous
))
136 if ((win
->next
= previous
->next
)) win
->next
->prev
= win
;
137 else if (win
->parent
->last_child
== previous
) win
->parent
->last_child
= win
;
138 win
->prev
->next
= win
;
142 if ((win
->next
= parent
->first_child
)) win
->next
->prev
= win
;
143 else win
->parent
->last_child
= win
;
144 parent
->first_child
= win
;
147 else /* move it to parent unlinked list */
149 parent
= win
->parent
;
150 if ((win
->next
= parent
->first_unlinked
)) win
->next
->prev
= win
;
152 parent
->first_unlinked
= win
;
156 /* append a user handle to a handle array */
157 static int add_handle_to_array( struct user_handle_array
*array
, user_handle_t handle
)
159 if (array
->count
>= array
->total
)
161 int new_total
= max( array
->total
* 2, 32 );
162 user_handle_t
*new_array
= realloc( array
->handles
, new_total
* sizeof(*new_array
) );
165 free( array
->handles
);
166 set_error( STATUS_NO_MEMORY
);
169 array
->handles
= new_array
;
170 array
->total
= new_total
;
172 array
->handles
[array
->count
++] = handle
;
176 /* set a window property */
177 static void set_property( struct window
*win
, atom_t atom
, obj_handle_t handle
,
178 enum property_type type
)
181 struct property
*new_props
;
183 /* check if it exists already */
184 for (i
= 0; i
< win
->prop_inuse
; i
++)
186 if (win
->properties
[i
].type
== PROP_TYPE_FREE
)
191 if (win
->properties
[i
].atom
== atom
)
193 win
->properties
[i
].type
= type
;
194 win
->properties
[i
].handle
= handle
;
199 /* need to add an entry */
200 if (!grab_global_atom( atom
)) return;
204 if (win
->prop_inuse
>= win
->prop_alloc
)
206 /* need to grow the array */
207 if (!(new_props
= realloc( win
->properties
,
208 sizeof(*new_props
) * (win
->prop_alloc
+ 16) )))
210 set_error( STATUS_NO_MEMORY
);
211 release_global_atom( atom
);
214 win
->prop_alloc
+= 16;
215 win
->properties
= new_props
;
217 free
= win
->prop_inuse
++;
219 win
->properties
[free
].atom
= atom
;
220 win
->properties
[free
].type
= type
;
221 win
->properties
[free
].handle
= handle
;
224 /* remove a window property */
225 static obj_handle_t
remove_property( struct window
*win
, atom_t atom
)
229 for (i
= 0; i
< win
->prop_inuse
; i
++)
231 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
232 if (win
->properties
[i
].atom
== atom
)
234 release_global_atom( atom
);
235 win
->properties
[i
].type
= PROP_TYPE_FREE
;
236 return win
->properties
[i
].handle
;
239 /* FIXME: last error? */
243 /* find a window property */
244 static obj_handle_t
get_property( struct window
*win
, atom_t atom
)
248 for (i
= 0; i
< win
->prop_inuse
; i
++)
250 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
251 if (win
->properties
[i
].atom
== atom
) return win
->properties
[i
].handle
;
253 /* FIXME: last error? */
257 /* destroy all properties of a window */
258 inline static void destroy_properties( struct window
*win
)
262 if (!win
->properties
) return;
263 for (i
= 0; i
< win
->prop_inuse
; i
++)
265 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
266 release_global_atom( win
->properties
[i
].atom
);
268 free( win
->properties
);
271 /* destroy a window */
272 static void destroy_window( struct window
*win
)
274 assert( win
!= top_window
);
276 /* destroy all children */
277 while (win
->first_child
) destroy_window( win
->first_child
);
278 while (win
->first_unlinked
) destroy_window( win
->first_unlinked
);
280 if (win
->thread
->queue
)
282 if (win
->paint_count
) inc_queue_paint_count( win
->thread
, -win
->paint_count
);
283 queue_cleanup_window( win
->thread
, win
->handle
);
285 /* reset global window pointers, if the corresponding window is destroyed */
286 if (win
== shell_window
) shell_window
= NULL
;
287 if (win
== shell_listview
) shell_listview
= NULL
;
288 if (win
== progman_window
) progman_window
= NULL
;
289 if (win
== taskman_window
) taskman_window
= NULL
;
290 free_user_handle( win
->handle
);
291 destroy_properties( win
);
292 unlink_window( win
);
293 if (win
->win_region
) free_region( win
->win_region
);
294 release_class( win
->class );
295 if (win
->text
) free( win
->text
);
296 memset( win
, 0x55, sizeof(*win
) );
300 /* create a new window structure (note: the window is not linked in the window tree) */
301 static struct window
*create_window( struct window
*parent
, struct window
*owner
,
302 atom_t atom
, void *instance
)
306 struct window_class
*class = grab_class( current
->process
, atom
, instance
, &extra_bytes
);
308 if (!class) return NULL
;
310 win
= mem_alloc( sizeof(*win
) + extra_bytes
- 1 );
313 release_class( class );
317 if (!(win
->handle
= alloc_user_handle( win
, USER_WINDOW
)))
319 release_class( class );
323 win
->parent
= parent
;
324 win
->owner
= owner
? owner
->handle
: 0;
325 win
->first_child
= NULL
;
326 win
->last_child
= NULL
;
327 win
->first_unlinked
= NULL
;
328 win
->thread
= current
;
331 win
->last_active
= win
->handle
;
332 win
->win_region
= NULL
;
336 win
->instance
= NULL
;
337 win
->user_data
= NULL
;
339 win
->paint_count
= 0;
342 win
->properties
= NULL
;
343 win
->nb_extra_bytes
= extra_bytes
;
344 memset( win
->extra_bytes
, 0, extra_bytes
);
346 if (parent
) /* put it on parent unlinked list */
348 if ((win
->next
= parent
->first_unlinked
)) win
->next
->prev
= win
;
350 parent
->first_unlinked
= win
;
352 else win
->next
= win
->prev
= NULL
;
354 /* if parent belongs to a different thread, attach the two threads */
355 if (parent
&& parent
->thread
&& parent
->thread
!= current
)
356 attach_thread_input( current
, parent
->thread
);
360 /* destroy all windows belonging to a given thread */
361 void destroy_thread_windows( struct thread
*thread
)
363 user_handle_t handle
= 0;
366 while ((win
= next_user_handle( &handle
, USER_WINDOW
)))
368 if (win
->thread
!= thread
) continue;
369 destroy_window( win
);
373 /* check whether child is a descendant of parent */
374 int is_child_window( user_handle_t parent
, user_handle_t child
)
376 struct window
*child_ptr
= get_user_object( child
, USER_WINDOW
);
377 struct window
*parent_ptr
= get_user_object( parent
, USER_WINDOW
);
379 if (!child_ptr
|| !parent_ptr
) return 0;
380 while (child_ptr
->parent
)
382 if (child_ptr
->parent
== parent_ptr
) return 1;
383 child_ptr
= child_ptr
->parent
;
388 /* check whether window is a top-level window */
389 int is_top_level_window( user_handle_t window
)
391 struct window
*win
= get_user_object( window
, USER_WINDOW
);
392 return (win
&& win
->parent
== top_window
);
395 /* make a window active if possible */
396 int make_window_active( user_handle_t window
)
398 struct window
*owner
, *win
= get_window( window
);
402 /* set last active for window and its owner */
403 win
->last_active
= win
->handle
;
404 if ((owner
= get_user_object( win
->owner
, USER_WINDOW
))) owner
->last_active
= win
->handle
;
408 /* check if window and all its ancestors are visible */
409 static int is_visible( const struct window
*win
)
411 while (win
&& win
!= top_window
)
413 if (!(win
->style
& WS_VISIBLE
)) return 0;
415 /* if parent is minimized children are not visible */
416 if (win
&& (win
->style
& WS_MINIMIZE
)) return 0;
421 /* same as is_visible but takes a window handle */
422 int is_window_visible( user_handle_t window
)
424 struct window
*win
= get_user_object( window
, USER_WINDOW
);
426 return is_visible( win
);
429 /* check if point is inside the window */
430 static inline int is_point_in_window( struct window
*win
, int x
, int y
)
432 if (!(win
->style
& WS_VISIBLE
)) return 0; /* not visible */
433 if ((win
->style
& (WS_POPUP
|WS_CHILD
|WS_DISABLED
)) == (WS_CHILD
|WS_DISABLED
))
434 return 0; /* disabled child */
435 if ((win
->ex_style
& (WS_EX_LAYERED
|WS_EX_TRANSPARENT
)) == (WS_EX_LAYERED
|WS_EX_TRANSPARENT
))
436 return 0; /* transparent */
437 if (x
< win
->window_rect
.left
|| x
>= win
->window_rect
.right
||
438 y
< win
->window_rect
.top
|| y
>= win
->window_rect
.bottom
)
439 return 0; /* not in window */
440 if (win
->win_region
&&
441 !point_in_region( win
->win_region
, x
- win
->window_rect
.left
, y
- win
->window_rect
.top
))
442 return 0; /* not in window region */
446 /* find child of 'parent' that contains the given point (in parent-relative coords) */
447 static struct window
*child_window_from_point( struct window
*parent
, int x
, int y
)
451 for (ptr
= parent
->first_child
; ptr
; ptr
= ptr
->next
)
453 if (!is_point_in_window( ptr
, x
, y
)) continue; /* skip it */
455 /* if window is minimized or disabled, return at once */
456 if (ptr
->style
& (WS_MINIMIZE
|WS_DISABLED
)) return ptr
;
458 /* if point is not in client area, return at once */
459 if (x
< ptr
->client_rect
.left
|| x
>= ptr
->client_rect
.right
||
460 y
< ptr
->client_rect
.top
|| y
>= ptr
->client_rect
.bottom
)
463 return child_window_from_point( ptr
, x
- ptr
->client_rect
.left
, y
- ptr
->client_rect
.top
);
465 return parent
; /* not found any child */
468 /* find all children of 'parent' that contain the given point */
469 static int get_window_children_from_point( struct window
*parent
, int x
, int y
,
470 struct user_handle_array
*array
)
474 for (ptr
= parent
->first_child
; ptr
; ptr
= ptr
->next
)
476 if (!is_point_in_window( ptr
, x
, y
)) continue; /* skip it */
478 /* if point is in client area, and window is not minimized or disabled, check children */
479 if (!(ptr
->style
& (WS_MINIMIZE
|WS_DISABLED
)) &&
480 x
>= ptr
->client_rect
.left
&& x
< ptr
->client_rect
.right
&&
481 y
>= ptr
->client_rect
.top
&& y
< ptr
->client_rect
.bottom
)
483 if (!get_window_children_from_point( ptr
, x
- ptr
->client_rect
.left
,
484 y
- ptr
->client_rect
.top
, array
))
488 /* now add window to the array */
489 if (!add_handle_to_array( array
, ptr
->handle
)) return 0;
494 /* find window containing point (in absolute coords) */
495 user_handle_t
window_from_point( int x
, int y
)
499 if (!top_window
) return 0;
500 ret
= child_window_from_point( top_window
, x
, y
);
504 /* return list of all windows containing point (in absolute coords) */
505 static int all_windows_from_point( struct window
*top
, int x
, int y
, struct user_handle_array
*array
)
509 /* make point relative to top window */
510 for (ptr
= top
->parent
; ptr
&& ptr
!= top_window
; ptr
= ptr
->parent
)
512 x
-= ptr
->client_rect
.left
;
513 y
-= ptr
->client_rect
.top
;
516 if (!is_point_in_window( top
, x
, y
)) return 1;
518 /* if point is in client area, and window is not minimized or disabled, check children */
519 if (!(top
->style
& (WS_MINIMIZE
|WS_DISABLED
)) &&
520 x
>= top
->client_rect
.left
&& x
< top
->client_rect
.right
&&
521 y
>= top
->client_rect
.top
&& y
< top
->client_rect
.bottom
)
523 if (!get_window_children_from_point( top
, x
- top
->client_rect
.left
,
524 y
- top
->client_rect
.top
, array
))
527 /* now add window to the array */
528 if (!add_handle_to_array( array
, top
->handle
)) return 0;
533 /* return the thread owning a window */
534 struct thread
*get_window_thread( user_handle_t handle
)
536 struct window
*win
= get_user_object( handle
, USER_WINDOW
);
537 if (!win
|| !win
->thread
) return NULL
;
538 return (struct thread
*)grab_object( win
->thread
);
541 /* find a child of the specified window that needs repainting */
542 static struct window
*find_child_to_repaint( struct window
*parent
, struct thread
*thread
)
544 struct window
*ptr
, *ret
= NULL
;
546 for (ptr
= parent
->first_child
; ptr
&& !ret
; ptr
= ptr
->next
)
548 if (!(ptr
->style
& WS_VISIBLE
)) continue;
549 if (ptr
->paint_count
&& ptr
->thread
== thread
)
551 else /* explore its children */
552 ret
= find_child_to_repaint( ptr
, thread
);
555 if (ret
&& (ret
->ex_style
& WS_EX_TRANSPARENT
))
557 /* transparent window, check for non-transparent sibling to paint first */
558 for (ptr
= ret
->next
; ptr
; ptr
= ptr
->next
)
560 if (!(ptr
->style
& WS_VISIBLE
)) continue;
561 if (ptr
->ex_style
& WS_EX_TRANSPARENT
) continue;
562 if (ptr
->paint_count
&& ptr
->thread
== thread
) return ptr
;
569 /* find a window that needs repainting */
570 user_handle_t
find_window_to_repaint( user_handle_t parent
, struct thread
*thread
)
572 struct window
*win
= parent
? get_window( parent
) : top_window
;
574 if (!win
|| !(win
->style
& WS_VISIBLE
)) return 0;
575 if (!win
->paint_count
|| win
->thread
!= thread
)
576 win
= find_child_to_repaint( win
, thread
);
577 return win
? win
->handle
: 0;
581 /* intersect the window region with the specified region, relative to the window parent */
582 static struct region
*intersect_window_region( struct region
*region
, struct window
*win
)
584 /* make region relative to window rect */
585 offset_region( region
, -win
->window_rect
.left
, -win
->window_rect
.top
);
586 if (!intersect_region( region
, region
, win
->win_region
)) return NULL
;
587 /* make region relative to parent again */
588 offset_region( region
, win
->window_rect
.left
, win
->window_rect
.top
);
593 /* clip all children of a given window out of the visible region */
594 static struct region
*clip_children( struct window
*parent
, struct window
*last
,
595 struct region
*region
, int offset_x
, int offset_y
)
598 struct region
*tmp
= create_empty_region();
600 if (!tmp
) return NULL
;
601 for (ptr
= parent
->first_child
; ptr
&& ptr
!= last
; ptr
= ptr
->next
)
603 if (!(ptr
->style
& WS_VISIBLE
)) continue;
604 if (ptr
->ex_style
& WS_EX_TRANSPARENT
) continue;
605 set_region_rect( tmp
, &ptr
->window_rect
);
606 if (ptr
->win_region
&& !intersect_window_region( tmp
, ptr
))
611 offset_region( tmp
, offset_x
, offset_y
);
612 if (!(region
= subtract_region( region
, region
, tmp
))) break;
613 if (is_region_empty( region
)) break;
620 /* compute the visible region of a window */
621 static struct region
*get_visible_region( struct window
*win
, struct window
*top
,
624 struct region
*tmp
, *region
;
625 int offset_x
, offset_y
;
627 if (!(region
= create_empty_region())) return NULL
;
629 /* first check if all ancestors are visible */
631 if (!is_visible( win
)) return region
; /* empty region */
633 /* create a region relative to the window itself */
635 if ((flags
& DCX_PARENTCLIP
) && win
!= top
&& win
->parent
)
638 rect
.left
= rect
.top
= 0;
639 rect
.right
= win
->parent
->client_rect
.right
- win
->parent
->client_rect
.left
;
640 rect
.bottom
= win
->parent
->client_rect
.bottom
- win
->parent
->client_rect
.top
;
641 set_region_rect( region
, &rect
);
642 offset_x
= win
->client_rect
.left
;
643 offset_y
= win
->client_rect
.top
;
645 else if (flags
& DCX_WINDOW
)
647 set_region_rect( region
, &win
->window_rect
);
648 if (win
->win_region
&& !intersect_window_region( region
, win
)) goto error
;
649 offset_x
= win
->window_rect
.left
;
650 offset_y
= win
->window_rect
.top
;
654 set_region_rect( region
, &win
->client_rect
);
655 if (win
->win_region
&& !intersect_window_region( region
, win
)) goto error
;
656 offset_x
= win
->client_rect
.left
;
657 offset_y
= win
->client_rect
.top
;
659 offset_region( region
, -offset_x
, -offset_y
);
663 if (flags
& DCX_CLIPCHILDREN
)
665 if (!clip_children( win
, NULL
, region
,
666 offset_x
- win
->client_rect
.left
,
667 offset_y
- win
->client_rect
.top
)) goto error
;
670 /* clip siblings of ancestors */
672 if (top
&& top
!= win
&& (tmp
= create_empty_region()) != NULL
)
674 offset_region( region
, offset_x
, offset_y
); /* make it relative to parent */
675 while (win
!= top
&& win
->parent
)
677 if (win
->style
& WS_CLIPSIBLINGS
)
679 if (!clip_children( win
->parent
, win
, region
, 0, 0 )) goto error
;
680 if (is_region_empty( region
)) break;
682 /* clip to parent client area */
684 offset_x
+= win
->client_rect
.left
;
685 offset_y
+= win
->client_rect
.top
;
686 offset_region( region
, win
->client_rect
.left
, win
->client_rect
.top
);
687 set_region_rect( tmp
, &win
->client_rect
);
688 if (win
->win_region
&& !intersect_window_region( tmp
, win
))
693 if (!intersect_region( region
, region
, tmp
))
698 if (is_region_empty( region
)) break;
700 offset_region( region
, -offset_x
, -offset_y
); /* make it relative to target window again */
706 free_region( region
);
711 /* get the window class of a window */
712 struct window_class
* get_window_class( user_handle_t window
)
715 if (!(win
= get_window( window
))) return NULL
;
720 /* create a window */
721 DECL_HANDLER(create_window
)
726 if (!req
->parent
) /* return desktop window */
730 if (!(top_window
= create_window( NULL
, NULL
, req
->atom
, req
->instance
))) return;
731 top_window
->thread
= NULL
; /* no thread owns the desktop */
732 top_window
->style
= WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
738 struct window
*parent
, *owner
= NULL
;
740 if (!(parent
= get_window( req
->parent
))) return;
741 if (req
->owner
&& !(owner
= get_window( req
->owner
))) return;
742 if (owner
== top_window
) owner
= NULL
;
743 else if (owner
&& parent
!= top_window
)
745 /* an owned window must be created as top-level */
746 set_error( STATUS_ACCESS_DENIED
);
749 if (!(win
= create_window( parent
, owner
, req
->atom
, req
->instance
))) return;
751 reply
->handle
= win
->handle
;
752 reply
->extra
= win
->nb_extra_bytes
;
753 reply
->class_ptr
= get_class_client_ptr( win
->class );
757 /* link a window into the tree */
758 DECL_HANDLER(link_window
)
760 struct window
*win
, *parent
= NULL
, *previous
= NULL
;
762 if (!(win
= get_window( req
->handle
))) return;
763 if (req
->parent
&& !(parent
= get_window( req
->parent
))) return;
765 if (win
== top_window
)
767 set_error( STATUS_INVALID_PARAMETER
);
770 reply
->full_parent
= parent
? parent
->handle
: 0;
771 if (parent
&& req
->previous
)
773 if (req
->previous
== (user_handle_t
)1) /* special case: HWND_BOTTOM */
775 previous
= parent
->last_child
;
776 if (previous
== win
) return; /* nothing to do */
780 if (!(previous
= get_window( req
->previous
))) return;
781 /* previous must be a child of parent, and not win itself */
782 if (previous
->parent
!= parent
|| previous
== win
)
784 set_error( STATUS_INVALID_PARAMETER
);
789 link_window( win
, parent
, previous
);
793 /* destroy a window */
794 DECL_HANDLER(destroy_window
)
796 struct window
*win
= get_window( req
->handle
);
799 if (win
!= top_window
) destroy_window( win
);
800 else set_error( STATUS_ACCESS_DENIED
);
805 /* set a window owner */
806 DECL_HANDLER(set_window_owner
)
808 struct window
*win
= get_window( req
->handle
);
809 struct window
*owner
= NULL
;
812 if (req
->owner
&& !(owner
= get_window( req
->owner
))) return;
813 if (win
== top_window
)
815 set_error( STATUS_ACCESS_DENIED
);
818 reply
->prev_owner
= win
->owner
;
819 reply
->full_owner
= win
->owner
= owner
? owner
->handle
: 0;
823 /* get information from a window handle */
824 DECL_HANDLER(get_window_info
)
826 struct window
*win
= get_window( req
->handle
);
828 reply
->full_handle
= 0;
829 reply
->tid
= reply
->pid
= 0;
832 reply
->full_handle
= win
->handle
;
833 reply
->last_active
= win
->handle
;
834 if (get_user_object( win
->last_active
, USER_WINDOW
)) reply
->last_active
= win
->last_active
;
837 reply
->tid
= get_thread_id( win
->thread
);
838 reply
->pid
= get_process_id( win
->thread
->process
);
839 reply
->atom
= get_class_atom( win
->class );
845 /* set some information in a window */
846 DECL_HANDLER(set_window_info
)
848 struct window
*win
= get_window( req
->handle
);
851 if (req
->flags
&& win
== top_window
)
853 set_error( STATUS_ACCESS_DENIED
);
856 if (req
->extra_size
> sizeof(req
->extra_value
) ||
857 req
->extra_offset
< -1 ||
858 req
->extra_offset
> win
->nb_extra_bytes
- (int)req
->extra_size
)
860 set_win32_error( ERROR_INVALID_INDEX
);
863 if (req
->extra_offset
!= -1)
865 memcpy( &reply
->old_extra_value
, win
->extra_bytes
+ req
->extra_offset
, req
->extra_size
);
867 else if (req
->flags
& SET_WIN_EXTRA
)
869 set_win32_error( ERROR_INVALID_INDEX
);
872 reply
->old_style
= win
->style
;
873 reply
->old_ex_style
= win
->ex_style
;
874 reply
->old_id
= win
->id
;
875 reply
->old_instance
= win
->instance
;
876 reply
->old_user_data
= win
->user_data
;
877 if (req
->flags
& SET_WIN_STYLE
) win
->style
= req
->style
;
878 if (req
->flags
& SET_WIN_EXSTYLE
) win
->ex_style
= req
->ex_style
;
879 if (req
->flags
& SET_WIN_ID
) win
->id
= req
->id
;
880 if (req
->flags
& SET_WIN_INSTANCE
) win
->instance
= req
->instance
;
881 if (req
->flags
& SET_WIN_USERDATA
) win
->user_data
= req
->user_data
;
882 if (req
->flags
& SET_WIN_EXTRA
) memcpy( win
->extra_bytes
+ req
->extra_offset
,
883 &req
->extra_value
, req
->extra_size
);
887 /* get a list of the window parents, up to the root of the tree */
888 DECL_HANDLER(get_window_parents
)
890 struct window
*ptr
, *win
= get_window( req
->handle
);
895 if (win
) for (ptr
= win
->parent
; ptr
; ptr
= ptr
->parent
) total
++;
897 reply
->count
= total
;
898 len
= min( get_reply_max_size(), total
* sizeof(user_handle_t
) );
899 if (len
&& ((data
= set_reply_data_size( len
))))
901 for (ptr
= win
->parent
; ptr
&& len
; ptr
= ptr
->parent
, len
-= sizeof(*data
))
902 *data
++ = ptr
->handle
;
907 /* get a list of the window children */
908 DECL_HANDLER(get_window_children
)
910 struct window
*ptr
, *parent
= get_window( req
->parent
);
916 for (ptr
= parent
->first_child
, total
= 0; ptr
; ptr
= ptr
->next
)
918 if (req
->atom
&& get_class_atom(ptr
->class) != req
->atom
) continue;
919 if (req
->tid
&& get_thread_id(ptr
->thread
) != req
->tid
) continue;
923 reply
->count
= total
;
924 len
= min( get_reply_max_size(), total
* sizeof(user_handle_t
) );
925 if (len
&& ((data
= set_reply_data_size( len
))))
927 for (ptr
= parent
->first_child
; ptr
&& len
; ptr
= ptr
->next
)
929 if (req
->atom
&& get_class_atom(ptr
->class) != req
->atom
) continue;
930 if (req
->tid
&& get_thread_id(ptr
->thread
) != req
->tid
) continue;
931 *data
++ = ptr
->handle
;
932 len
-= sizeof(*data
);
938 /* get a list of the window children that contain a given point */
939 DECL_HANDLER(get_window_children_from_point
)
941 struct user_handle_array array
;
942 struct window
*parent
= get_window( req
->parent
);
947 array
.handles
= NULL
;
950 if (!all_windows_from_point( parent
, req
->x
, req
->y
, &array
)) return;
952 reply
->count
= array
.count
;
953 len
= min( get_reply_max_size(), array
.count
* sizeof(user_handle_t
) );
954 if (len
) set_reply_data_ptr( array
.handles
, len
);
955 else free( array
.handles
);
959 /* get window tree information from a window handle */
960 DECL_HANDLER(get_window_tree
)
962 struct window
*win
= get_window( req
->handle
);
968 struct window
*parent
= win
->parent
;
969 reply
->parent
= parent
->handle
;
970 reply
->owner
= win
->owner
;
971 reply
->next_sibling
= win
->next
? win
->next
->handle
: 0;
972 reply
->prev_sibling
= win
->prev
? win
->prev
->handle
: 0;
973 reply
->first_sibling
= parent
->first_child
? parent
->first_child
->handle
: 0;
974 reply
->last_sibling
= parent
->last_child
? parent
->last_child
->handle
: 0;
980 reply
->next_sibling
= 0;
981 reply
->prev_sibling
= 0;
982 reply
->first_sibling
= 0;
983 reply
->last_sibling
= 0;
985 reply
->first_child
= win
->first_child
? win
->first_child
->handle
: 0;
986 reply
->last_child
= win
->last_child
? win
->last_child
->handle
: 0;
990 /* set the window and client rectangles of a window */
991 DECL_HANDLER(set_window_rectangles
)
993 struct window
*win
= get_window( req
->handle
);
997 win
->window_rect
= req
->window
;
998 win
->client_rect
= req
->client
;
1003 /* get the window and client rectangles of a window */
1004 DECL_HANDLER(get_window_rectangles
)
1006 struct window
*win
= get_window( req
->handle
);
1010 reply
->window
= win
->window_rect
;
1011 reply
->client
= win
->client_rect
;
1016 /* get the window text */
1017 DECL_HANDLER(get_window_text
)
1019 struct window
*win
= get_window( req
->handle
);
1021 if (win
&& win
->text
)
1023 size_t len
= strlenW( win
->text
) * sizeof(WCHAR
);
1024 if (len
> get_reply_max_size()) len
= get_reply_max_size();
1025 set_reply_data( win
->text
, len
);
1030 /* set the window text */
1031 DECL_HANDLER(set_window_text
)
1033 struct window
*win
= get_window( req
->handle
);
1038 size_t len
= get_req_data_size() / sizeof(WCHAR
);
1041 if (!(text
= mem_alloc( (len
+1) * sizeof(WCHAR
) ))) return;
1042 memcpy( text
, get_req_data(), len
* sizeof(WCHAR
) );
1045 if (win
->text
) free( win
->text
);
1051 /* increment the window paint count */
1052 DECL_HANDLER(inc_window_paint_count
)
1054 struct window
*win
= get_window( req
->handle
);
1056 if (win
&& win
->thread
)
1058 int old
= win
->paint_count
;
1059 if ((win
->paint_count
+= req
->incr
) < 0) win
->paint_count
= 0;
1060 inc_queue_paint_count( win
->thread
, win
->paint_count
- old
);
1065 /* get the coordinates offset between two windows */
1066 DECL_HANDLER(get_windows_offset
)
1070 reply
->x
= reply
->y
= 0;
1073 if (!(win
= get_window( req
->from
))) return;
1076 reply
->x
+= win
->client_rect
.left
;
1077 reply
->y
+= win
->client_rect
.top
;
1083 if (!(win
= get_window( req
->to
))) return;
1086 reply
->x
-= win
->client_rect
.left
;
1087 reply
->y
-= win
->client_rect
.top
;
1094 /* get the visible region of a window */
1095 DECL_HANDLER(get_visible_region
)
1097 struct region
*region
;
1098 struct window
*win
= get_window( req
->window
);
1099 struct window
*top
= NULL
;
1102 if (req
->top_win
&& !(top
= get_window( req
->top_win
))) return;
1104 if ((region
= get_visible_region( win
, top
, req
->flags
)))
1106 rectangle_t
*data
= get_region_data_and_free( region
, get_reply_max_size(), &reply
->total_size
);
1107 if (data
) set_reply_data_ptr( data
, reply
->total_size
);
1112 /* get the window region */
1113 DECL_HANDLER(get_window_region
)
1115 struct window
*win
= get_window( req
->window
);
1119 if (win
->win_region
)
1121 rectangle_t
*data
= get_region_data( win
->win_region
, get_reply_max_size(), &reply
->total_size
);
1122 if (data
) set_reply_data_ptr( data
, reply
->total_size
);
1127 /* set the window region */
1128 DECL_HANDLER(set_window_region
)
1130 struct region
*region
= NULL
;
1131 struct window
*win
= get_window( req
->window
);
1135 if (get_req_data_size()) /* no data means remove the region completely */
1137 if (!(region
= create_region_from_req_data( get_req_data(), get_req_data_size() )))
1140 if (win
->win_region
) free_region( win
->win_region
);
1141 win
->win_region
= region
;
1145 /* set a window property */
1146 DECL_HANDLER(set_window_property
)
1148 struct window
*win
= get_window( req
->window
);
1150 if (win
) set_property( win
, req
->atom
, req
->handle
,
1151 req
->string
? PROP_TYPE_STRING
: PROP_TYPE_ATOM
);
1155 /* remove a window property */
1156 DECL_HANDLER(remove_window_property
)
1158 struct window
*win
= get_window( req
->window
);
1160 if (win
) reply
->handle
= remove_property( win
, req
->atom
);
1164 /* get a window property */
1165 DECL_HANDLER(get_window_property
)
1167 struct window
*win
= get_window( req
->window
);
1169 if (win
) reply
->handle
= get_property( win
, req
->atom
);
1173 /* get the list of properties of a window */
1174 DECL_HANDLER(get_window_properties
)
1176 property_data_t
*data
;
1177 int i
, count
, max
= get_reply_max_size() / sizeof(*data
);
1178 struct window
*win
= get_window( req
->window
);
1183 for (i
= count
= 0; i
< win
->prop_inuse
; i
++)
1184 if (win
->properties
[i
].type
!= PROP_TYPE_FREE
) count
++;
1185 reply
->total
= count
;
1187 if (count
> max
) count
= max
;
1188 if (!count
|| !(data
= set_reply_data_size( count
* sizeof(*data
) ))) return;
1190 for (i
= 0; i
< win
->prop_inuse
&& count
; i
++)
1192 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
1193 data
->atom
= win
->properties
[i
].atom
;
1194 data
->string
= (win
->properties
[i
].type
== PROP_TYPE_STRING
);
1195 data
->handle
= win
->properties
[i
].handle
;
1202 /* get the new window pointer for a global window, checking permissions */
1203 /* helper for set_global_windows request */
1204 static int get_new_global_window( struct window
**win
, user_handle_t handle
)
1213 set_error( STATUS_ACCESS_DENIED
);
1216 *win
= get_window( handle
);
1217 return (*win
!= NULL
);
1220 /* Set/get the global windows */
1221 DECL_HANDLER(set_global_windows
)
1223 struct window
*new_shell_window
= shell_window
;
1224 struct window
*new_shell_listview
= shell_listview
;
1225 struct window
*new_progman_window
= progman_window
;
1226 struct window
*new_taskman_window
= taskman_window
;
1228 reply
->old_shell_window
= shell_window
? shell_window
->handle
: 0;
1229 reply
->old_shell_listview
= shell_listview
? shell_listview
->handle
: 0;
1230 reply
->old_progman_window
= progman_window
? progman_window
->handle
: 0;
1231 reply
->old_taskman_window
= taskman_window
? taskman_window
->handle
: 0;
1233 if (req
->flags
& SET_GLOBAL_SHELL_WINDOWS
)
1235 if (!get_new_global_window( &new_shell_window
, req
->shell_window
)) return;
1236 if (!get_new_global_window( &new_shell_listview
, req
->shell_listview
)) return;
1238 if (req
->flags
& SET_GLOBAL_PROGMAN_WINDOW
)
1240 if (!get_new_global_window( &new_progman_window
, req
->progman_window
)) return;
1242 if (req
->flags
& SET_GLOBAL_TASKMAN_WINDOW
)
1244 if (!get_new_global_window( &new_taskman_window
, req
->taskman_window
)) return;
1246 shell_window
= new_shell_window
;
1247 shell_listview
= new_shell_listview
;
1248 progman_window
= new_progman_window
;
1249 taskman_window
= new_taskman_window
;