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 atom_t atom
; /* class atom */
67 user_handle_t last_active
; /* last active popup */
68 rectangle_t window_rect
; /* window rectangle */
69 rectangle_t client_rect
; /* client rectangle */
70 unsigned int style
; /* window style */
71 unsigned int ex_style
; /* window extended style */
72 unsigned int id
; /* window id */
73 void* instance
; /* creator instance */
74 void* user_data
; /* user-specific data */
75 WCHAR
*text
; /* window caption text */
76 int paint_count
; /* count of pending paints for this window */
77 int prop_inuse
; /* number of in-use window properties */
78 int prop_alloc
; /* number of allocated window properties */
79 struct property
*properties
; /* window properties array */
80 int nb_extra_bytes
; /* number of extra bytes */
81 char extra_bytes
[1]; /* extra bytes storage */
84 static struct window
*top_window
; /* top-level (desktop) window */
86 /* global window pointers */
87 static struct window
*shell_window
;
88 static struct window
*shell_listview
;
89 static struct window
*progman_window
;
90 static struct window
*taskman_window
;
92 /* retrieve a pointer to a window from its handle */
93 inline static struct window
*get_window( user_handle_t handle
)
95 struct window
*ret
= get_user_object( handle
, USER_WINDOW
);
96 if (!ret
) set_error( STATUS_INVALID_HANDLE
);
100 /* unlink a window from the tree */
101 static void unlink_window( struct window
*win
)
103 struct window
*parent
= win
->parent
;
107 if (win
->next
) win
->next
->prev
= win
->prev
;
108 else if (parent
->last_child
== win
) parent
->last_child
= win
->prev
;
110 if (win
->prev
) win
->prev
->next
= win
->next
;
111 else if (parent
->first_child
== win
) parent
->first_child
= win
->next
;
112 else if (parent
->first_unlinked
== win
) parent
->first_unlinked
= win
->next
;
116 /* link a window into the tree (or unlink it if the new parent is NULL) */
117 static void link_window( struct window
*win
, struct window
*parent
, struct window
*previous
)
119 unlink_window( win
); /* unlink it from the previous location */
123 win
->parent
= parent
;
124 if ((win
->prev
= previous
))
126 if ((win
->next
= previous
->next
)) win
->next
->prev
= win
;
127 else if (win
->parent
->last_child
== previous
) win
->parent
->last_child
= win
;
128 win
->prev
->next
= win
;
132 if ((win
->next
= parent
->first_child
)) win
->next
->prev
= win
;
133 else win
->parent
->last_child
= win
;
134 parent
->first_child
= win
;
137 else /* move it to parent unlinked list */
139 parent
= win
->parent
;
140 if ((win
->next
= parent
->first_unlinked
)) win
->next
->prev
= win
;
142 parent
->first_unlinked
= win
;
146 /* set a window property */
147 static void set_property( struct window
*win
, atom_t atom
, obj_handle_t handle
,
148 enum property_type type
)
151 struct property
*new_props
;
153 /* check if it exists already */
154 for (i
= 0; i
< win
->prop_inuse
; i
++)
156 if (win
->properties
[i
].type
== PROP_TYPE_FREE
)
161 if (win
->properties
[i
].atom
== atom
)
163 win
->properties
[i
].type
= type
;
164 win
->properties
[i
].handle
= handle
;
169 /* need to add an entry */
170 if (!grab_global_atom( atom
)) return;
174 if (win
->prop_inuse
>= win
->prop_alloc
)
176 /* need to grow the array */
177 if (!(new_props
= realloc( win
->properties
,
178 sizeof(*new_props
) * (win
->prop_alloc
+ 16) )))
180 set_error( STATUS_NO_MEMORY
);
181 release_global_atom( atom
);
184 win
->prop_alloc
+= 16;
185 win
->properties
= new_props
;
187 free
= win
->prop_inuse
++;
189 win
->properties
[free
].atom
= atom
;
190 win
->properties
[free
].type
= type
;
191 win
->properties
[free
].handle
= handle
;
194 /* remove a window property */
195 static obj_handle_t
remove_property( struct window
*win
, atom_t atom
)
199 for (i
= 0; i
< win
->prop_inuse
; i
++)
201 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
202 if (win
->properties
[i
].atom
== atom
)
204 release_global_atom( atom
);
205 win
->properties
[i
].type
= PROP_TYPE_FREE
;
206 return win
->properties
[i
].handle
;
209 /* FIXME: last error? */
213 /* find a window property */
214 static obj_handle_t
get_property( struct window
*win
, atom_t atom
)
218 for (i
= 0; i
< win
->prop_inuse
; i
++)
220 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
221 if (win
->properties
[i
].atom
== atom
) return win
->properties
[i
].handle
;
223 /* FIXME: last error? */
227 /* destroy all properties of a window */
228 inline static void destroy_properties( struct window
*win
)
232 if (!win
->properties
) return;
233 for (i
= 0; i
< win
->prop_inuse
; i
++)
235 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
236 release_global_atom( win
->properties
[i
].atom
);
238 free( win
->properties
);
241 /* destroy a window */
242 static void destroy_window( struct window
*win
)
244 assert( win
!= top_window
);
246 /* destroy all children */
247 while (win
->first_child
) destroy_window( win
->first_child
);
248 while (win
->first_unlinked
) destroy_window( win
->first_unlinked
);
250 if (win
->thread
->queue
)
252 if (win
->paint_count
) inc_queue_paint_count( win
->thread
, -win
->paint_count
);
253 queue_cleanup_window( win
->thread
, win
->handle
);
255 /* reset global window pointers, if the corresponding window is destroyed */
256 if (win
== shell_window
) shell_window
= NULL
;
257 if (win
== shell_listview
) shell_listview
= NULL
;
258 if (win
== progman_window
) progman_window
= NULL
;
259 if (win
== taskman_window
) taskman_window
= NULL
;
260 free_user_handle( win
->handle
);
261 destroy_properties( win
);
262 unlink_window( win
);
263 if (win
->text
) free( win
->text
);
264 memset( win
, 0x55, sizeof(*win
) );
268 /* create a new window structure (note: the window is not linked in the window tree) */
269 static struct window
*create_window( struct window
*parent
, struct window
*owner
, atom_t atom
,
272 struct window
*win
= mem_alloc( sizeof(*win
) + extra_bytes
- 1 );
273 if (!win
) return NULL
;
275 if (!(win
->handle
= alloc_user_handle( win
, USER_WINDOW
)))
280 win
->parent
= parent
;
281 win
->owner
= owner
? owner
->handle
: 0;
282 win
->first_child
= NULL
;
283 win
->last_child
= NULL
;
284 win
->first_unlinked
= NULL
;
285 win
->thread
= current
;
287 win
->last_active
= win
->handle
;
291 win
->instance
= NULL
;
292 win
->user_data
= NULL
;
294 win
->paint_count
= 0;
297 win
->properties
= NULL
;
298 win
->nb_extra_bytes
= extra_bytes
;
299 memset( win
->extra_bytes
, 0, extra_bytes
);
301 if (parent
) /* put it on parent unlinked list */
303 if ((win
->next
= parent
->first_unlinked
)) win
->next
->prev
= win
;
305 parent
->first_unlinked
= win
;
307 else win
->next
= win
->prev
= NULL
;
309 /* if parent belongs to a different thread, attach the two threads */
310 if (parent
&& parent
->thread
&& parent
->thread
!= current
)
311 attach_thread_input( current
, parent
->thread
);
315 /* destroy all windows belonging to a given thread */
316 void destroy_thread_windows( struct thread
*thread
)
318 user_handle_t handle
= 0;
321 while ((win
= next_user_handle( &handle
, USER_WINDOW
)))
323 if (win
->thread
!= thread
) continue;
324 destroy_window( win
);
328 /* check whether child is a descendant of parent */
329 int is_child_window( user_handle_t parent
, user_handle_t child
)
331 struct window
*child_ptr
= get_user_object( child
, USER_WINDOW
);
332 struct window
*parent_ptr
= get_user_object( parent
, USER_WINDOW
);
334 if (!child_ptr
|| !parent_ptr
) return 0;
335 while (child_ptr
->parent
)
337 if (child_ptr
->parent
== parent_ptr
) return 1;
338 child_ptr
= child_ptr
->parent
;
343 /* check whether window is a top-level window */
344 int is_top_level_window( user_handle_t window
)
346 struct window
*win
= get_user_object( window
, USER_WINDOW
);
347 return (win
&& win
->parent
== top_window
);
350 /* make a window active if possible */
351 int make_window_active( user_handle_t window
)
353 struct window
*owner
, *win
= get_window( window
);
357 /* set last active for window and its owner */
358 win
->last_active
= win
->handle
;
359 if ((owner
= get_user_object( win
->owner
, USER_WINDOW
))) owner
->last_active
= win
->handle
;
363 /* find child of 'parent' that contains the given point (in parent-relative coords) */
364 static struct window
*child_window_from_point( struct window
*parent
, int x
, int y
)
368 for (ptr
= parent
->first_child
; ptr
; ptr
= ptr
->next
)
370 if (!(ptr
->style
& WS_VISIBLE
)) continue; /* not visible -> skip */
371 if ((ptr
->style
& (WS_POPUP
|WS_CHILD
|WS_DISABLED
)) == (WS_CHILD
|WS_DISABLED
))
372 continue; /* disabled child -> skip */
373 if ((ptr
->ex_style
& (WS_EX_LAYERED
|WS_EX_TRANSPARENT
)) == (WS_EX_LAYERED
|WS_EX_TRANSPARENT
))
374 continue; /* transparent -> skip */
375 if (x
< ptr
->window_rect
.left
|| x
>= ptr
->window_rect
.right
||
376 y
< ptr
->window_rect
.top
|| y
>= ptr
->window_rect
.bottom
)
377 continue; /* not in window -> skip */
379 /* FIXME: check window region here */
381 /* if window is minimized or disabled, return at once */
382 if (ptr
->style
& (WS_MINIMIZE
|WS_DISABLED
)) return ptr
;
384 /* if point is not in client area, return at once */
385 if (x
< ptr
->client_rect
.left
|| x
>= ptr
->client_rect
.right
||
386 y
< ptr
->client_rect
.top
|| y
>= ptr
->client_rect
.bottom
)
389 return child_window_from_point( ptr
, x
- ptr
->client_rect
.left
, y
- ptr
->client_rect
.top
);
391 return parent
; /* not found any child */
394 /* find window containing point (in absolute coords) */
395 user_handle_t
window_from_point( int x
, int y
)
399 if (!top_window
) return 0;
400 ret
= child_window_from_point( top_window
, x
, y
);
404 /* return the thread owning a window */
405 struct thread
*get_window_thread( user_handle_t handle
)
407 struct window
*win
= get_user_object( handle
, USER_WINDOW
);
408 if (!win
|| !win
->thread
) return NULL
;
409 return (struct thread
*)grab_object( win
->thread
);
412 /* find a child of the specified window that needs repainting */
413 static struct window
*find_child_to_repaint( struct window
*parent
, struct thread
*thread
)
415 struct window
*ptr
, *ret
= NULL
;
417 for (ptr
= parent
->first_child
; ptr
&& !ret
; ptr
= ptr
->next
)
419 if (!(ptr
->style
& WS_VISIBLE
)) continue;
420 if (ptr
->paint_count
&& ptr
->thread
== thread
)
422 else /* explore its children */
423 ret
= find_child_to_repaint( ptr
, thread
);
426 if (ret
&& (ret
->ex_style
& WS_EX_TRANSPARENT
))
428 /* transparent window, check for non-transparent sibling to paint first */
429 for (ptr
= ret
->next
; ptr
; ptr
= ptr
->next
)
431 if (!(ptr
->style
& WS_VISIBLE
)) continue;
432 if (ptr
->ex_style
& WS_EX_TRANSPARENT
) continue;
433 if (ptr
->paint_count
&& ptr
->thread
== thread
) return ptr
;
440 /* find a window that needs repainting */
441 user_handle_t
find_window_to_repaint( user_handle_t parent
, struct thread
*thread
)
443 struct window
*win
= parent
? get_window( parent
) : top_window
;
445 if (!win
|| !(win
->style
& WS_VISIBLE
)) return 0;
446 if (!win
->paint_count
|| win
->thread
!= thread
)
447 win
= find_child_to_repaint( win
, thread
);
448 return win
? win
->handle
: 0;
452 /* create a window */
453 DECL_HANDLER(create_window
)
456 if (req
->extra
< 0 || req
->extra
> 4096) /* don't allow stupid values here */
458 set_error( STATUS_INVALID_PARAMETER
);
461 if (!req
->parent
) /* return desktop window */
465 if (!(top_window
= create_window( NULL
, NULL
, req
->atom
, req
->extra
))) return;
466 top_window
->thread
= NULL
; /* no thread owns the desktop */
467 top_window
->style
= WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
469 reply
->handle
= top_window
->handle
;
473 struct window
*win
, *parent
, *owner
= NULL
;
475 if (!(parent
= get_window( req
->parent
))) return;
476 if (req
->owner
&& !(owner
= get_window( req
->owner
))) return;
477 if (owner
== top_window
) owner
= NULL
;
478 else if (owner
&& parent
!= top_window
)
480 /* an owned window must be created as top-level */
481 set_error( STATUS_ACCESS_DENIED
);
484 if (!(win
= create_window( parent
, owner
, req
->atom
, req
->extra
))) return;
485 reply
->handle
= win
->handle
;
490 /* link a window into the tree */
491 DECL_HANDLER(link_window
)
493 struct window
*win
, *parent
= NULL
, *previous
= NULL
;
495 if (!(win
= get_window( req
->handle
))) return;
496 if (req
->parent
&& !(parent
= get_window( req
->parent
))) return;
498 if (win
== top_window
)
500 set_error( STATUS_INVALID_PARAMETER
);
503 reply
->full_parent
= parent
? parent
->handle
: 0;
504 if (parent
&& req
->previous
)
506 if (req
->previous
== (user_handle_t
)1) /* special case: HWND_BOTTOM */
508 previous
= parent
->last_child
;
509 if (previous
== win
) return; /* nothing to do */
513 if (!(previous
= get_window( req
->previous
))) return;
514 /* previous must be a child of parent, and not win itself */
515 if (previous
->parent
!= parent
|| previous
== win
)
517 set_error( STATUS_INVALID_PARAMETER
);
522 link_window( win
, parent
, previous
);
526 /* destroy a window */
527 DECL_HANDLER(destroy_window
)
529 struct window
*win
= get_window( req
->handle
);
532 if (win
!= top_window
) destroy_window( win
);
533 else set_error( STATUS_ACCESS_DENIED
);
538 /* set a window owner */
539 DECL_HANDLER(set_window_owner
)
541 struct window
*win
= get_window( req
->handle
);
542 struct window
*owner
= NULL
;
545 if (req
->owner
&& !(owner
= get_window( req
->owner
))) return;
546 if (win
== top_window
)
548 set_error( STATUS_ACCESS_DENIED
);
551 reply
->prev_owner
= win
->owner
;
552 reply
->full_owner
= win
->owner
= owner
? owner
->handle
: 0;
556 /* get information from a window handle */
557 DECL_HANDLER(get_window_info
)
559 struct window
*win
= get_window( req
->handle
);
561 reply
->full_handle
= 0;
562 reply
->tid
= reply
->pid
= 0;
565 reply
->full_handle
= win
->handle
;
566 reply
->last_active
= win
->handle
;
567 if (get_user_object( win
->last_active
, USER_WINDOW
)) reply
->last_active
= win
->last_active
;
570 reply
->tid
= get_thread_id( win
->thread
);
571 reply
->pid
= get_process_id( win
->thread
->process
);
572 reply
->atom
= win
->atom
;
578 /* set some information in a window */
579 DECL_HANDLER(set_window_info
)
581 struct window
*win
= get_window( req
->handle
);
584 if (req
->flags
&& win
== top_window
)
586 set_error( STATUS_ACCESS_DENIED
);
589 if (req
->extra_offset
< -1 || req
->extra_offset
>= win
->nb_extra_bytes
)
591 set_error( STATUS_INVALID_PARAMETER
);
594 if (req
->extra_offset
!= -1)
596 memcpy( &reply
->old_extra_value
, win
->extra_bytes
+ req
->extra_offset
,
597 min( sizeof(reply
->old_extra_value
),
598 (size_t)(win
->nb_extra_bytes
- req
->extra_offset
) ));
600 else if (req
->flags
& (SET_WIN_EXTRAWORD
|SET_WIN_EXTRALONG
))
602 set_error( STATUS_INVALID_PARAMETER
);
605 reply
->old_style
= win
->style
;
606 reply
->old_ex_style
= win
->ex_style
;
607 reply
->old_id
= win
->id
;
608 reply
->old_instance
= win
->instance
;
609 reply
->old_user_data
= win
->user_data
;
610 if (req
->flags
& SET_WIN_STYLE
) win
->style
= req
->style
;
611 if (req
->flags
& SET_WIN_EXSTYLE
) win
->ex_style
= req
->ex_style
;
612 if (req
->flags
& SET_WIN_ID
) win
->id
= req
->id
;
613 if (req
->flags
& SET_WIN_INSTANCE
) win
->instance
= req
->instance
;
614 if (req
->flags
& SET_WIN_USERDATA
) win
->user_data
= req
->user_data
;
615 if (req
->flags
& (SET_WIN_EXTRAWORD
|SET_WIN_EXTRALONG
))
617 const int len
= (req
->flags
& SET_WIN_EXTRALONG
) ? sizeof(int) : sizeof(short);
618 memcpy( win
->extra_bytes
+ req
->extra_offset
, &req
->extra_value
,
619 min( len
, win
->nb_extra_bytes
- req
->extra_offset
));
624 /* get a list of the window parents, up to the root of the tree */
625 DECL_HANDLER(get_window_parents
)
627 struct window
*ptr
, *win
= get_window( req
->handle
);
632 if (win
) for (ptr
= win
->parent
; ptr
; ptr
= ptr
->parent
) total
++;
634 reply
->count
= total
;
635 len
= min( get_reply_max_size(), total
* sizeof(user_handle_t
) );
636 if (len
&& ((data
= set_reply_data_size( len
))))
638 for (ptr
= win
->parent
; ptr
&& len
; ptr
= ptr
->parent
, len
-= sizeof(*data
))
639 *data
++ = ptr
->handle
;
644 /* get a list of the window children */
645 DECL_HANDLER(get_window_children
)
647 struct window
*ptr
, *parent
= get_window( req
->parent
);
653 for (ptr
= parent
->first_child
, total
= 0; ptr
; ptr
= ptr
->next
)
655 if (req
->atom
&& ptr
->atom
!= req
->atom
) continue;
656 if (req
->tid
&& get_thread_id(ptr
->thread
) != req
->tid
) continue;
660 reply
->count
= total
;
661 len
= min( get_reply_max_size(), total
* sizeof(user_handle_t
) );
662 if (len
&& ((data
= set_reply_data_size( len
))))
664 for (ptr
= parent
->first_child
; ptr
&& len
; ptr
= ptr
->next
)
666 if (req
->atom
&& ptr
->atom
!= req
->atom
) continue;
667 if (req
->tid
&& get_thread_id(ptr
->thread
) != req
->tid
) continue;
668 *data
++ = ptr
->handle
;
669 len
-= sizeof(*data
);
675 /* get window tree information from a window handle */
676 DECL_HANDLER(get_window_tree
)
678 struct window
*win
= get_window( req
->handle
);
684 struct window
*parent
= win
->parent
;
685 reply
->parent
= parent
->handle
;
686 reply
->owner
= win
->owner
;
687 reply
->next_sibling
= win
->next
? win
->next
->handle
: 0;
688 reply
->prev_sibling
= win
->prev
? win
->prev
->handle
: 0;
689 reply
->first_sibling
= parent
->first_child
? parent
->first_child
->handle
: 0;
690 reply
->last_sibling
= parent
->last_child
? parent
->last_child
->handle
: 0;
696 reply
->next_sibling
= 0;
697 reply
->prev_sibling
= 0;
698 reply
->first_sibling
= 0;
699 reply
->last_sibling
= 0;
701 reply
->first_child
= win
->first_child
? win
->first_child
->handle
: 0;
702 reply
->last_child
= win
->last_child
? win
->last_child
->handle
: 0;
706 /* set the window and client rectangles of a window */
707 DECL_HANDLER(set_window_rectangles
)
709 struct window
*win
= get_window( req
->handle
);
713 win
->window_rect
= req
->window
;
714 win
->client_rect
= req
->client
;
719 /* get the window and client rectangles of a window */
720 DECL_HANDLER(get_window_rectangles
)
722 struct window
*win
= get_window( req
->handle
);
726 reply
->window
= win
->window_rect
;
727 reply
->client
= win
->client_rect
;
732 /* get the window text */
733 DECL_HANDLER(get_window_text
)
735 struct window
*win
= get_window( req
->handle
);
737 if (win
&& win
->text
)
739 size_t len
= strlenW( win
->text
) * sizeof(WCHAR
);
740 if (len
> get_reply_max_size()) len
= get_reply_max_size();
741 set_reply_data( win
->text
, len
);
746 /* set the window text */
747 DECL_HANDLER(set_window_text
)
749 struct window
*win
= get_window( req
->handle
);
754 size_t len
= get_req_data_size() / sizeof(WCHAR
);
757 if (!(text
= mem_alloc( (len
+1) * sizeof(WCHAR
) ))) return;
758 memcpy( text
, get_req_data(), len
* sizeof(WCHAR
) );
761 if (win
->text
) free( win
->text
);
767 /* increment the window paint count */
768 DECL_HANDLER(inc_window_paint_count
)
770 struct window
*win
= get_window( req
->handle
);
772 if (win
&& win
->thread
)
774 int old
= win
->paint_count
;
775 if ((win
->paint_count
+= req
->incr
) < 0) win
->paint_count
= 0;
776 inc_queue_paint_count( win
->thread
, win
->paint_count
- old
);
781 /* get the coordinates offset between two windows */
782 DECL_HANDLER(get_windows_offset
)
786 reply
->x
= reply
->y
= 0;
789 if (!(win
= get_window( req
->from
))) return;
792 reply
->x
+= win
->client_rect
.left
;
793 reply
->y
+= win
->client_rect
.top
;
799 if (!(win
= get_window( req
->to
))) return;
802 reply
->x
-= win
->client_rect
.left
;
803 reply
->y
-= win
->client_rect
.top
;
810 /* set a window property */
811 DECL_HANDLER(set_window_property
)
813 struct window
*win
= get_window( req
->window
);
815 if (win
) set_property( win
, req
->atom
, req
->handle
,
816 req
->string
? PROP_TYPE_STRING
: PROP_TYPE_ATOM
);
820 /* remove a window property */
821 DECL_HANDLER(remove_window_property
)
823 struct window
*win
= get_window( req
->window
);
825 if (win
) reply
->handle
= remove_property( win
, req
->atom
);
829 /* get a window property */
830 DECL_HANDLER(get_window_property
)
832 struct window
*win
= get_window( req
->window
);
834 if (win
) reply
->handle
= get_property( win
, req
->atom
);
838 /* get the list of properties of a window */
839 DECL_HANDLER(get_window_properties
)
841 property_data_t
*data
;
842 int i
, count
, max
= get_reply_max_size() / sizeof(*data
);
843 struct window
*win
= get_window( req
->window
);
848 for (i
= count
= 0; i
< win
->prop_inuse
; i
++)
849 if (win
->properties
[i
].type
!= PROP_TYPE_FREE
) count
++;
850 reply
->total
= count
;
852 if (count
> max
) count
= max
;
853 if (!count
|| !(data
= set_reply_data_size( count
* sizeof(*data
) ))) return;
855 for (i
= 0; i
< win
->prop_inuse
&& count
; i
++)
857 if (win
->properties
[i
].type
== PROP_TYPE_FREE
) continue;
858 data
->atom
= win
->properties
[i
].atom
;
859 data
->string
= (win
->properties
[i
].type
== PROP_TYPE_STRING
);
860 data
->handle
= win
->properties
[i
].handle
;
867 /* get the new window pointer for a global window, checking permissions */
868 /* helper for set_global_windows request */
869 static int get_new_global_window( struct window
**win
, user_handle_t handle
)
878 set_error( STATUS_ACCESS_DENIED
);
881 *win
= get_window( handle
);
882 return (*win
!= NULL
);
885 /* Set/get the global windows */
886 DECL_HANDLER(set_global_windows
)
888 struct window
*new_shell_window
= shell_window
;
889 struct window
*new_shell_listview
= shell_listview
;
890 struct window
*new_progman_window
= progman_window
;
891 struct window
*new_taskman_window
= taskman_window
;
893 reply
->old_shell_window
= shell_window
? shell_window
->handle
: 0;
894 reply
->old_shell_listview
= shell_listview
? shell_listview
->handle
: 0;
895 reply
->old_progman_window
= progman_window
? progman_window
->handle
: 0;
896 reply
->old_taskman_window
= taskman_window
? taskman_window
->handle
: 0;
898 if (req
->flags
& SET_GLOBAL_SHELL_WINDOWS
)
900 if (!get_new_global_window( &new_shell_window
, req
->shell_window
)) return;
901 if (!get_new_global_window( &new_shell_listview
, req
->shell_listview
)) return;
903 if (req
->flags
& SET_GLOBAL_PROGMAN_WINDOW
)
905 if (!get_new_global_window( &new_progman_window
, req
->progman_window
)) return;
907 if (req
->flags
& SET_GLOBAL_TASKMAN_WINDOW
)
909 if (!get_new_global_window( &new_taskman_window
, req
->taskman_window
)) return;
911 shell_window
= new_shell_window
;
912 shell_listview
= new_shell_listview
;
913 progman_window
= new_progman_window
;
914 taskman_window
= new_taskman_window
;