Only send TVN_ITEMEXPANDING for items marked as having children.
[wine] / server / clipboard.c
1 /*
2  * Server-side clipboard management
3  *
4  * Copyright (C) 2002 Ulrich Czekalla
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "request.h"
30 #include "object.h"
31 #include "user.h"
32
33 struct thread *cbthread;        /* thread id that has clipboard open */
34 static user_handle_t clipboard; /* window that has clipboard open */
35
36 struct thread *cbowner;         /* thread id that owns the clipboard */
37 static user_handle_t owner;     /* window that owns the clipboard data */
38
39 static user_handle_t viewer;    /* first window in clipboard viewer list */
40 static unsigned int seqno;      /* clipboard change sequence number */
41 static time_t seqnots;          /* time stamp of last seqno increment */
42
43 #define MINUPDATELAPSE 2
44
45 /* Called when thread terminates to allow release of clipboard */
46 void cleanup_clipboard_thread(struct thread *thread)
47 {
48     if (thread == cbthread)
49     {
50         clipboard = 0;
51         cbthread = NULL;
52     }
53     if (thread == cbowner)
54     {
55         owner = 0;
56         cbowner = NULL;
57     }
58 }
59
60 static int set_clipboard_window(user_handle_t win, int clear)
61 {
62     if (cbthread && cbthread != current)
63     {
64         set_error(STATUS_WAS_LOCKED);
65         return 0;
66     }
67     else if (!clear)
68     {
69         clipboard = win;
70         cbthread = current;
71     }
72     else
73     {
74         cbthread = NULL;
75         clipboard = 0;
76     }
77     return 1;
78 }
79
80
81 static int set_clipboard_owner(user_handle_t win, int clear)
82 {
83     if (cbthread == current)
84     {
85         if (!clear)
86         {
87             cbowner = current;
88             owner = win;
89         }
90         else
91         {
92             cbowner = 0;
93             owner = 0;
94         }
95         seqno++;
96         return 1;
97     }
98     else
99     {
100         set_error(STATUS_WAS_LOCKED);
101         return 0;
102     }
103 }
104
105
106 static int get_seqno(void)
107 {
108     time_t tm = time(NULL);
109
110     if (!cbowner && (tm > (seqnots + MINUPDATELAPSE)))
111     {
112         seqnots = tm;
113         seqno++;
114     }
115     return seqno;
116 }
117
118
119 DECL_HANDLER(set_clipboard_info)
120 {
121     reply->old_clipboard = clipboard;
122     reply->old_owner = owner;
123     reply->old_viewer = viewer;
124
125     if (req->flags & SET_CB_OPEN)
126     {
127         if (!set_clipboard_window(req->clipboard, 0))
128             return;
129     }
130     else if (req->flags & SET_CB_CLOSE)
131     {
132         if (!set_clipboard_window(0, 1))
133             return;
134     }
135
136     if (req->flags & SET_CB_OWNER)
137     {
138         if (!set_clipboard_owner(req->owner, 0))
139             return;
140     }
141     else if (req->flags & SET_CB_RELOWNER)
142     {
143         if (!set_clipboard_owner(0, 1))
144             return;
145     }
146
147     if (req->flags & SET_CB_VIEWER)
148         viewer = req->viewer;
149
150     if (req->flags & SET_CB_SEQNO)
151         seqno++;
152
153     reply->seqno = get_seqno();
154
155     if (cbthread == current)
156         reply->flags |= CB_OPEN;
157
158     if (cbowner == current)
159         reply->flags |= CB_OWNER;
160 }