14456fccdSmrg/* 24456fccdSmrg * 34456fccdSmrg * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. 44456fccdSmrg * 54456fccdSmrg * Permission to use, copy, modify, distribute, and sell this software and its 64456fccdSmrg * documentation for any purpose is hereby granted without fee, provided that 74456fccdSmrg * the above copyright notice appear in all copies and that both that 84456fccdSmrg * copyright notice and this permission notice appear in supporting 94456fccdSmrg * documentation, and that the name of Keith Packard not be used in 104456fccdSmrg * advertising or publicity pertaining to distribution of the software without 114456fccdSmrg * specific, written prior permission. Keith Packard makes no 124456fccdSmrg * representations about the suitability of this software for any purpose. It 134456fccdSmrg * is provided "as is" without express or implied warranty. 144456fccdSmrg * 154456fccdSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 164456fccdSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 174456fccdSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 184456fccdSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 194456fccdSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 204456fccdSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 214456fccdSmrg * PERFORMANCE OF THIS SOFTWARE. 224456fccdSmrg */ 234456fccdSmrg 244456fccdSmrg#ifdef HAVE_CONFIG_H 254456fccdSmrg#include <config.h> 264456fccdSmrg#endif 27a7e741d5Smrg#include <X11/Xfuncproto.h> 284456fccdSmrg#include "Xfixesint.h" 294456fccdSmrg 304456fccdSmrgXFixesExtInfo XFixesExtensionInfo; 314456fccdSmrgchar XFixesExtensionName[] = XFIXES_NAME; 324456fccdSmrg 334456fccdSmrgstatic int 344456fccdSmrgXFixesCloseDisplay (Display *dpy, XExtCodes *codes); 353e6c936aSmrg 364456fccdSmrgstatic Bool 374456fccdSmrgXFixesWireToEvent(Display *dpy, XEvent *event, xEvent *wire); 384456fccdSmrg 394456fccdSmrgstatic Status 404456fccdSmrgXFixesEventToWire(Display *dpy, XEvent *event, xEvent *wire); 414456fccdSmrg 424456fccdSmrg/* 434456fccdSmrg * XFixesExtAddDisplay - add a display to this extension. (Replaces 444456fccdSmrg * XextAddDisplay) 454456fccdSmrg */ 464456fccdSmrgstatic XFixesExtDisplayInfo * 474456fccdSmrgXFixesExtAddDisplay (XFixesExtInfo *extinfo, 484456fccdSmrg Display *dpy, 494456fccdSmrg char *ext_name) 504456fccdSmrg{ 514456fccdSmrg XFixesExtDisplayInfo *info; 524456fccdSmrg 53a7e741d5Smrg info = Xmalloc (sizeof (XFixesExtDisplayInfo)); 544456fccdSmrg if (!info) return NULL; 554456fccdSmrg info->display = dpy; 564456fccdSmrg 574456fccdSmrg info->codes = XInitExtension (dpy, ext_name); 584456fccdSmrg 594456fccdSmrg /* 603e6c936aSmrg * if the server has the extension, then we can initialize the 614456fccdSmrg * appropriate function vectors 624456fccdSmrg */ 634456fccdSmrg if (info->codes) { 644456fccdSmrg xXFixesQueryVersionReply rep; 654456fccdSmrg xXFixesQueryVersionReq *req; 663e6c936aSmrg XESetCloseDisplay (dpy, info->codes->extension, 674456fccdSmrg XFixesCloseDisplay); 68a7e741d5Smrg for (int ev = info->codes->first_event; 694456fccdSmrg ev < info->codes->first_event + XFixesNumberEvents; 704456fccdSmrg ev++) 714456fccdSmrg { 724456fccdSmrg XESetWireToEvent (dpy, ev, XFixesWireToEvent); 734456fccdSmrg XESetEventToWire (dpy, ev, XFixesEventToWire); 744456fccdSmrg } 754456fccdSmrg /* 764456fccdSmrg * Get the version info 774456fccdSmrg */ 784456fccdSmrg LockDisplay (dpy); 794456fccdSmrg GetReq (XFixesQueryVersion, req); 80a7e741d5Smrg req->reqType = (CARD8) info->codes->major_opcode; 814456fccdSmrg req->xfixesReqType = X_XFixesQueryVersion; 824456fccdSmrg req->majorVersion = XFIXES_MAJOR; 834456fccdSmrg req->minorVersion = XFIXES_MINOR; 843e6c936aSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) 854456fccdSmrg { 864456fccdSmrg UnlockDisplay (dpy); 874456fccdSmrg SyncHandle (); 884456fccdSmrg Xfree(info); 8942d69509Smrg return NULL; 904456fccdSmrg } 91a7e741d5Smrg info->major_version = (int) rep.majorVersion; 92a7e741d5Smrg info->minor_version = (int) rep.minorVersion; 934456fccdSmrg UnlockDisplay (dpy); 94521070a0Smrg SyncHandle (); 954456fccdSmrg } else { 964456fccdSmrg /* The server doesn't have this extension. 974456fccdSmrg * Use a private Xlib-internal extension to hang the close_display 984456fccdSmrg * hook on so that the "cache" (extinfo->cur) is properly cleaned. 994456fccdSmrg * (XBUG 7955) 1004456fccdSmrg */ 1014456fccdSmrg XExtCodes *codes = XAddExtension(dpy); 1024456fccdSmrg if (!codes) { 1034456fccdSmrg XFree(info); 1044456fccdSmrg return NULL; 1054456fccdSmrg } 1064456fccdSmrg XESetCloseDisplay (dpy, codes->extension, XFixesCloseDisplay); 1074456fccdSmrg } 1084456fccdSmrg 1094456fccdSmrg /* 1104456fccdSmrg * now, chain it onto the list 1114456fccdSmrg */ 1124456fccdSmrg _XLockMutex(_Xglobal_lock); 1134456fccdSmrg info->next = extinfo->head; 1144456fccdSmrg extinfo->head = info; 1154456fccdSmrg extinfo->cur = info; 1164456fccdSmrg extinfo->ndisplays++; 1174456fccdSmrg _XUnlockMutex(_Xglobal_lock); 1184456fccdSmrg return info; 1194456fccdSmrg} 1204456fccdSmrg 1214456fccdSmrg 1224456fccdSmrg/* 1234456fccdSmrg * XFixesExtRemoveDisplay - remove the indicated display from the 1244456fccdSmrg * extension object. (Replaces XextRemoveDisplay.) 1254456fccdSmrg */ 1263e6c936aSmrgstatic int 127a7e741d5SmrgXFixesExtRemoveDisplay (XFixesExtInfo *extinfo, const Display *dpy) 1284456fccdSmrg{ 1294456fccdSmrg XFixesExtDisplayInfo *info, *prev; 1304456fccdSmrg 1314456fccdSmrg /* 1324456fccdSmrg * locate this display and its back link so that it can be removed 1334456fccdSmrg */ 1344456fccdSmrg _XLockMutex(_Xglobal_lock); 1354456fccdSmrg prev = NULL; 1364456fccdSmrg for (info = extinfo->head; info; info = info->next) { 1374456fccdSmrg if (info->display == dpy) break; 1384456fccdSmrg prev = info; 1394456fccdSmrg } 1404456fccdSmrg if (!info) { 1414456fccdSmrg _XUnlockMutex(_Xglobal_lock); 1424456fccdSmrg return 0; /* hmm, actually an error */ 1434456fccdSmrg } 1444456fccdSmrg 1454456fccdSmrg /* 1464456fccdSmrg * remove the display from the list; handles going to zero 1474456fccdSmrg */ 1484456fccdSmrg if (prev) 1494456fccdSmrg prev->next = info->next; 1504456fccdSmrg else 1514456fccdSmrg extinfo->head = info->next; 1524456fccdSmrg 1534456fccdSmrg extinfo->ndisplays--; 1544456fccdSmrg if (info == extinfo->cur) extinfo->cur = NULL; /* flush cache */ 1554456fccdSmrg _XUnlockMutex(_Xglobal_lock); 1564456fccdSmrg 157a7e741d5Smrg Xfree (info); 1584456fccdSmrg return 1; 1594456fccdSmrg} 1604456fccdSmrg 1614456fccdSmrg/* 1624456fccdSmrg * XFixesExtFindDisplay - look for a display in this extension; keeps a 1634456fccdSmrg * cache of the most-recently used for efficiency. (Replaces 1644456fccdSmrg * XextFindDisplay.) 1654456fccdSmrg */ 1664456fccdSmrgstatic XFixesExtDisplayInfo * 1673e6c936aSmrgXFixesExtFindDisplay (XFixesExtInfo *extinfo, 168a7e741d5Smrg const Display *dpy) 1694456fccdSmrg{ 1704456fccdSmrg XFixesExtDisplayInfo *info; 1714456fccdSmrg 1724456fccdSmrg /* 1734456fccdSmrg * see if this was the most recently accessed display 1744456fccdSmrg */ 1753e6c936aSmrg if ((info = extinfo->cur) && info->display == dpy) 1764456fccdSmrg return info; 1774456fccdSmrg 1784456fccdSmrg /* 1794456fccdSmrg * look for display in list 1804456fccdSmrg */ 1814456fccdSmrg _XLockMutex(_Xglobal_lock); 1824456fccdSmrg for (info = extinfo->head; info; info = info->next) { 1834456fccdSmrg if (info->display == dpy) { 1844456fccdSmrg extinfo->cur = info; /* cache most recently used */ 1854456fccdSmrg _XUnlockMutex(_Xglobal_lock); 1864456fccdSmrg return info; 1874456fccdSmrg } 1884456fccdSmrg } 1894456fccdSmrg _XUnlockMutex(_Xglobal_lock); 1904456fccdSmrg 1914456fccdSmrg return NULL; 1924456fccdSmrg} 1934456fccdSmrg 1944456fccdSmrgXFixesExtDisplayInfo * 1954456fccdSmrgXFixesFindDisplay (Display *dpy) 1964456fccdSmrg{ 1974456fccdSmrg XFixesExtDisplayInfo *info; 1984456fccdSmrg 1994456fccdSmrg info = XFixesExtFindDisplay (&XFixesExtensionInfo, dpy); 2004456fccdSmrg if (!info) 2013e6c936aSmrg info = XFixesExtAddDisplay (&XFixesExtensionInfo, dpy, 2024456fccdSmrg XFixesExtensionName); 2034456fccdSmrg return info; 2044456fccdSmrg} 2053e6c936aSmrg 2064456fccdSmrgstatic int 207a7e741d5SmrgXFixesCloseDisplay (Display *dpy, _X_UNUSED XExtCodes *codes) 2084456fccdSmrg{ 2094456fccdSmrg return XFixesExtRemoveDisplay (&XFixesExtensionInfo, dpy); 2104456fccdSmrg} 2114456fccdSmrg 2124456fccdSmrgstatic Bool 2134456fccdSmrgXFixesWireToEvent(Display *dpy, XEvent *event, xEvent *wire) 2144456fccdSmrg{ 2154456fccdSmrg XFixesExtDisplayInfo *info = XFixesFindDisplay(dpy); 2164456fccdSmrg 2174456fccdSmrg XFixesCheckExtension(dpy, info, False); 2184456fccdSmrg 2194456fccdSmrg switch ((wire->u.u.type & 0x7F) - info->codes->first_event) 2204456fccdSmrg { 2214456fccdSmrg case XFixesSelectionNotify: { 2224456fccdSmrg XFixesSelectionNotifyEvent *aevent; 2234456fccdSmrg xXFixesSelectionNotifyEvent *awire; 2244456fccdSmrg awire = (xXFixesSelectionNotifyEvent *) wire; 2254456fccdSmrg aevent = (XFixesSelectionNotifyEvent *) event; 2264456fccdSmrg aevent->type = awire->type & 0x7F; 2274456fccdSmrg aevent->subtype = awire->subtype; 2284456fccdSmrg aevent->serial = _XSetLastRequestRead(dpy, 2294456fccdSmrg (xGenericReply *) wire); 2304456fccdSmrg aevent->send_event = (awire->type & 0x80) != 0; 2314456fccdSmrg aevent->display = dpy; 2324456fccdSmrg aevent->window = awire->window; 2334456fccdSmrg aevent->owner = awire->owner; 2344456fccdSmrg aevent->selection = awire->selection; 2354456fccdSmrg aevent->timestamp = awire->timestamp; 2364456fccdSmrg aevent->selection_timestamp = awire->selectionTimestamp; 2374456fccdSmrg return True; 2384456fccdSmrg } 2394456fccdSmrg case XFixesCursorNotify: { 2404456fccdSmrg XFixesCursorNotifyEvent *aevent; 2414456fccdSmrg xXFixesCursorNotifyEvent *awire; 2424456fccdSmrg awire = (xXFixesCursorNotifyEvent *) wire; 2434456fccdSmrg aevent = (XFixesCursorNotifyEvent *) event; 2444456fccdSmrg aevent->type = awire->type & 0x7F; 2454456fccdSmrg aevent->subtype = awire->subtype; 2464456fccdSmrg aevent->serial = _XSetLastRequestRead(dpy, 2474456fccdSmrg (xGenericReply *) wire); 2484456fccdSmrg aevent->send_event = (awire->type & 0x80) != 0; 2494456fccdSmrg aevent->display = dpy; 2504456fccdSmrg aevent->window = awire->window; 2514456fccdSmrg aevent->cursor_serial = awire->cursorSerial; 2524456fccdSmrg aevent->timestamp = awire->timestamp; 2534456fccdSmrg aevent->cursor_name = awire->name; 2544456fccdSmrg return True; 2554456fccdSmrg } 2564456fccdSmrg } 2574456fccdSmrg return False; 2584456fccdSmrg} 2594456fccdSmrg 2604456fccdSmrgstatic Status 2614456fccdSmrgXFixesEventToWire(Display *dpy, XEvent *event, xEvent *wire) 2624456fccdSmrg{ 2634456fccdSmrg XFixesExtDisplayInfo *info = XFixesFindDisplay(dpy); 2644456fccdSmrg 2654456fccdSmrg XFixesCheckExtension(dpy, info, False); 2664456fccdSmrg 2674456fccdSmrg switch ((event->type & 0x7F) - info->codes->first_event) 2684456fccdSmrg { 2694456fccdSmrg case XFixesSelectionNotify: { 2704456fccdSmrg XFixesSelectionNotifyEvent *aevent; 2714456fccdSmrg xXFixesSelectionNotifyEvent *awire; 2724456fccdSmrg awire = (xXFixesSelectionNotifyEvent *) wire; 2734456fccdSmrg aevent = (XFixesSelectionNotifyEvent *) event; 274a7e741d5Smrg awire->type = (CARD8) (aevent->type | (aevent->send_event ? 0x80 : 0)); 275a7e741d5Smrg awire->subtype = (CARD8) aevent->subtype; 276a7e741d5Smrg awire->window = (CARD32) aevent->window; 277a7e741d5Smrg awire->owner = (CARD32) aevent->owner; 278a7e741d5Smrg awire->selection = (CARD32) aevent->selection; 279a7e741d5Smrg awire->timestamp = (CARD32) aevent->timestamp; 280a7e741d5Smrg awire->selectionTimestamp = (CARD32) aevent->selection_timestamp; 2814456fccdSmrg return True; 2824456fccdSmrg } 2834456fccdSmrg case XFixesCursorNotify: { 2844456fccdSmrg XFixesCursorNotifyEvent *aevent; 2854456fccdSmrg xXFixesCursorNotifyEvent *awire; 2864456fccdSmrg awire = (xXFixesCursorNotifyEvent *) wire; 2874456fccdSmrg aevent = (XFixesCursorNotifyEvent *) event; 288a7e741d5Smrg awire->type = (CARD8) (aevent->type | (aevent->send_event ? 0x80 : 0)); 289a7e741d5Smrg awire->subtype = (CARD8) aevent->subtype; 290a7e741d5Smrg awire->window = (CARD32) aevent->window; 291a7e741d5Smrg awire->timestamp = (CARD32) aevent->timestamp; 292a7e741d5Smrg awire->cursorSerial = (CARD32) aevent->cursor_serial; 293a7e741d5Smrg awire->name = (CARD32) aevent->cursor_name; 2944456fccdSmrg } 2954456fccdSmrg } 2964456fccdSmrg return False; 2974456fccdSmrg} 2984456fccdSmrg 2993e6c936aSmrgBool 30042d69509SmrgXFixesQueryExtension (Display *dpy, 30142d69509Smrg int *event_base_return, 30242d69509Smrg int *error_base_return) 3034456fccdSmrg{ 3044456fccdSmrg XFixesExtDisplayInfo *info = XFixesFindDisplay (dpy); 3054456fccdSmrg 3063e6c936aSmrg if (XFixesHasExtension(info)) 3074456fccdSmrg { 30842d69509Smrg *event_base_return = info->codes->first_event; 30942d69509Smrg *error_base_return = info->codes->first_error; 3104456fccdSmrg return True; 3113e6c936aSmrg } 3124456fccdSmrg else 3134456fccdSmrg return False; 3144456fccdSmrg} 3154456fccdSmrg 3163e6c936aSmrgStatus 3174456fccdSmrgXFixesQueryVersion (Display *dpy, 31842d69509Smrg int *major_version_return, 31942d69509Smrg int *minor_version_return) 3204456fccdSmrg{ 3214456fccdSmrg XFixesExtDisplayInfo *info = XFixesFindDisplay (dpy); 3224456fccdSmrg 3234456fccdSmrg XFixesCheckExtension (dpy, info, 0); 3244456fccdSmrg 32542d69509Smrg *major_version_return = info->major_version; 32642d69509Smrg *minor_version_return = info->minor_version; 3274456fccdSmrg return 1; 3284456fccdSmrg} 3294456fccdSmrg 3304456fccdSmrgint 3314456fccdSmrgXFixesVersion (void) 3324456fccdSmrg{ 3334456fccdSmrg return XFIXES_VERSION; 3344456fccdSmrg} 335