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 <QDebug>
19 #include <QDataStream>
20 
21 #include <X11/Xlib.h>
22 #include <X11/cursorfont.h> // for XGrabPointer
23 #include "x11extras.h"
24 #include "qtx11keymapper.h"
25 #include "unixcapturewindowutility.h"
26 
UnixCaptureWindowUtility(QObject * parent)27 UnixCaptureWindowUtility::UnixCaptureWindowUtility(QObject *parent) :
28     QObject(parent)
29 {
30     targetPath = "";
31     failed = false;
32     targetWindow = None;
33 }
34 
35 /**
36  * @brief Attempt to capture window selected with the mouse
37  */
attemptWindowCapture()38 void UnixCaptureWindowUtility::attemptWindowCapture()
39 {
40     // Only create instance when needed.
41     static QtX11KeyMapper x11KeyMapper;
42 
43     targetPath = "";
44     targetWindow = None;
45     failed = false;
46 
47     bool escaped = false;
48 
49     Cursor cursor;
50     Window target_window = None;
51     int status = 0;
52     Display *display = 0;
53 
54     QString potentialXDisplayString = X11Extras::getInstance()->getXDisplayString();
55     if (!potentialXDisplayString.isEmpty())
56     {
57         QByteArray tempByteArray = potentialXDisplayString.toLocal8Bit();
58         display = XOpenDisplay(tempByteArray.constData());
59     }
60     else
61     {
62         display = XOpenDisplay(NULL);
63     }
64 
65     Window rootWin = XDefaultRootWindow(display);
66 
67     cursor = XCreateFontCursor(display, XC_crosshair);
68     status = XGrabPointer(display, rootWin, False, ButtonPressMask,
69                  GrabModeSync, GrabModeAsync, None,
70                  cursor, CurrentTime);
71     if (status == Success)
72     {
73         XGrabKey(display, XKeysymToKeycode(display, x11KeyMapper.returnVirtualKey(Qt::Key_Escape)), 0, rootWin,
74                  true, GrabModeAsync, GrabModeAsync);
75 
76         XEvent event;
77         XAllowEvents(display, SyncPointer, CurrentTime);
78         XWindowEvent(display, rootWin, ButtonPressMask|KeyPressMask, &event);
79         switch (event.type)
80         {
81             case (ButtonPress):
82                 target_window = event.xbutton.subwindow;
83                 if (target_window == None)
84                 {
85                     target_window = event.xbutton.window;
86                 }
87 
88                 //qDebug() << QString::number(target_window, 16);
89                 break;
90 
91             case (KeyPress):
92             {
93                 escaped = true;
94                 break;
95             }
96         }
97 
98         XUngrabKey(display, XKeysymToKeycode(display, x11KeyMapper.returnVirtualKey(Qt::Key_Escape)),
99                    0, rootWin);
100         XUngrabPointer(display, CurrentTime);
101         XFlush(display);
102     }
103 
104     if (target_window != None)
105     {
106         targetWindow = target_window;
107     }
108     else if (!escaped)
109     {
110         failed = true;
111     }
112 
113     XCloseDisplay(display);
114     emit captureFinished();
115 }
116 
117 /**
118  * @brief Get the saved path for a window
119  * @return Program path
120  */
getTargetPath()121 QString UnixCaptureWindowUtility::getTargetPath()
122 {
123     return targetPath;
124 }
125 
126 /**
127  * @brief Check if attemptWindowCapture failed to obtain an application
128  * @return Error status
129  */
hasFailed()130 bool UnixCaptureWindowUtility::hasFailed()
131 {
132     return failed;
133 }
134 
getTargetWindow()135 unsigned long UnixCaptureWindowUtility::getTargetWindow()
136 {
137     return targetWindow;
138 }
139