]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/dix/grabs.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / dix / grabs.c
1 /* $XConsortium: grabs.c,v 5.10 94/04/17 20:26:39 dpw Exp $ */
2 /* $XFree86: xc/programs/Xserver/dix/grabs.c,v 3.0 1996/04/15 11:19:48 dawes Exp $ */
3 /*
4
5 Copyright (c) 1987  X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
30
31
32 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
33
34                         All Rights Reserved
35
36 Permission to use, copy, modify, and distribute this software and its 
37 documentation for any purpose and without fee is hereby granted, 
38 provided that the above copyright notice appear in all copies and that
39 both that copyright notice and this permission notice appear in 
40 supporting documentation, and that the name of Digital not be
41 used in advertising or publicity pertaining to distribution of the
42 software without specific, written prior permission.  
43 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
44 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
45 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
46 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
47 WHETHER IN AN action OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
48 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 SOFTWARE.
50
51 */
52
53 #include "X.h"
54 #include "misc.h"
55 #define NEED_EVENTS
56 #include "Xproto.h"
57 #include "windowstr.h"
58 #include "inputstr.h"
59 #include "cursorstr.h"
60 #include "dixgrabs.h"
61
62 extern InputInfo inputInfo;
63
64 #define BITMASK(i) (((Mask)1) << ((i) & 31))
65 #define MASKIDX(i) ((i) >> 5)
66 #define MASKWORD(buf, i) buf[MASKIDX(i)]
67 #define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
68 #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
69 #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
70
71 GrabPtr
72 #if NeedFunctionPrototypes
73 CreateGrab(
74     int client,
75     DeviceIntPtr device,
76     WindowPtr window,
77     Mask eventMask,
78     Bool ownerEvents, Bool keyboardMode, Bool pointerMode,
79     DeviceIntPtr modDevice,
80     unsigned short modifiers,
81     int type,
82     KeyCode keybut,     /* key or button */
83     WindowPtr confineTo,
84     CursorPtr cursor)
85 #else
86 CreateGrab(client, device, window, eventMask, ownerEvents, keyboardMode,
87            pointerMode, modDevice, modifiers, type, keybut, confineTo, cursor)
88     int client;
89     DeviceIntPtr device;
90     WindowPtr window;
91     Mask eventMask;
92     Bool ownerEvents, keyboardMode, pointerMode;
93     DeviceIntPtr modDevice;
94     unsigned short modifiers;
95     int type;
96     KeyCode keybut;     /* key or button */
97     WindowPtr confineTo;
98     CursorPtr cursor;
99 #endif
100 {
101     GrabPtr grab;
102
103     grab = (GrabPtr)xalloc(sizeof(GrabRec));
104     if (!grab)
105         return (GrabPtr)NULL;
106     grab->resource = FakeClientID(client);
107     grab->device = device;
108     grab->coreGrab = ((device == inputInfo.keyboard) ||
109                       (device == inputInfo.pointer));
110     grab->window = window;
111     grab->eventMask = eventMask;
112     grab->ownerEvents = ownerEvents;
113     grab->keyboardMode = keyboardMode;
114     grab->pointerMode = pointerMode;
115     grab->modifiersDetail.exact = modifiers;
116     grab->modifiersDetail.pMask = NULL;
117     grab->modifierDevice = modDevice;
118     grab->coreMods = ((modDevice == inputInfo.keyboard) ||
119                       (modDevice == inputInfo.pointer));
120     grab->type = type;
121     grab->detail.exact = keybut;
122     grab->detail.pMask = NULL;
123     grab->confineTo = confineTo;
124     grab->cursor = cursor;
125     if (cursor)
126         cursor->refcnt++;
127     return grab;
128
129 }
130
131 static void
132 #if NeedFunctionPrototypes
133 FreeGrab(GrabPtr pGrab)
134 #else
135 FreeGrab(pGrab)
136     GrabPtr pGrab;
137 #endif
138 {
139     if (pGrab->modifiersDetail.pMask != NULL)
140         xfree(pGrab->modifiersDetail.pMask);
141
142     if (pGrab->detail.pMask != NULL)
143         xfree(pGrab->detail.pMask);
144
145     if (pGrab->cursor)
146         FreeCursor(pGrab->cursor, (Cursor)0);
147
148     xfree(pGrab);
149 }
150
151 /*ARGSUSED*/
152 int
153 DeletePassiveGrab(value, id)
154     pointer value;
155     XID   id;
156 {
157     register GrabPtr g, prev;
158     GrabPtr pGrab = (GrabPtr)value;
159
160     /* it is OK if the grab isn't found */
161     prev = 0;
162     for (g = (wPassiveGrabs (pGrab->window)); g; g = g->next)
163     {
164         if (pGrab == g)
165         {
166             if (prev)
167                 prev->next = g->next;
168             else
169                 if (!(pGrab->window->optional->passiveGrabs = g->next))
170                     CheckWindowOptionalNeed (pGrab->window);
171             break;
172         }
173         prev = g;
174     }
175     FreeGrab(pGrab);
176     return Success;
177 }
178
179 static Mask *
180 #if NeedFunctionPrototypes
181 DeleteDetailFromMask(Mask *pDetailMask, unsigned short detail)
182 #else
183 DeleteDetailFromMask(pDetailMask, detail)
184     Mask *pDetailMask;
185     unsigned short detail;
186 #endif
187 {
188     register Mask *mask;
189     register int i;
190
191     mask = (Mask *)xalloc(sizeof(Mask) * MasksPerDetailMask);
192     if (mask)
193     {
194         if (pDetailMask)
195             for (i = 0; i < MasksPerDetailMask; i++)
196                 mask[i]= pDetailMask[i];
197         else
198             for (i = 0; i < MasksPerDetailMask; i++)
199                 mask[i]= ~0L;
200         BITCLEAR(mask, detail);
201     }
202     return mask; 
203 }
204
205 static Bool
206 #if NeedFunctionPrototypes
207 IsInGrabMask(
208     DetailRec firstDetail,
209     DetailRec secondDetail,
210     unsigned short exception)
211 #else
212 IsInGrabMask(firstDetail, secondDetail, exception)
213     DetailRec firstDetail, secondDetail;
214     unsigned short exception;
215 #endif
216 {
217     if (firstDetail.exact == exception)
218     {
219         if (firstDetail.pMask == NULL)
220             return TRUE;
221         
222         /* (at present) never called with two non-null pMasks */
223         if (secondDetail.exact == exception)
224             return FALSE;
225
226         if (GETBIT(firstDetail.pMask, secondDetail.exact))
227             return TRUE;
228     }
229     
230     return FALSE;
231 }
232
233 static Bool 
234 #if NeedFunctionPrototypes
235 IdenticalExactDetails(
236     unsigned short firstExact,
237     unsigned short secondExact,
238     unsigned short exception)
239 #else
240 IdenticalExactDetails(firstExact, secondExact, exception)
241     unsigned short firstExact, secondExact, exception;
242 #endif
243 {
244     if ((firstExact == exception) || (secondExact == exception))
245         return FALSE;
246    
247     if (firstExact == secondExact)
248         return TRUE;
249
250     return FALSE;
251 }
252
253 static Bool 
254 #if NeedFunctionPrototypes
255 DetailSupersedesSecond(
256     DetailRec firstDetail,
257     DetailRec secondDetail,
258     unsigned short exception)
259 #else
260 DetailSupersedesSecond(firstDetail, secondDetail, exception)
261     DetailRec firstDetail, secondDetail;
262     unsigned short exception;
263 #endif
264 {
265     if (IsInGrabMask(firstDetail, secondDetail, exception))
266         return TRUE;
267
268     if (IdenticalExactDetails(firstDetail.exact, secondDetail.exact,
269                               exception))
270         return TRUE;
271   
272     return FALSE;
273 }
274
275 static Bool
276 #if NeedFunctionPrototypes
277 GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
278 #else
279 GrabSupersedesSecond(pFirstGrab, pSecondGrab)
280     GrabPtr pFirstGrab, pSecondGrab;
281 #endif
282 {
283     if (!DetailSupersedesSecond(pFirstGrab->modifiersDetail,
284                                 pSecondGrab->modifiersDetail, 
285                                 (unsigned short)AnyModifier))
286         return FALSE;
287
288     if (DetailSupersedesSecond(pFirstGrab->detail,
289                                pSecondGrab->detail, (unsigned short)AnyKey))
290         return TRUE;
291  
292     return FALSE;
293 }
294
295 Bool
296 GrabMatchesSecond(pFirstGrab, pSecondGrab)
297     GrabPtr pFirstGrab, pSecondGrab;
298 {
299     if ((pFirstGrab->device != pSecondGrab->device) ||
300         (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) ||
301         (pFirstGrab->type != pSecondGrab->type))
302         return FALSE;
303
304     if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) ||
305         GrabSupersedesSecond(pSecondGrab, pFirstGrab))
306         return TRUE;
307  
308     if (DetailSupersedesSecond(pSecondGrab->detail, pFirstGrab->detail,
309                                (unsigned short)AnyKey) 
310         && 
311         DetailSupersedesSecond(pFirstGrab->modifiersDetail,
312                                pSecondGrab->modifiersDetail,
313                                (unsigned short)AnyModifier))
314         return TRUE;
315
316     if (DetailSupersedesSecond(pFirstGrab->detail, pSecondGrab->detail,
317                                (unsigned short)AnyKey)
318         && 
319         DetailSupersedesSecond(pSecondGrab->modifiersDetail,
320                                pFirstGrab->modifiersDetail,
321                                (unsigned short)AnyModifier))
322         return TRUE;
323
324     return FALSE;
325 }
326
327 int
328 AddPassiveGrabToList(pGrab)
329     GrabPtr pGrab;
330 {
331     GrabPtr grab;
332
333     for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
334     {
335         if (GrabMatchesSecond(pGrab, grab))
336         {
337             if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource))
338             {
339                 FreeGrab(pGrab);
340                 return BadAccess;
341             }
342         }
343     }
344
345     if (!pGrab->window->optional && !MakeWindowOptional (pGrab->window))
346     {
347         FreeGrab(pGrab);
348         return BadAlloc;
349     }
350     pGrab->next = pGrab->window->optional->passiveGrabs;
351     pGrab->window->optional->passiveGrabs = pGrab;
352     if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer)pGrab))
353         return Success;
354     return BadAlloc;
355 }
356
357 /* the following is kinda complicated, because we need to be able to back out
358  * if any allocation fails
359  */
360
361 Bool
362 DeletePassiveGrabFromList(pMinuendGrab)
363     GrabPtr pMinuendGrab;
364 {
365     register GrabPtr grab;
366     GrabPtr *deletes, *adds;
367     Mask ***updates, **details;
368     int i, ndels, nadds, nups;
369     Bool ok;
370
371 #define UPDATE(mask,exact) \
372         if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \
373           ok = FALSE; \
374         else \
375           updates[nups++] = &(mask)
376
377     i = 0;
378     for (grab = wPassiveGrabs(pMinuendGrab->window); grab; grab = grab->next)
379         i++;
380     if (!i)
381         return TRUE;
382     deletes = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr));
383     adds = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr));
384     updates = (Mask ***)ALLOCATE_LOCAL(i * sizeof(Mask **));
385     details = (Mask **)ALLOCATE_LOCAL(i * sizeof(Mask *));
386     if (!deletes || !adds || !updates || !details)
387     {
388         if (details) DEALLOCATE_LOCAL(details);
389         if (updates) DEALLOCATE_LOCAL(updates);
390         if (adds) DEALLOCATE_LOCAL(adds);
391         if (deletes) DEALLOCATE_LOCAL(deletes);
392         return FALSE;
393     }
394     ndels = nadds = nups = 0;
395     ok = TRUE;
396     for (grab = wPassiveGrabs(pMinuendGrab->window);
397          grab && ok;
398          grab = grab->next)
399     {
400         if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) ||
401             !GrabMatchesSecond(grab, pMinuendGrab))
402             continue;
403         if (GrabSupersedesSecond(pMinuendGrab, grab))
404         {
405             deletes[ndels++] = grab;
406         }
407         else if ((grab->detail.exact == AnyKey)
408                  && (grab->modifiersDetail.exact != AnyModifier))
409         {
410             UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
411         }
412         else if ((grab->modifiersDetail.exact == AnyModifier) 
413                  && (grab->detail.exact != AnyKey))
414         {
415             UPDATE(grab->modifiersDetail.pMask,
416                    pMinuendGrab->modifiersDetail.exact);
417         }
418         else if ((pMinuendGrab->detail.exact != AnyKey)
419                  && (pMinuendGrab->modifiersDetail.exact != AnyModifier))
420         {
421             GrabPtr pNewGrab;
422
423             UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
424
425             pNewGrab = CreateGrab(CLIENT_ID(grab->resource), grab->device,
426                                   grab->window, (Mask)grab->eventMask,
427                                   (Bool)grab->ownerEvents,
428                                   (Bool)grab->keyboardMode,
429                                   (Bool)grab->pointerMode,
430                                   grab->modifierDevice,
431                                   AnyModifier, (int)grab->type,
432                                   pMinuendGrab->detail.exact,
433                                   grab->confineTo, grab->cursor);
434             if (!pNewGrab)
435                 ok = FALSE;
436             else if (!(pNewGrab->modifiersDetail.pMask =
437                        DeleteDetailFromMask(grab->modifiersDetail.pMask,
438                                          pMinuendGrab->modifiersDetail.exact))
439                      ||
440                      (!pNewGrab->window->optional &&
441                       !MakeWindowOptional(pNewGrab->window)))
442             {
443                 FreeGrab(pNewGrab);
444                 ok = FALSE;
445             }
446             else if (!AddResource(pNewGrab->resource, RT_PASSIVEGRAB,
447                                   (pointer)pNewGrab))
448                 ok = FALSE;
449             else
450                 adds[nadds++] = pNewGrab;
451         }   
452         else if (pMinuendGrab->detail.exact == AnyKey)
453         {
454             UPDATE(grab->modifiersDetail.pMask,
455                    pMinuendGrab->modifiersDetail.exact);
456         }
457         else
458         {
459             UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
460         }
461     }
462
463     if (!ok)
464     {
465         for (i = 0; i < nadds; i++)
466             FreeResource(adds[i]->resource, RT_NONE);
467         for (i = 0; i < nups; i++)
468             xfree(details[i]);
469     }
470     else
471     {
472         for (i = 0; i < ndels; i++)
473             FreeResource(deletes[i]->resource, RT_NONE);
474         for (i = 0; i < nadds; i++)
475         {
476             grab = adds[i];
477             grab->next = grab->window->optional->passiveGrabs;
478             grab->window->optional->passiveGrabs = grab;
479         }
480         for (i = 0; i < nups; i++)
481         {
482             xfree(*updates[i]);
483             *updates[i] = details[i];
484         }
485     }
486     DEALLOCATE_LOCAL(details);
487     DEALLOCATE_LOCAL(updates);
488     DEALLOCATE_LOCAL(adds);
489     DEALLOCATE_LOCAL(deletes);
490     return ok;
491
492 #undef UPDATE
493 }