File indexing completed on 2024-05-12 05:37:18
0001 /* 0002 SPDX-FileCopyrightText: 2007 Fredrik Höglund <fredrik@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include "cursornotificationhandler.h" 0008 0009 #include <private/qtx11extras_p.h> 0010 0011 #include <X11/extensions/Xfixes.h> 0012 0013 /* 0014 * This class is a QWidget because we need an X window to 0015 * be able to receive XFixes events. We don't actually map 0016 * the widget. 0017 */ 0018 0019 CursorNotificationHandler::CursorNotificationHandler() 0020 : QWidget() 0021 , currentName(0) 0022 { 0023 Display *dpy = QX11Info::display(); 0024 int errorBase; 0025 haveXfixes = false; 0026 0027 // Request cursor change notification events 0028 if (XFixesQueryExtension(dpy, &fixesEventBase, &errorBase)) { 0029 int major, minor; 0030 XFixesQueryVersion(dpy, &major, &minor); 0031 0032 if (major >= 2) { 0033 XFixesSelectCursorInput(dpy, winId(), XFixesDisplayCursorNotifyMask); 0034 haveXfixes = true; 0035 } 0036 } 0037 } 0038 0039 CursorNotificationHandler::~CursorNotificationHandler() 0040 { 0041 } 0042 0043 QString CursorNotificationHandler::cursorName() 0044 { 0045 if (!haveXfixes) 0046 return QString(); 0047 0048 if (!currentName) { 0049 // Xfixes doesn't have a request for getting the current cursor name, 0050 // but it's included in the XFixesCursorImage struct. 0051 XFixesCursorImage *image = XFixesGetCursorImage(QX11Info::display()); 0052 currentName = image->atom; 0053 XFree(image); 0054 } 0055 0056 return cursorName(currentName); 0057 } 0058 0059 QString CursorNotificationHandler::cursorName(Atom cursor) 0060 { 0061 QString name; 0062 0063 // XGetAtomName() is a synchronous call, so we cache the name 0064 // in an atom<->string map the first time we see a name 0065 // to keep the X server round trips down. 0066 if (names.contains(cursor)) 0067 name = names[cursor]; 0068 else { 0069 char *data = XGetAtomName(QX11Info::display(), cursor); 0070 name = QString::fromUtf8(data); 0071 XFree(data); 0072 0073 names.insert(cursor, name); 0074 } 0075 0076 return name; 0077 } 0078 0079 bool CursorNotificationHandler::x11Event(XEvent *event) 0080 { 0081 if (event->type != fixesEventBase + XFixesCursorNotify) 0082 return false; 0083 0084 XFixesCursorNotifyEvent *xfe = reinterpret_cast<XFixesCursorNotifyEvent *>(event); 0085 currentName = xfe->cursor_name; 0086 0087 Q_EMIT cursorNameChanged(cursorName(currentName)); 0088 0089 return false; 0090 }