Make winsock.h and winsock2.h independent from the Unix headers.
[wine] / server / window.c
1 /*
2  * Server-side window handling
3  *
4  * Copyright (C) 2001 Alexandre Julliard
5  */
6
7 #include <assert.h>
8
9 #include "object.h"
10 #include "request.h"
11 #include "thread.h"
12 #include "process.h"
13 #include "user.h"
14 #include "unicode.h"
15
16 /* a window property */
17 struct property
18 {
19     unsigned short type;     /* property type (see below) */
20     atom_t         atom;     /* property atom */
21     handle_t       handle;   /* property handle (user-defined storage) */
22 };
23
24 enum property_type
25 {
26     PROP_TYPE_FREE,   /* free entry */
27     PROP_TYPE_STRING, /* atom that was originally a string */
28     PROP_TYPE_ATOM    /* plain atom */
29 };
30
31
32 struct window
33 {
34     struct window   *parent;          /* parent window */
35     struct window   *owner;           /* owner of this window */
36     struct window   *first_child;     /* first child in Z-order */
37     struct window   *last_child;      /* last child in Z-order */
38     struct window   *first_unlinked;  /* first child not linked in the Z-order list */
39     struct window   *next;            /* next window in Z-order */
40     struct window   *prev;            /* prev window in Z-order */
41     user_handle_t    handle;          /* full handle for this window */
42     struct thread   *thread;          /* thread owning the window */
43     atom_t           atom;            /* class atom */
44     rectangle_t      window_rect;     /* window rectangle */
45     rectangle_t      client_rect;     /* client rectangle */
46     unsigned int     style;           /* window style */
47     unsigned int     ex_style;        /* window extended style */
48     unsigned int     id;              /* window id */
49     void*            instance;        /* creator instance */
50     void*            user_data;       /* user-specific data */
51     WCHAR           *text;            /* window caption text */
52     int              paint_count;     /* count of pending paints for this window */
53     int              prop_inuse;      /* number of in-use window properties */
54     int              prop_alloc;      /* number of allocated window properties */
55     struct property *properties;      /* window properties array */
56 };
57
58 static struct window *top_window;  /* top-level (desktop) window */
59
60
61 /* retrieve a pointer to a window from its handle */
62 inline static struct window *get_window( user_handle_t handle )
63 {
64     struct window *ret = get_user_object( handle, USER_WINDOW );
65     if (!ret) set_error( STATUS_INVALID_HANDLE );
66     return ret;
67 }
68
69 /* unlink a window from the tree */
70 static void unlink_window( struct window *win )
71 {
72     struct window *parent = win->parent;
73
74     assert( parent );
75
76     if (win->next) win->next->prev = win->prev;
77     else if (parent->last_child == win) parent->last_child = win->prev;
78
79     if (win->prev) win->prev->next = win->next;
80     else if (parent->first_child == win) parent->first_child = win->next;
81     else if (parent->first_unlinked == win) parent->first_unlinked = win->next;
82 }
83
84
85 /* link a window into the tree (or unlink it if the new parent is NULL)  */
86 static void link_window( struct window *win, struct window *parent, struct window *previous )
87 {
88     unlink_window( win );  /* unlink it from the previous location */
89
90     if (parent)
91     {
92         if (win->parent != parent)
93         {
94             win->owner = NULL;  /* reset owner if changing parent */
95             win->parent = parent;
96         }
97         if ((win->prev = previous))
98         {
99             if ((win->next = previous->next)) win->next->prev = win;
100             else if (win->parent->last_child == previous) win->parent->last_child = win;
101             win->prev->next = win;
102         }
103         else
104         {
105             if ((win->next = parent->first_child)) win->next->prev = win;
106             else win->parent->last_child = win;
107             parent->first_child = win;
108         }
109     }
110     else  /* move it to parent unlinked list */
111     {
112         parent = win->parent;
113         if ((win->next = parent->first_unlinked)) win->next->prev = win;
114         win->prev = NULL;
115         parent->first_unlinked = win;
116     }
117 }
118
119 /* set a window property */
120 static void set_property( struct window *win, atom_t atom, handle_t handle,
121                           enum property_type type )
122 {
123     int i, free = -1;
124     struct property *new_props;
125
126     /* check if it exists already */
127     for (i = 0; i < win->prop_inuse; i++)
128     {
129         if (win->properties[i].type == PROP_TYPE_FREE)
130         {
131             free = i;
132             continue;
133         }
134         if (win->properties[i].atom == atom)
135         {
136             win->properties[i].type = type;
137             win->properties[i].handle = handle;
138             return;
139         }
140     }
141
142     /* need to add an entry */
143     if (!grab_global_atom( atom )) return;
144     if (free == -1)
145     {
146         /* no free entry */
147         if (win->prop_inuse >= win->prop_alloc)
148         {
149             /* need to grow the array */
150             if (!(new_props = realloc( win->properties,
151                                        sizeof(*new_props) * (win->prop_alloc + 16) )))
152             {
153                 set_error( STATUS_NO_MEMORY );
154                 release_global_atom( atom );
155                 return;
156             }
157             win->prop_alloc += 16;
158             win->properties = new_props;
159         }
160         free = win->prop_inuse++;
161     }
162     win->properties[free].atom   = atom;
163     win->properties[free].type   = type;
164     win->properties[free].handle = handle;
165 }
166
167 /* remove a window property */
168 static handle_t remove_property( struct window *win, atom_t atom )
169 {
170     int i;
171
172     for (i = 0; i < win->prop_inuse; i++)
173     {
174         if (win->properties[i].type == PROP_TYPE_FREE) continue;
175         if (win->properties[i].atom == atom)
176         {
177             release_global_atom( atom );
178             win->properties[i].type = PROP_TYPE_FREE;
179             return win->properties[i].handle;
180         }
181     }
182     /* FIXME: last error? */
183     return 0;
184 }
185
186 /* find a window property */
187 static handle_t get_property( struct window *win, atom_t atom )
188 {
189     int i;
190
191     for (i = 0; i < win->prop_inuse; i++)
192     {
193         if (win->properties[i].type == PROP_TYPE_FREE) continue;
194         if (win->properties[i].atom == atom) return win->properties[i].handle;
195     }
196     /* FIXME: last error? */
197     return 0;
198 }
199
200 /* destroy all properties of a window */
201 inline static void destroy_properties( struct window *win )
202 {
203     int i;
204
205     if (!win->properties) return;
206     for (i = 0; i < win->prop_inuse; i++)
207     {
208         if (win->properties[i].type == PROP_TYPE_FREE) continue;
209         release_global_atom( win->properties[i].atom );
210     }
211     free( win->properties );
212 }
213
214 /* enum all properties into the data array */
215 static int enum_properties( struct window *win, property_data_t *data, int max )
216 {
217     int i, count;
218
219     for (i = count = 0; i < win->prop_inuse && count < max; i++)
220     {
221         if (win->properties[i].type == PROP_TYPE_FREE) continue;
222         data->atom   = win->properties[i].atom;
223         data->string = (win->properties[i].type == PROP_TYPE_STRING);
224         data->handle = win->properties[i].handle;
225         data++;
226         count++;
227     }
228     return count;
229 }
230
231 /* destroy a window */
232 static void destroy_window( struct window *win )
233 {
234     assert( win != top_window );
235
236     /* destroy all children */
237     while (win->first_child) destroy_window( win->first_child );
238     while (win->first_unlinked) destroy_window( win->first_unlinked );
239
240     /* reset siblings owner */
241     if (win->parent)
242     {
243         struct window *ptr;
244         for (ptr = win->parent->first_child; ptr; ptr = ptr->next)
245             if (ptr->owner == win) ptr->owner = NULL;
246         for (ptr = win->parent->first_unlinked; ptr; ptr = ptr->next)
247             if (ptr->owner == win) ptr->owner = NULL;
248     }
249
250     if (win->paint_count) inc_queue_paint_count( win->thread, -win->paint_count );
251     queue_cleanup_window( win->thread, win->handle );
252     free_user_handle( win->handle );
253     destroy_properties( win );
254     unlink_window( win );
255     if (win->text) free( win->text );
256     memset( win, 0x55, sizeof(*win) );
257     free( win );
258 }
259
260 /* create a new window structure (note: the window is not linked in the window tree) */
261 static struct window *create_window( struct window *parent, struct window *owner, atom_t atom )
262 {
263     struct window *win = mem_alloc( sizeof(*win) );
264     if (!win) return NULL;
265
266     if (!(win->handle = alloc_user_handle( win, USER_WINDOW )))
267     {
268         free( win );
269         return NULL;
270     }
271     win->parent         = parent;
272     win->owner          = owner;
273     win->first_child    = NULL;
274     win->last_child     = NULL;
275     win->first_unlinked = NULL;
276     win->thread         = current;
277     win->atom           = atom;
278     win->style          = 0;
279     win->ex_style       = 0;
280     win->id             = 0;
281     win->instance       = NULL;
282     win->user_data      = NULL;
283     win->text           = NULL;
284     win->paint_count    = 0;
285     win->prop_inuse     = 0;
286     win->prop_alloc     = 0;
287     win->properties     = NULL;
288
289     if (parent)  /* put it on parent unlinked list */
290     {
291         if ((win->next = parent->first_unlinked)) win->next->prev = win;
292         win->prev = NULL;
293         parent->first_unlinked = win;
294     }
295     else win->next = win->prev = NULL;
296
297     return win;
298 }
299
300 /* destroy all windows belonging to a given thread */
301 void destroy_thread_windows( struct thread *thread )
302 {
303     user_handle_t handle = 0;
304     struct window *win;
305
306     while ((win = next_user_handle( &handle, USER_WINDOW )))
307     {
308         if (win->thread != thread) continue;
309         destroy_window( win );
310     }
311 }
312
313 /* check whether child is a descendant of parent */
314 int is_child_window( user_handle_t parent, user_handle_t child )
315 {
316     struct window *child_ptr = get_user_object( child, USER_WINDOW );
317     struct window *parent_ptr = get_user_object( parent, USER_WINDOW );
318
319     if (!child_ptr || !parent_ptr) return 0;
320     while (child_ptr->parent)
321     {
322         if (child_ptr->parent == parent_ptr) return 1;
323         child_ptr = child_ptr->parent;
324     }
325     return 0;
326 }
327
328 /* create a window */
329 DECL_HANDLER(create_window)
330 {
331     req->handle = 0;
332     if (!req->parent)  /* return desktop window */
333     {
334         if (!top_window)
335         {
336             if (!(top_window = create_window( NULL, NULL, req->atom ))) return;
337             top_window->thread = NULL;  /* no thread owns the desktop */
338         }
339         req->handle = top_window->handle;
340     }
341     else
342     {
343         struct window *win, *parent, *owner = NULL;
344
345         if (!(parent = get_window( req->parent ))) return;
346         if (req->owner && !(owner = get_window( req->owner ))) return;
347         if (owner == top_window) owner = NULL;
348         else if (owner && owner->parent != parent)
349         {
350             /* owner must be a sibling of the new window */
351             set_error( STATUS_ACCESS_DENIED );
352             return;
353         }
354         if (!(win = create_window( parent, owner, req->atom ))) return;
355         req->handle = win->handle;
356     }
357 }
358
359
360 /* link a window into the tree */
361 DECL_HANDLER(link_window)
362 {
363     struct window *win, *parent = NULL, *previous = NULL;
364
365     if (!(win = get_window( req->handle ))) return;
366     if (req->parent && !(parent = get_window( req->parent ))) return;
367
368     if (win == top_window)
369     {
370         set_error( STATUS_INVALID_PARAMETER );
371         return;
372     }
373     req->full_parent = parent ? parent->handle : 0;
374     if (parent && req->previous)
375     {
376         if (req->previous == (user_handle_t)1)  /* special case: HWND_BOTTOM */
377         {
378             previous = parent->last_child;
379             if (previous == win) return;  /* nothing to do */
380         }
381         else
382         {
383             if (!(previous = get_window( req->previous ))) return;
384             /* previous must be a child of parent, and not win itself */
385             if (previous->parent != parent || previous == win)
386             {
387                 set_error( STATUS_INVALID_PARAMETER );
388                 return;
389             }
390         }
391     }
392     link_window( win, parent, previous );
393 }
394
395
396 /* destroy a window */
397 DECL_HANDLER(destroy_window)
398 {
399     struct window *win = get_window( req->handle );
400     if (win)
401     {
402         if (win != top_window) destroy_window( win );
403         else set_error( STATUS_ACCESS_DENIED );
404     }
405 }
406
407
408 /* set a window owner */
409 DECL_HANDLER(set_window_owner)
410 {
411     struct window *win = get_window( req->handle );
412     struct window *owner = get_window( req->owner );
413
414     if (!win || !owner) return;
415     if (owner->parent != win->parent)
416     {
417         /* owner has to be a sibling of window */
418         set_error( STATUS_ACCESS_DENIED );
419         return;
420     }
421     win->owner = owner;
422     req->full_owner = owner->handle;
423 }
424
425
426 /* get information from a window handle */
427 DECL_HANDLER(get_window_info)
428 {
429     struct window *win = get_window( req->handle );
430
431     req->full_handle = 0;
432     req->tid = req->pid = 0;
433     if (win)
434     {
435         req->full_handle = win->handle;
436         if (win->thread)
437         {
438             req->tid  = get_thread_id( win->thread );
439             req->pid  = get_process_id( win->thread->process );
440             req->atom = win->atom;
441         }
442     }
443 }
444
445
446 /* set some information in a window */
447 DECL_HANDLER(set_window_info)
448 {
449     struct window *win = get_window( req->handle );
450     if (!win) return;
451     req->old_style     = win->style;
452     req->old_ex_style  = win->ex_style;
453     req->old_id        = win->id;
454     req->old_instance  = win->instance;
455     req->old_user_data = win->user_data;
456     if (req->flags & SET_WIN_STYLE) win->style = req->style;
457     if (req->flags & SET_WIN_EXSTYLE) win->ex_style = req->ex_style;
458     if (req->flags & SET_WIN_ID) win->id = req->id;
459     if (req->flags & SET_WIN_INSTANCE) win->instance = req->instance;
460     if (req->flags & SET_WIN_USERDATA) win->user_data = req->user_data;
461 }
462
463
464 /* get a list of the window parents, up to the root of the tree */
465 DECL_HANDLER(get_window_parents)
466 {
467     struct window *ptr, *win = get_window( req->handle );
468     int total = 0;
469     size_t len;
470
471     if (win) for (ptr = win->parent; ptr; ptr = ptr->parent) total++;
472
473     req->count = total;
474     len = min( get_req_data_size(req), total * sizeof(user_handle_t) );
475     set_req_data_size( req, len );
476     if (len)
477     {
478         user_handle_t *data = get_req_data(req);
479         for (ptr = win->parent; ptr && len; ptr = ptr->parent, len -= sizeof(*data))
480             *data++ = ptr->handle;
481     }
482 }
483
484
485 /* get a list of the window children */
486 DECL_HANDLER(get_window_children)
487 {
488     struct window *ptr, *parent = get_window( req->parent );
489     int total = 0;
490     size_t len;
491
492     if (parent)
493         for (ptr = parent->first_child, total = 0; ptr; ptr = ptr->next)
494         {
495             if (req->atom && ptr->atom != req->atom) continue;
496             if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
497             total++;
498         }
499
500     req->count = total;
501     len = min( get_req_data_size(req), total * sizeof(user_handle_t) );
502     set_req_data_size( req, len );
503     if (len)
504     {
505         user_handle_t *data = get_req_data(req);
506         for (ptr = parent->first_child; ptr && len; ptr = ptr->next, len -= sizeof(*data))
507         {
508             if (req->atom && ptr->atom != req->atom) continue;
509             if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
510             *data++ = ptr->handle;
511         }
512     }
513 }
514
515
516 /* get window tree information from a window handle */
517 DECL_HANDLER(get_window_tree)
518 {
519     struct window *win = get_window( req->handle );
520
521     if (!win) return;
522
523     if (win->parent)
524     {
525         struct window *parent = win->parent;
526         req->parent        = parent->handle;
527         req->owner         = win->owner ? win->owner->handle : 0;
528         req->next_sibling  = win->next ? win->next->handle : 0;
529         req->prev_sibling  = win->prev ? win->prev->handle : 0;
530         req->first_sibling = parent->first_child ? parent->first_child->handle : 0;
531         req->last_sibling  = parent->last_child ? parent->last_child->handle : 0;
532     }
533     else
534     {
535         req->parent        = 0;
536         req->owner         = 0;
537         req->next_sibling  = 0;
538         req->prev_sibling  = 0;
539         req->first_sibling = 0;
540         req->last_sibling  = 0;
541     }
542     req->first_child = win->first_child ? win->first_child->handle : 0;
543     req->last_child  = win->last_child ? win->last_child->handle : 0;
544 }
545
546
547 /* set the window and client rectangles of a window */
548 DECL_HANDLER(set_window_rectangles)
549 {
550     struct window *win = get_window( req->handle );
551
552     if (win)
553     {
554         win->window_rect = req->window;
555         win->client_rect = req->client;
556     }
557 }
558
559
560 /* get the window and client rectangles of a window */
561 DECL_HANDLER(get_window_rectangles)
562 {
563     struct window *win = get_window( req->handle );
564
565     if (win)
566     {
567         req->window = win->window_rect;
568         req->client = win->client_rect;
569     }
570 }
571
572
573 /* get the window text */
574 DECL_HANDLER(get_window_text)
575 {
576     struct window *win = get_window( req->handle );
577     size_t len = 0;
578
579     if (win && win->text)
580     {
581         len = strlenW( win->text ) * sizeof(WCHAR);
582         if (len > get_req_data_size(req)) len = get_req_data_size(req);
583         memcpy( get_req_data(req), win->text, len );
584     }
585     set_req_data_size( req, len );
586 }
587
588
589 /* set the window text */
590 DECL_HANDLER(set_window_text)
591 {
592     struct window *win = get_window( req->handle );
593
594     if (win)
595     {
596         WCHAR *text = NULL;
597         size_t len = get_req_data_size(req) / sizeof(WCHAR);
598         if (len)
599         {
600             if (!(text = mem_alloc( (len+1) * sizeof(WCHAR) ))) return;
601             memcpy( text, get_req_data(req), len * sizeof(WCHAR) );
602             text[len] = 0;
603         }
604         if (win->text) free( win->text );
605         win->text = text;
606     }
607 }
608
609
610 /* increment the window paint count */
611 DECL_HANDLER(inc_window_paint_count)
612 {
613     struct window *win = get_window( req->handle );
614
615     if (win)
616     {
617         int old = win->paint_count;
618         if ((win->paint_count += req->incr) < 0) win->paint_count = 0;
619         inc_queue_paint_count( win->thread, win->paint_count - old );
620     }
621 }
622
623
624 /* get the coordinates offset between two windows */
625 DECL_HANDLER(get_windows_offset)
626 {
627     struct window *win;
628
629     req->x = req->y = 0;
630     if (req->from)
631     {
632         if (!(win = get_window( req->from ))) return;
633         while (win)
634         {
635             req->x += win->client_rect.left;
636             req->y += win->client_rect.top;
637             win = win->parent;
638         }
639     }
640     if (req->to)
641     {
642         if (!(win = get_window( req->to ))) return;
643         while (win)
644         {
645             req->x -= win->client_rect.left;
646             req->y -= win->client_rect.top;
647             win = win->parent;
648         }
649     }
650 }
651
652
653 /* set a window property */
654 DECL_HANDLER(set_window_property)
655 {
656     struct window *win = get_window( req->window );
657
658     if (win) set_property( win, req->atom, req->handle,
659                            req->string ? PROP_TYPE_STRING : PROP_TYPE_ATOM );
660 }
661
662
663 /* remove a window property */
664 DECL_HANDLER(remove_window_property)
665 {
666     struct window *win = get_window( req->window );
667     req->handle = 0;
668     if (win) req->handle = remove_property( win, req->atom );
669 }
670
671
672 /* get a window property */
673 DECL_HANDLER(get_window_property)
674 {
675     struct window *win = get_window( req->window );
676     req->handle = 0;
677     if (win) req->handle = get_property( win, req->atom );
678 }
679
680
681 /* get the list of properties of a window */
682 DECL_HANDLER(get_window_properties)
683 {
684     int count = 0;
685     property_data_t *data = get_req_data(req);
686     struct window *win = get_window( req->window );
687
688     if (win) count = enum_properties( win, data, get_req_data_size(req) / sizeof(*data) );
689     set_req_data_size( req, count * sizeof(*data) );
690 }