xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

select.c (8351B)


      1 /*
      2  * Copyright © 2002 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that
      7  * copyright notice and this permission notice appear in supporting
      8  * documentation, and that the name of Keith Packard not be used in
      9  * advertising or publicity pertaining to distribution of the software without
     10  * specific, written prior permission.  Keith Packard makes no
     11  * representations about the suitability of this software for any purpose.  It
     12  * is provided "as is" without express or implied warranty.
     13  *
     14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     20  * PERFORMANCE OF THIS SOFTWARE.
     21  */
     22 
     23 #ifdef HAVE_DIX_CONFIG_H
     24 #include <dix-config.h>
     25 #endif
     26 
     27 #include "xfixesint.h"
     28 #include "xace.h"
     29 
     30 static RESTYPE SelectionClientType, SelectionWindowType;
     31 static Bool SelectionCallbackRegistered = FALSE;
     32 
     33 /*
     34  * There is a global list of windows selecting for selection events
     35  * on every selection.  This should be plenty efficient for the
     36  * expected usage, if it does become a problem, it should be easily
     37  * replaced with a hash table of some kind keyed off the selection atom
     38  */
     39 
     40 typedef struct _SelectionEvent *SelectionEventPtr;
     41 
     42 typedef struct _SelectionEvent {
     43     SelectionEventPtr next;
     44     Atom selection;
     45     CARD32 eventMask;
     46     ClientPtr pClient;
     47     WindowPtr pWindow;
     48     XID clientResource;
     49 } SelectionEventRec;
     50 
     51 static SelectionEventPtr selectionEvents;
     52 
     53 static void
     54 XFixesSelectionCallback(CallbackListPtr *callbacks, void *data, void *args)
     55 {
     56     SelectionEventPtr e;
     57     SelectionInfoRec *info = (SelectionInfoRec *) args;
     58     Selection *selection = info->selection;
     59     int subtype;
     60     CARD32 eventMask;
     61 
     62     switch (info->kind) {
     63     case SelectionSetOwner:
     64         subtype = XFixesSetSelectionOwnerNotify;
     65         eventMask = XFixesSetSelectionOwnerNotifyMask;
     66         break;
     67     case SelectionWindowDestroy:
     68         subtype = XFixesSelectionWindowDestroyNotify;
     69         eventMask = XFixesSelectionWindowDestroyNotifyMask;
     70         break;
     71     case SelectionClientClose:
     72         subtype = XFixesSelectionClientCloseNotify;
     73         eventMask = XFixesSelectionClientCloseNotifyMask;
     74         break;
     75     default:
     76         return;
     77     }
     78     UpdateCurrentTimeIf();
     79     for (e = selectionEvents; e; e = e->next) {
     80         if (e->selection == selection->selection && (e->eventMask & eventMask)) {
     81             xXFixesSelectionNotifyEvent ev = {
     82                 .type = XFixesEventBase + XFixesSelectionNotify,
     83                 .subtype = subtype,
     84                 .window = e->pWindow->drawable.id,
     85                 .owner = (subtype == XFixesSetSelectionOwnerNotify) ?
     86                             selection->window : 0,
     87                 .selection = e->selection,
     88                 .timestamp = currentTime.milliseconds,
     89                 .selectionTimestamp = selection->lastTimeChanged.milliseconds
     90             };
     91             WriteEventsToClient(e->pClient, 1, (xEvent *) &ev);
     92         }
     93     }
     94 }
     95 
     96 static Bool
     97 CheckSelectionCallback(void)
     98 {
     99     if (selectionEvents) {
    100         if (!SelectionCallbackRegistered) {
    101             if (!AddCallback(&SelectionCallback, XFixesSelectionCallback, NULL))
    102                 return FALSE;
    103             SelectionCallbackRegistered = TRUE;
    104         }
    105     }
    106     else {
    107         if (SelectionCallbackRegistered) {
    108             DeleteCallback(&SelectionCallback, XFixesSelectionCallback, NULL);
    109             SelectionCallbackRegistered = FALSE;
    110         }
    111     }
    112     return TRUE;
    113 }
    114 
    115 #define SelectionAllEvents (XFixesSetSelectionOwnerNotifyMask |\
    116 			    XFixesSelectionWindowDestroyNotifyMask |\
    117 			    XFixesSelectionClientCloseNotifyMask)
    118 
    119 static int
    120 XFixesSelectSelectionInput(ClientPtr pClient,
    121                            Atom selection, WindowPtr pWindow, CARD32 eventMask)
    122 {
    123     void *val;
    124     int rc;
    125     SelectionEventPtr *prev, e;
    126 
    127     rc = XaceHook(XACE_SELECTION_ACCESS, pClient, selection, DixGetAttrAccess);
    128     if (rc != Success)
    129         return rc;
    130 
    131     for (prev = &selectionEvents; (e = *prev); prev = &e->next) {
    132         if (e->selection == selection &&
    133             e->pClient == pClient && e->pWindow == pWindow) {
    134             break;
    135         }
    136     }
    137     if (!eventMask) {
    138         if (e) {
    139             FreeResource(e->clientResource, 0);
    140         }
    141         return Success;
    142     }
    143     if (!e) {
    144         e = (SelectionEventPtr) malloc(sizeof(SelectionEventRec));
    145         if (!e)
    146             return BadAlloc;
    147 
    148         e->next = 0;
    149         e->selection = selection;
    150         e->pClient = pClient;
    151         e->pWindow = pWindow;
    152         e->clientResource = FakeClientID(pClient->index);
    153 
    154         /*
    155          * Add a resource hanging from the window to
    156          * catch window destroy
    157          */
    158         rc = dixLookupResourceByType(&val, pWindow->drawable.id,
    159                                      SelectionWindowType, serverClient,
    160                                      DixGetAttrAccess);
    161         if (rc != Success)
    162             if (!AddResource(pWindow->drawable.id, SelectionWindowType,
    163                              (void *) pWindow)) {
    164                 free(e);
    165                 return BadAlloc;
    166             }
    167 
    168         if (!AddResource(e->clientResource, SelectionClientType, (void *) e))
    169             return BadAlloc;
    170 
    171         *prev = e;
    172         if (!CheckSelectionCallback()) {
    173             FreeResource(e->clientResource, 0);
    174             return BadAlloc;
    175         }
    176     }
    177     e->eventMask = eventMask;
    178     return Success;
    179 }
    180 
    181 int
    182 ProcXFixesSelectSelectionInput(ClientPtr client)
    183 {
    184     REQUEST(xXFixesSelectSelectionInputReq);
    185     WindowPtr pWin;
    186     int rc;
    187 
    188     REQUEST_SIZE_MATCH(xXFixesSelectSelectionInputReq);
    189     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    190     if (rc != Success)
    191         return rc;
    192     if (stuff->eventMask & ~SelectionAllEvents) {
    193         client->errorValue = stuff->eventMask;
    194         return BadValue;
    195     }
    196     return XFixesSelectSelectionInput(client, stuff->selection,
    197                                       pWin, stuff->eventMask);
    198 }
    199 
    200 int _X_COLD
    201 SProcXFixesSelectSelectionInput(ClientPtr client)
    202 {
    203     REQUEST(xXFixesSelectSelectionInputReq);
    204 
    205     REQUEST_SIZE_MATCH(xXFixesSelectSelectionInputReq);
    206     swaps(&stuff->length);
    207     swapl(&stuff->window);
    208     swapl(&stuff->selection);
    209     swapl(&stuff->eventMask);
    210     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
    211 }
    212 
    213 void _X_COLD
    214 SXFixesSelectionNotifyEvent(xXFixesSelectionNotifyEvent * from,
    215                             xXFixesSelectionNotifyEvent * to)
    216 {
    217     to->type = from->type;
    218     cpswaps(from->sequenceNumber, to->sequenceNumber);
    219     cpswapl(from->window, to->window);
    220     cpswapl(from->owner, to->owner);
    221     cpswapl(from->selection, to->selection);
    222     cpswapl(from->timestamp, to->timestamp);
    223     cpswapl(from->selectionTimestamp, to->selectionTimestamp);
    224 }
    225 
    226 static int
    227 SelectionFreeClient(void *data, XID id)
    228 {
    229     SelectionEventPtr old = (SelectionEventPtr) data;
    230     SelectionEventPtr *prev, e;
    231 
    232     for (prev = &selectionEvents; (e = *prev); prev = &e->next) {
    233         if (e == old) {
    234             *prev = e->next;
    235             free(e);
    236             CheckSelectionCallback();
    237             break;
    238         }
    239     }
    240     return 1;
    241 }
    242 
    243 static int
    244 SelectionFreeWindow(void *data, XID id)
    245 {
    246     WindowPtr pWindow = (WindowPtr) data;
    247     SelectionEventPtr e, next;
    248 
    249     for (e = selectionEvents; e; e = next) {
    250         next = e->next;
    251         if (e->pWindow == pWindow) {
    252             FreeResource(e->clientResource, 0);
    253         }
    254     }
    255     return 1;
    256 }
    257 
    258 Bool
    259 XFixesSelectionInit(void)
    260 {
    261     SelectionClientType = CreateNewResourceType(SelectionFreeClient,
    262                                                 "XFixesSelectionClient");
    263     SelectionWindowType = CreateNewResourceType(SelectionFreeWindow,
    264                                                 "XFixesSelectionWindow");
    265     return SelectionClientType && SelectionWindowType;
    266 }