Xfixes.c revision 42d69509
14456fccdSmrg/* 24456fccdSmrg * $XFree86: xc/lib/Xfixes/Xfixes.c,v 1.1 2002/11/30 06:21:45 keithp Exp $ 34456fccdSmrg * 44456fccdSmrg * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. 54456fccdSmrg * 64456fccdSmrg * Permission to use, copy, modify, distribute, and sell this software and its 74456fccdSmrg * documentation for any purpose is hereby granted without fee, provided that 84456fccdSmrg * the above copyright notice appear in all copies and that both that 94456fccdSmrg * copyright notice and this permission notice appear in supporting 104456fccdSmrg * documentation, and that the name of Keith Packard not be used in 114456fccdSmrg * advertising or publicity pertaining to distribution of the software without 124456fccdSmrg * specific, written prior permission. Keith Packard makes no 134456fccdSmrg * representations about the suitability of this software for any purpose. It 144456fccdSmrg * is provided "as is" without express or implied warranty. 154456fccdSmrg * 164456fccdSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 174456fccdSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 184456fccdSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 194456fccdSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 204456fccdSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 214456fccdSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 224456fccdSmrg * PERFORMANCE OF THIS SOFTWARE. 234456fccdSmrg */ 244456fccdSmrg 254456fccdSmrg#ifdef HAVE_CONFIG_H 264456fccdSmrg#include <config.h> 274456fccdSmrg#endif 284456fccdSmrg#include "Xfixesint.h" 294456fccdSmrg 304456fccdSmrgXFixesExtInfo XFixesExtensionInfo; 314456fccdSmrgchar XFixesExtensionName[] = XFIXES_NAME; 324456fccdSmrg 334456fccdSmrgstatic int 344456fccdSmrgXFixesCloseDisplay (Display *dpy, XExtCodes *codes); 354456fccdSmrg 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 int ev; 534456fccdSmrg 544456fccdSmrg info = (XFixesExtDisplayInfo *) Xmalloc (sizeof (XFixesExtDisplayInfo)); 554456fccdSmrg if (!info) return NULL; 564456fccdSmrg info->display = dpy; 574456fccdSmrg 584456fccdSmrg info->codes = XInitExtension (dpy, ext_name); 594456fccdSmrg 604456fccdSmrg /* 614456fccdSmrg * if the server has the extension, then we can initialize the 624456fccdSmrg * appropriate function vectors 634456fccdSmrg */ 644456fccdSmrg if (info->codes) { 654456fccdSmrg xXFixesQueryVersionReply rep; 664456fccdSmrg xXFixesQueryVersionReq *req; 674456fccdSmrg XESetCloseDisplay (dpy, info->codes->extension, 684456fccdSmrg XFixesCloseDisplay); 694456fccdSmrg for (ev = info->codes->first_event; 704456fccdSmrg ev < info->codes->first_event + XFixesNumberEvents; 714456fccdSmrg ev++) 724456fccdSmrg { 734456fccdSmrg XESetWireToEvent (dpy, ev, XFixesWireToEvent); 744456fccdSmrg XESetEventToWire (dpy, ev, XFixesEventToWire); 754456fccdSmrg } 764456fccdSmrg /* 774456fccdSmrg * Get the version info 784456fccdSmrg */ 794456fccdSmrg LockDisplay (dpy); 804456fccdSmrg GetReq (XFixesQueryVersion, req); 814456fccdSmrg req->reqType = info->codes->major_opcode; 824456fccdSmrg req->xfixesReqType = X_XFixesQueryVersion; 834456fccdSmrg req->majorVersion = XFIXES_MAJOR; 844456fccdSmrg req->minorVersion = XFIXES_MINOR; 854456fccdSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) 864456fccdSmrg { 874456fccdSmrg UnlockDisplay (dpy); 884456fccdSmrg SyncHandle (); 894456fccdSmrg Xfree(info); 9042d69509Smrg return NULL; 914456fccdSmrg } 924456fccdSmrg info->major_version = rep.majorVersion; 934456fccdSmrg info->minor_version = rep.minorVersion; 944456fccdSmrg UnlockDisplay (dpy); 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 */ 1264456fccdSmrgstatic int 1274456fccdSmrgXFixesExtRemoveDisplay (XFixesExtInfo *extinfo, 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 1574456fccdSmrg Xfree ((char *) 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 * 1674456fccdSmrgXFixesExtFindDisplay (XFixesExtInfo *extinfo, 1684456fccdSmrg Display *dpy) 1694456fccdSmrg{ 1704456fccdSmrg XFixesExtDisplayInfo *info; 1714456fccdSmrg 1724456fccdSmrg /* 1734456fccdSmrg * see if this was the most recently accessed display 1744456fccdSmrg */ 1754456fccdSmrg 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) 2014456fccdSmrg info = XFixesExtAddDisplay (&XFixesExtensionInfo, dpy, 2024456fccdSmrg XFixesExtensionName); 2034456fccdSmrg return info; 2044456fccdSmrg} 2054456fccdSmrg 2064456fccdSmrgstatic int 2074456fccdSmrgXFixesCloseDisplay (Display *dpy, 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; 2744456fccdSmrg awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); 2754456fccdSmrg awire->subtype = aevent->subtype; 2764456fccdSmrg awire->window = aevent->window; 2774456fccdSmrg awire->owner = aevent->owner; 2784456fccdSmrg awire->selection = aevent->selection; 2794456fccdSmrg awire->timestamp = aevent->timestamp; 2804456fccdSmrg awire->selectionTimestamp = aevent->selection_timestamp; 2814456fccdSmrg return True; 2824456fccdSmrg } 2834456fccdSmrg case XFixesCursorNotify: { 2844456fccdSmrg XFixesCursorNotifyEvent *aevent; 2854456fccdSmrg xXFixesCursorNotifyEvent *awire; 2864456fccdSmrg awire = (xXFixesCursorNotifyEvent *) wire; 2874456fccdSmrg aevent = (XFixesCursorNotifyEvent *) event; 2884456fccdSmrg awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); 2894456fccdSmrg awire->subtype = aevent->subtype; 2904456fccdSmrg awire->window = aevent->window; 2914456fccdSmrg awire->timestamp = aevent->timestamp; 2924456fccdSmrg awire->cursorSerial = aevent->cursor_serial; 2934456fccdSmrg awire->name = aevent->cursor_name; 2944456fccdSmrg } 2954456fccdSmrg } 2964456fccdSmrg return False; 2974456fccdSmrg} 2984456fccdSmrg 2994456fccdSmrgBool 30042d69509SmrgXFixesQueryExtension (Display *dpy, 30142d69509Smrg int *event_base_return, 30242d69509Smrg int *error_base_return) 3034456fccdSmrg{ 3044456fccdSmrg XFixesExtDisplayInfo *info = XFixesFindDisplay (dpy); 3054456fccdSmrg 3064456fccdSmrg if (XFixesHasExtension(info)) 3074456fccdSmrg { 30842d69509Smrg *event_base_return = info->codes->first_event; 30942d69509Smrg *error_base_return = info->codes->first_error; 3104456fccdSmrg return True; 3114456fccdSmrg } 3124456fccdSmrg else 3134456fccdSmrg return False; 3144456fccdSmrg} 3154456fccdSmrg 3164456fccdSmrgStatus 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