1 /* antimicro Gamepad to KB+M event mapper
2  * Copyright (C) 2015 Travis Nickles <nickles.travis@gmail.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13 
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <unistd.h>
19 //#include <QDebug>
20 #include <QFileInfo>
21 #include <QThreadStorage>
22 
23 #include "common.h"
24 
25 #include <X11/Xatom.h>
26 #include <X11/XKBlib.h>
27 #include <X11/extensions/XInput.h>
28 #include <X11/extensions/XInput2.h>
29 
30 #include "x11extras.h"
31 
32 const QString X11Extras::mouseDeviceName = PadderCommon::mouseDeviceName;
33 const QString X11Extras::keyboardDeviceName = PadderCommon::keyboardDeviceName;
34 const QString X11Extras::xtestMouseDeviceName = QString("Virtual core XTEST pointer");
35 
36 QString X11Extras::_customDisplayString = QString("");
37 
38 static QThreadStorage<X11Extras*> displays;
39 
40 X11Extras* X11Extras::_instance = 0;
41 
X11Extras(QObject * parent)42 X11Extras::X11Extras(QObject *parent) :
43     QObject(parent),
44     knownAliases()
45 {
46     //knownAliases = QHash<QString, QString> ();
47     _display = XOpenDisplay(NULL);
48     populateKnownAliases();
49 }
50 
51 /**
52  * @brief Close display connection if one exists
53  */
~X11Extras()54 X11Extras::~X11Extras()
55 {
56     if (_display)
57     {
58         XCloseDisplay(display());
59         _display = 0;
60         //_customDisplayString = "";
61     }
62 }
63 
getInstance()64 X11Extras *X11Extras::getInstance()
65 {
66     /*if (!_instance)
67     {
68         _instance = new X11Extras();
69     }
70 
71     return _instance;
72     */
73     X11Extras *temp = 0;
74     if (!displays.hasLocalData())
75     {
76         temp = new X11Extras();
77         displays.setLocalData(temp);
78     }
79     else
80     {
81         temp = displays.localData();
82     }
83 
84     return temp;
85 }
86 
deleteInstance()87 void X11Extras::deleteInstance()
88 {
89     /*if (_instance)
90     {
91         delete _instance;
92         _instance = 0;
93     }
94     */
95     if (displays.hasLocalData())
96     {
97         X11Extras *temp = displays.localData();
98         delete temp;
99         displays.setLocalData(0);
100     }
101 }
102 
103 /**
104  * @brief Get display instance
105  * @return Display struct
106  */
display()107 Display* X11Extras::display()
108 {
109     return _display;
110 }
111 
hasValidDisplay()112 bool X11Extras::hasValidDisplay()
113 {
114     bool result = _display != NULL;
115     return result;
116 }
117 
118 /**
119  * @brief CURRENTLY NOT USED
120  */
closeDisplay()121 void X11Extras::closeDisplay()
122 {
123     if (_display)
124     {
125         XCloseDisplay(display());
126         _display = 0;
127         //_customDisplayString = "";
128     }
129 }
130 
131 /**
132  * @brief Grab instance of active display.
133  */
syncDisplay()134 void X11Extras::syncDisplay()
135 {
136     _display = XOpenDisplay(NULL);
137     //_customDisplayString = "";
138 }
139 
140 /**
141  * @brief Grab instance of specified display. Useful for having the GUI
142  *     on one display while generating events on another during ssh tunneling.
143  * @param Valid display string that X can use
144  */
syncDisplay(QString displayString)145 void X11Extras::syncDisplay(QString displayString)
146 {
147     QByteArray tempByteArray = displayString.toLocal8Bit();
148     _display = XOpenDisplay(tempByteArray.constData());
149     /*if (_display)
150     {
151         _customDisplayString = displayString;
152     }
153     else
154     {
155         _customDisplayString = "";
156     }
157     */
158 }
159 
setCustomDisplay(QString displayString)160 void X11Extras::setCustomDisplay(QString displayString)
161 {
162     _customDisplayString = displayString;
163 }
164 
165 /**
166  * @brief Return root window for a given X display
167  * @param Screen number. If no value is passed, uses screen 1.
168  * @return XID of the window
169  */
appRootWindow(int screen)170 unsigned long X11Extras::appRootWindow(int screen)
171 {
172     return screen == -1 ? XDefaultRootWindow(display()) : XRootWindowOfScreen(XScreenOfDisplay(display(), screen));
173 }
174 
175 /**
176  * @brief Get appropriate alias for a known KeySym string that might be blank
177  *     or contain invalid characters when returned from X.
178  * @param QString representation of a KeySym string
179  * @return Alias string or a blank QString if no alias was found
180  */
getDisplayString(QString xcodestring)181 QString X11Extras::getDisplayString(QString xcodestring)
182 {
183     QString temp;
184     if (knownAliases.contains(xcodestring))
185     {
186         temp = knownAliases.value(xcodestring);
187     }
188 
189     return temp;
190 }
191 
populateKnownAliases()192 void X11Extras::populateKnownAliases()
193 {
194     // These aliases are needed for xstrings that would
195     // return empty space characters from XLookupString
196     if (knownAliases.isEmpty())
197     {
198         knownAliases.insert("Escape", tr("ESC"));
199         knownAliases.insert("Tab", tr("Tab"));
200         knownAliases.insert("space", tr("Space"));
201         knownAliases.insert("Delete", tr("DEL"));
202         knownAliases.insert("Return", tr("Return"));
203         knownAliases.insert("KP_Enter", tr("KP_Enter"));
204         knownAliases.insert("BackSpace", tr("Backspace"));
205     }
206 }
207 
findParentClient(Window window)208 Window X11Extras::findParentClient(Window window)
209 {
210     Window parent = 0;
211     Window root = 0;
212     Window *children = 0;
213     unsigned int num_children = 0;
214     Window finalwindow = 0;
215     Display *display = this->display();
216 
217     if (windowIsViewable(display, window) &&
218         isWindowRelevant(display, window))
219     {
220         finalwindow = window;
221     }
222     else
223     {
224         bool quitTraversal = false;
225         while (!quitTraversal)
226         {
227             children = 0;
228 
229             if (XQueryTree(display, window, &root, &parent, &children, &num_children))
230             {
231                 if (children)
232                 {
233                     // must test for NULL
234                     XFree(children);
235                 }
236 
237                 if (parent)
238                 {
239                     if (windowIsViewable(display, parent) &&
240                         isWindowRelevant(display, parent))
241                     {
242                         quitTraversal = true;
243                         finalwindow = parent;
244                     }
245                     else if (parent == 0)
246                     {
247                         quitTraversal = true;
248                     }
249                     else if (parent == root)
250                     {
251                         quitTraversal = true;
252                     }
253                     else
254                     {
255                         window = parent;
256                     }
257                 }
258                 else
259                 {
260                     quitTraversal = true;
261                 }
262             }
263             else
264             {
265                 quitTraversal = true;
266             }
267         }
268     }
269 
270     return finalwindow;
271 }
272 
273 /**
274  * @brief Check window and any parents for the window property "_NET_WM_PID"
275  * @param Window XID for window of interest
276  * @return PID of the application instance corresponding to the window
277  */
getApplicationPid(Window window)278 int X11Extras::getApplicationPid(Window window)
279 {
280     Atom atom, actual_type;
281     int actual_format = 0;
282     unsigned long nitems = 0;
283     unsigned long bytes_after = 0;
284     unsigned char *prop = 0;
285     int status = 0;
286     int pid = 0;
287     Window finalwindow = 0;
288 
289     Display *display = this->display();
290     atom = XInternAtom(display, "_NET_WM_PID", True);
291     if (windowHasProperty(display, window, atom))
292     {
293         finalwindow = window;
294     }
295     else
296     {
297         Window parent = 0;
298         Window root = 0;
299         Window *children;
300         unsigned int num_children;
301         bool quitTraversal = false;
302 
303         while (!quitTraversal)
304         {
305             children = 0;
306 
307             if (XQueryTree(display, window, &root, &parent, &children, &num_children))
308             {
309                 if (children)
310                 {
311                     // must test for NULL
312                     XFree(children);
313                 }
314 
315                 if (parent)
316                 {
317                     if (windowHasProperty(display, parent, atom))
318                     {
319                         quitTraversal = true;
320                         finalwindow = parent;
321                     }
322                     else if (parent == 0)
323                     {
324                         quitTraversal = true;
325                     }
326                     else if (parent == root)
327                     {
328                         quitTraversal = true;
329                     }
330                     else
331                     {
332                         window = parent;
333                     }
334                 }
335                 else
336                 {
337                     quitTraversal = true;
338                 }
339             }
340             else
341             {
342                 quitTraversal = true;
343             }
344         }
345     }
346 
347     if (finalwindow)
348     {
349         status = XGetWindowProperty(display, finalwindow, atom, 0, 1024, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
350         if (status == 0 && prop)
351         {
352             pid = prop[1] << 8;
353             pid += prop[0];
354             XFree(prop);
355         }
356     }
357 
358     return pid;
359 }
360 
361 /**
362  * @brief Find the application file location for a given PID
363  * @param PID of window
364  * @return File location of application
365  */
getApplicationLocation(int pid)366 QString X11Extras::getApplicationLocation(int pid)
367 {
368     QString exepath;
369     if (pid > 0)
370     {
371         QString procString = QString("/proc/%1/exe").arg(pid);
372         QFileInfo procFileInfo(procString);
373         if (procFileInfo.exists())
374         {
375             char buf[1024];
376             QByteArray tempByteArray = procString.toLocal8Bit();
377             ssize_t len = readlink(tempByteArray.constData(), buf, sizeof(buf)-1);
378             if (len != -1)
379             {
380                 buf[len] = '\0';
381             }
382 
383             if (len > 0)
384             {
385                 QString temp = QString::fromUtf8(buf);
386                 if (!temp.isEmpty())
387                 {
388                     exepath = temp;
389                 }
390             }
391         }
392     }
393 
394     return exepath;
395 }
396 
397 /**
398  * @brief Find the proper client window within a hierarchy. This check is needed
399  *     in some environments where the window that has been selected is actually
400  *     a child to a transparent parent window which was the one that was
401  *     actually grabbed
402  * @param Top window to check
403  * @return Client window XID or 0 if no appropriate window was found
404  */
findClientWindow(Window window)405 Window X11Extras::findClientWindow(Window window)
406 {
407     Window parent = 1;
408     Window root = 0;
409     Window *children = 0;
410     unsigned int num_children = 0;
411     Window finalwindow = 0;
412     Display *display = this->display();
413 
414     if (windowIsViewable(display, window) &&
415         isWindowRelevant(display, window))
416     {
417         finalwindow = window;
418     }
419     else
420     {
421         XQueryTree(display, window, &root, &parent, &children, &num_children);
422         if (children)
423         {
424             for (unsigned int i = 0; i < num_children && !finalwindow; i++)
425             {
426                 if (windowIsViewable(display, children[i]) &&
427                     isWindowRelevant(display, window))
428                 {
429                     finalwindow = children[i];
430                 }
431             }
432         }
433 
434         if (!finalwindow && children)
435         {
436             for (unsigned int i = 0; i < num_children && !finalwindow; i++)
437             {
438                 finalwindow = findClientWindow(children[i]);
439             }
440         }
441 
442         if (children)
443         {
444             XFree(children);
445             children = 0;
446         }
447     }
448 
449     return finalwindow;
450 }
451 
windowHasProperty(Display * display,Window window,Atom atom)452 bool X11Extras::windowHasProperty(Display *display, Window window, Atom atom)
453 {
454     bool result = false;
455 
456     Atom actual_type;
457     int actual_format = 0;
458     unsigned long nitems = 0;
459     unsigned long bytes_after = 0;
460     unsigned char *prop = 0;
461     int status = 0;
462     status = XGetWindowProperty(display, window, atom, 0, 1024, false, AnyPropertyType,
463                                 &actual_type, &actual_format, &nitems, &bytes_after,
464                                 &prop);
465 
466     if (status == Success && prop)
467     {
468         result = true;
469     }
470 
471     if (prop)
472     {
473         XFree(prop);
474         prop = 0;
475     }
476 
477     return result;
478 }
479 
windowIsViewable(Display * display,Window window)480 bool X11Extras::windowIsViewable(Display *display, Window window)
481 {
482     bool result = false;
483     XWindowAttributes xwa;
484     XGetWindowAttributes(display, window, &xwa);
485     if (xwa.c_class == InputOutput && xwa.map_state == IsViewable)
486     {
487         result = true;
488     }
489 
490     return result;
491 }
492 
493 /**
494  * @brief Go through a window's properties and search for an Atom
495  *     from a defined list. If an Atom is found in a window's properties,
496  *     that window should be considered relevant and one that should be grabbed.
497  * @param Display*
498  * @param Window
499  * @return If a window has a relevant Atom in its properties.
500  */
isWindowRelevant(Display * display,Window window)501 bool X11Extras::isWindowRelevant(Display *display, Window window)
502 {
503     bool result = false;
504 
505     QList<Atom> temp;
506     temp.append(XInternAtom(display, "WM_STATE", True));
507     temp.append(XInternAtom(display, "_NW_WM_STATE", True));
508     temp.append(XInternAtom(display, "_NW_WM_NAME", True));
509 
510     QListIterator<Atom> iter(temp);
511     while (iter.hasNext())
512     {
513         Atom current_atom = iter.next();
514         if (windowHasProperty(display, window, current_atom))
515         {
516             iter.toBack();
517             result = true;
518         }
519     }
520 
521     return result;
522 }
523 
getWindowTitle(Window window)524 QString X11Extras::getWindowTitle(Window window)
525 {
526     QString temp;
527 
528     Atom atom, actual_type;
529     int actual_format = 0;
530     unsigned long nitems = 0;
531     unsigned long bytes_after = 0;
532     unsigned char *prop = 0;
533     int status = 0;
534 
535     //qDebug() << "WIN: 0x" << QString::number(window, 16);
536 
537     Display *display = this->display();
538     Atom wm_name = XInternAtom(display, "WM_NAME", True);
539     Atom net_wm_name = XInternAtom(display, "_NET_WM_NAME", True);
540     atom = wm_name;
541 
542     QList<Atom> tempList;
543     tempList.append(wm_name);
544     tempList.append(net_wm_name);
545     QListIterator<Atom> iter(tempList);
546     while (iter.hasNext())
547     {
548         Atom temp_atom = iter.next();
549         if (windowHasProperty(display, window, temp_atom))
550         {
551             iter.toBack();
552             atom = temp_atom;
553         }
554     }
555 
556     status = XGetWindowProperty(display, window, atom, 0, 1024, false, AnyPropertyType,
557                                 &actual_type, &actual_format, &nitems, &bytes_after,
558                                 &prop);
559 
560     if (status == Success && prop)
561     {
562         char *tempprop = (char*)prop;
563         temp.append(QString::fromUtf8(tempprop));
564         //qDebug() << temp;
565     }
566 
567     if (prop)
568     {
569         XFree(prop);
570         prop = 0;
571     }
572 
573     return temp;
574 }
575 
getWindowClass(Window window)576 QString X11Extras::getWindowClass(Window window)
577 {
578     QString temp;
579 
580     Atom atom, actual_type;
581     int actual_format = 0;
582     unsigned long nitems = 0;
583     unsigned long bytes_after = 0;
584     unsigned char *prop = 0;
585     int status = 0;
586 
587     Display *display = this->display();
588     atom = XInternAtom(display, "WM_CLASS", True);
589     status = XGetWindowProperty(display, window, atom, 0, 1024, false, AnyPropertyType,
590                                 &actual_type, &actual_format, &nitems, &bytes_after,
591                                 &prop);
592 
593     if (status == Success && prop)
594     {
595         //qDebug() << nitems;
596         char *null_char = strchr((char*)prop, '\0');
597         if ((char*)prop + nitems - 1 > null_char)
598         {
599             *(null_char) = ' ';
600         }
601 
602         char *tempprop = (char*)prop;
603         temp.append(QString::fromUtf8(tempprop));
604         //qDebug() << temp;
605         //qDebug() << (char*)prop;
606     }
607 
608     if (prop)
609     {
610         XFree(prop);
611         prop = 0;
612     }
613 
614     return temp;
615 }
616 
getWindowInFocus()617 unsigned long X11Extras::getWindowInFocus()
618 {
619     unsigned long result = 0;
620 
621     Window currentWindow = 0;
622     int focusState = 0;
623 
624     Display *display = this->display();
625     XGetInputFocus(display, &currentWindow, &focusState);
626 
627     if (currentWindow > 0)
628     {
629         result = static_cast<unsigned long>(currentWindow);
630     }
631 
632     return result;
633 }
634 
635 /**
636  * @brief Get QString representation of currently utilized X display.
637  * @return
638  */
getXDisplayString()639 QString X11Extras::getXDisplayString()
640 {
641     return _customDisplayString;
642 }
643 
getGroup1KeySym(unsigned int virtualkey)644 unsigned int X11Extras::getGroup1KeySym(unsigned int virtualkey)
645 {
646     unsigned int result = 0;
647     Display *display = this->display();
648 
649     unsigned int temp = XKeysymToKeycode(display, virtualkey);
650     result = XkbKeycodeToKeysym(display, temp, 0, 0);
651 
652     return result;
653 }
654 
x11ResetMouseAccelerationChange(QString pointerName)655 void X11Extras::x11ResetMouseAccelerationChange(QString pointerName)
656  {
657     int xi_opcode, event, error;
658     xi_opcode = event = error = 0;
659     Display *display = this->display();
660 
661     bool result = XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error);
662     if (!result)
663     {
664         Logger::LogInfo(tr("xinput extension was not found. No mouse acceleration changes will occur."));
665     }
666     else
667     {
668         int ximajor = 2, ximinor = 0;
669         if (XIQueryVersion(display, &ximajor, &ximinor) != Success)
670         {
671             Logger::LogInfo(tr("xinput version must be at least 2.0. No mouse acceleration changes will occur."));
672             result = false;
673         }
674     }
675 
676     if (result)
677     {
678         XIDeviceInfo *all_devices = 0;
679         XIDeviceInfo *current_devices = 0;
680         XIDeviceInfo *mouse_device = 0;
681 
682         int num_devices = 0;
683         all_devices = XIQueryDevice(display, XIAllDevices, &num_devices);
684         for (int i=0; i < num_devices; i++)
685         {
686             current_devices = &all_devices[i];
687             if (current_devices->use == XISlavePointer &&
688                 QString::fromUtf8(current_devices->name) == pointerName)
689             {
690                 Logger::LogInfo(tr("Virtual pointer found with id=%1.").arg(current_devices->deviceid));
691                 mouse_device = current_devices;
692             }
693         }
694 
695         if (mouse_device)
696         {
697             XDevice *device = XOpenDevice(display, mouse_device->deviceid);
698 
699             int num_feedbacks = 0;
700             int feedback_id = -1;
701             XFeedbackState *feedbacks = XGetFeedbackControl(display, device, &num_feedbacks);
702             XFeedbackState *temp = feedbacks;
703             for (int i=0; (i < num_feedbacks) && (feedback_id == -1); i++)
704             {
705                 if (temp->c_class == PtrFeedbackClass)
706                 {
707                     feedback_id = temp->id;
708                 }
709 
710                 if (i+1 < num_feedbacks)
711                 {
712                     temp = (XFeedbackState*) ((char*) temp + temp->length);
713                 }
714             }
715 
716             XFree(feedbacks);
717             feedbacks = temp = 0;
718 
719             if (feedback_id <= -1)
720             {
721                 Logger::LogInfo(tr("PtrFeedbackClass was not found for virtual pointer."
722                                    "No change to mouse acceleration will occur for device with id=%1").arg(device->device_id));
723 
724                 result = false;
725             }
726             else
727             {
728                 Logger::LogInfo(tr("Changing mouse acceleration for device with id=%1").arg(device->device_id));
729 
730                 XPtrFeedbackControl	feedback;
731                 feedback.c_class = PtrFeedbackClass;
732                 feedback.length = sizeof(XPtrFeedbackControl);
733                 feedback.id = feedback_id;
734                 feedback.threshold = 0;
735                 feedback.accelNum = 1;
736                 feedback.accelDenom = 1;
737 
738                 XChangeFeedbackControl(display, device, DvAccelNum|DvAccelDenom|DvThreshold,
739                            (XFeedbackControl*) &feedback);
740 
741                 XSync(display, false);
742             }
743 
744             XCloseDevice(display, device);
745         }
746 
747         if (all_devices)
748         {
749             XIFreeDeviceInfo(all_devices);
750         }
751      }
752  }
753 
x11ResetMouseAccelerationChange()754 void X11Extras::x11ResetMouseAccelerationChange()
755 {
756     x11ResetMouseAccelerationChange(mouseDeviceName);
757 }
758 
getPointInformation(QString pointerName)759 struct X11Extras::ptrInformation X11Extras::getPointInformation(QString pointerName)
760 {
761     struct ptrInformation tempInfo;
762 
763     int xi_opcode, event, error;
764     xi_opcode = event = error = 0;
765     Display *display = this->display();
766 
767     bool result = XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error);
768     if (result)
769     {
770         int ximajor = 2, ximinor = 0;
771         if (XIQueryVersion(display, &ximajor, &ximinor) != Success)
772         {
773             Logger::LogInfo(tr("xinput version must be at least 2.0. No mouse acceleration changes will occur."));
774             result = false;
775         }
776     }
777 
778     if (result)
779     {
780         XIDeviceInfo *all_devices = 0;
781         XIDeviceInfo *current_devices = 0;
782         XIDeviceInfo *mouse_device = 0;
783 
784         int num_devices = 0;
785         all_devices = XIQueryDevice(display, XIAllDevices, &num_devices);
786         for (int i=0; i < num_devices; i++)
787         {
788             current_devices = &all_devices[i];
789             if (current_devices->use == XISlavePointer &&
790                 QString::fromUtf8(current_devices->name) == pointerName)
791             {
792                 mouse_device = current_devices;
793             }
794         }
795 
796         if (mouse_device)
797         {
798             XDevice *device = XOpenDevice(display, mouse_device->deviceid);
799 
800             int num_feedbacks = 0;
801             int feedback_id = -1;
802             XFeedbackState *feedbacks = XGetFeedbackControl(display, device, &num_feedbacks);
803             XFeedbackState *temp = feedbacks;
804             for (int i=0; (i < num_feedbacks) && (feedback_id == -1); i++)
805             {
806                 if (temp->c_class == PtrFeedbackClass)
807                 {
808                     feedback_id = temp->id;
809                 }
810 
811                 if (feedback_id == -1 && (i+1 < num_feedbacks))
812                 {
813                     temp = (XFeedbackState*) ((char*) temp + temp->length);
814                 }
815             }
816 
817             if (feedback_id <= -1)
818             {
819                 result = false;
820             }
821             else
822             {
823                 XPtrFeedbackState *tempPtrFeedback = reinterpret_cast<XPtrFeedbackState*>(temp);
824                 tempInfo.id = feedback_id;
825                 tempInfo.accelNum = tempPtrFeedback->accelNum;
826                 tempInfo.accelDenom = tempPtrFeedback->accelDenom;
827                 tempInfo.threshold = tempPtrFeedback->threshold;
828             }
829 
830             XFree(feedbacks);
831             feedbacks = temp = 0;
832             XCloseDevice(display, device);
833         }
834 
835         if (all_devices)
836         {
837             XIFreeDeviceInfo(all_devices);
838         }
839     }
840 
841     return tempInfo;
842 }
843 
getPointInformation()844 struct X11Extras::ptrInformation X11Extras::getPointInformation()
845 {
846     return getPointInformation(mouseDeviceName);
847 }
848 
getPos()849 QPoint X11Extras::getPos()
850 {
851     XEvent mouseEvent;
852     Window wid = DefaultRootWindow(display());
853     XWindowAttributes xwAttr;
854 
855     XQueryPointer(display(), wid,
856                   &mouseEvent.xbutton.root, &mouseEvent.xbutton.window,
857                   &mouseEvent.xbutton.x_root, &mouseEvent.xbutton.y_root,
858                   &mouseEvent.xbutton.x, &mouseEvent.xbutton.y,
859                   &mouseEvent.xbutton.state);
860 
861     XGetWindowAttributes(display(), wid, &xwAttr);
862     QPoint currentPoint(mouseEvent.xbutton.x_root, mouseEvent.xbutton.y_root);
863     return currentPoint;
864 }
865