-
Notifications
You must be signed in to change notification settings - Fork 0
/
Application.cpp
123 lines (109 loc) · 3.52 KB
/
Application.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QX11Info>
#include "Application.h"
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
Application::Application(int& argc, char** argv)
: QApplication(argc, argv)
{
this->dpy = QX11Info::display();
Atom a_XKB_RULES_NAMES = XInternAtom(this->dpy, "_XKB_RULES_NAMES", False);
if (a_XKB_RULES_NAMES == None)
{
qDebug() << "XInternAtom(this->dpy, \"_XKB_RULES_NAMES\", False) == None";
return;
}
int dummy;
if (!XkbQueryExtension(this->dpy, &dummy, &this->xkb_event_type, &dummy, &dummy, &dummy))
{
qDebug() << "XkbQueryExtension(this->dpy, &dummy, &this->xkb_event_type, &dummy, &dummy, &dummy) == 0";
return;
}
XkbSelectEventDetails(this->dpy, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);
XkbStateRec xkb_state;
if (XkbGetState(this->dpy, XkbUseCoreKbd, &xkb_state) != Success)
{
qDebug() << "XkbGetState(this->dpy, XkbUseCoreKbd, &xkb_state) != Success";
return;
}
this->_NET_ACTIVE_WINDOW = XInternAtom(this->dpy, "_NET_ACTIVE_WINDOW", False);
this->_NET_WM_PID = XInternAtom(this->dpy, "_NET_WM_PID", False);
this->setEnglishLayout();
}
bool Application::x11EventFilter(XEvent* event)
{
if (event->type == this->xkb_event_type)
{
XkbEvent* xkbev = (XkbEvent*)event;
if (xkbev->any.xkb_type == XkbStateNotify)
{
auto activeWindow = this->getActiveWindow();
if (activeWindow)
{
auto pid = this->getWindowPID(activeWindow);
if (pid)
{
auto processName = this->getProcessName(pid);
if (processName == "mpv" ||
processName == "theMediaShell")
{
this->setEnglishLayout(); // do not allow layout any other from english
}
}
}
}
}
return false;
}
Window Application::getActiveWindow()
{
Atom actual_type;
int actual_format;
unsigned long nitems = 0;
unsigned long bytes_after;
unsigned char* current_window_prop;
XGetWindowProperty(this->dpy, XRootWindow(this->dpy, 0), this->_NET_ACTIVE_WINDOW, 0, (~0L),
False, AnyPropertyType, &actual_type,
&actual_format, &nitems, &bytes_after,
¤t_window_prop);
if (nitems > 0 && *current_window_prop > 0)
{
return *((Window*)current_window_prop);
}
return 0;
}
unsigned long Application::getWindowPID(Window window)
{
Atom actual_type;
int actual_format;
unsigned long nitems = 0;
unsigned long bytes_after;
unsigned char* pid_prop;
if (Success == XGetWindowProperty(this->dpy, window, this->_NET_WM_PID, 0, 1,
False, XA_CARDINAL, &actual_type,
&actual_format, &nitems, &bytes_after,
&pid_prop))
{
if (pid_prop != 0)
{
return *((unsigned long*)pid_prop);
}
}
return 0;
}
QString Application::getProcessName(unsigned long pid)
{
QFile file(QString("/proc/%1/cmdline").arg(pid));
if (file.open(QIODevice::ReadOnly))
{
return QFileInfo(QString::fromUtf8(file.readAll().constData())).fileName();
}
return QString();
}
void Application::setEnglishLayout()
{
XkbLockGroup(this->dpy, XkbUseCoreKbd, 0);
}