1 /*
2     KWin - the KDE window manager
3     This file is part of the KDE project.
4 
5     SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6     SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
7 
8     SPDX-License-Identifier: GPL-2.0-or-later
9 */
10 
11 /*
12 
13  This file is for (very) small utility functions/classes.
14 
15 */
16 
17 #include "utils.h"
18 
19 #include <QPainter>
20 #include <QWidget>
21 #include <kkeyserver.h>
22 
23 #ifndef KCMRULES
24 #include <QApplication>
25 #include <QDebug>
26 
27 #include "atoms.h"
28 #include "platform.h"
29 #include "workspace.h"
30 
31 #include <csignal>
32 #include <cstdio>
33 
34 #endif
35 
36 Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core", QtWarningMsg)
37 Q_LOGGING_CATEGORY(KWIN_VIRTUALKEYBOARD, "kwin_virtualkeyboard", QtWarningMsg)
38 namespace KWin
39 {
40 
41 #ifndef KCMRULES
42 
43 //************************************
44 // StrutRect
45 //************************************
46 
StrutRect(QRect rect,StrutArea area)47 StrutRect::StrutRect(QRect rect, StrutArea area)
48     : QRect(rect)
49     , m_area(area)
50 {
51 }
52 
StrutRect(int x,int y,int width,int height,StrutArea area)53 StrutRect::StrutRect(int x, int y, int width, int height, StrutArea area)
54     : QRect(x, y, width, height)
55     , m_area(area)
56 {
57 }
58 
StrutRect(const StrutRect & other)59 StrutRect::StrutRect(const StrutRect& other)
60     : QRect(other)
61     , m_area(other.area())
62 {
63 }
64 
operator =(const StrutRect & other)65 StrutRect &StrutRect::operator=(const StrutRect &other)
66 {
67     if (this != &other) {
68         QRect::operator=(other);
69         m_area = other.area();
70     }
71     return *this;
72 }
73 
74 #endif
75 
Process(QObject * parent)76 Process::Process(QObject *parent)
77     : QProcess(parent)
78 {
79 }
80 
81 Process::~Process() = default;
82 
83 #ifndef KCMRULES
updateXTime()84 void updateXTime()
85 {
86     kwinApp()->platform()->updateXTime();
87 }
88 
89 static int server_grab_count = 0;
90 
grabXServer()91 void grabXServer()
92 {
93     if (++server_grab_count == 1)
94         xcb_grab_server(connection());
95 }
96 
ungrabXServer()97 void ungrabXServer()
98 {
99     Q_ASSERT(server_grab_count > 0);
100     if (--server_grab_count == 0) {
101         xcb_ungrab_server(connection());
102         xcb_flush(connection());
103     }
104 }
105 
106 static bool keyboard_grabbed = false;
107 
grabXKeyboard(xcb_window_t w)108 bool grabXKeyboard(xcb_window_t w)
109 {
110     if (QWidget::keyboardGrabber() != nullptr)
111         return false;
112     if (keyboard_grabbed)
113         return false;
114     if (qApp->activePopupWidget() != nullptr)
115         return false;
116     if (w == XCB_WINDOW_NONE)
117         w = rootWindow();
118     const xcb_grab_keyboard_cookie_t c = xcb_grab_keyboard_unchecked(connection(), false, w, xTime(),
119                                                                      XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
120     ScopedCPointer<xcb_grab_keyboard_reply_t> grab(xcb_grab_keyboard_reply(connection(), c, nullptr));
121     if (grab.isNull()) {
122         return false;
123     }
124     if (grab->status != XCB_GRAB_STATUS_SUCCESS) {
125         return false;
126     }
127     keyboard_grabbed = true;
128     return true;
129 }
130 
ungrabXKeyboard()131 void ungrabXKeyboard()
132 {
133     if (!keyboard_grabbed) {
134         // grabXKeyboard() may fail sometimes, so don't fail, but at least warn anyway
135         qCDebug(KWIN_CORE) << "ungrabXKeyboard() called but keyboard not grabbed!";
136     }
137     keyboard_grabbed = false;
138     xcb_ungrab_keyboard(connection(), XCB_TIME_CURRENT_TIME);
139 }
140 
setupChildProcess()141 void Process::setupChildProcess()
142 {
143     sigset_t userSignals;
144     sigemptyset(&userSignals);
145     sigaddset(&userSignals, SIGUSR1);
146     sigaddset(&userSignals, SIGUSR2);
147     pthread_sigmask(SIG_UNBLOCK, &userSignals, nullptr);
148 }
149 
150 #endif
151 
152 // converting between X11 mouse/keyboard state mask and Qt button/keyboard states
153 
x11ToQtMouseButton(int button)154 Qt::MouseButton x11ToQtMouseButton(int button)
155 {
156     if (button == XCB_BUTTON_INDEX_1)
157         return Qt::LeftButton;
158     if (button == XCB_BUTTON_INDEX_2)
159         return Qt::MiddleButton;
160     if (button == XCB_BUTTON_INDEX_3)
161         return Qt::RightButton;
162     if (button == XCB_BUTTON_INDEX_4)
163         return Qt::XButton1;
164     if (button == XCB_BUTTON_INDEX_5)
165         return Qt::XButton2;
166     return Qt::NoButton;
167 }
168 
x11ToQtMouseButtons(int state)169 Qt::MouseButtons x11ToQtMouseButtons(int state)
170 {
171     Qt::MouseButtons ret = {};
172     if (state & XCB_KEY_BUT_MASK_BUTTON_1)
173         ret |= Qt::LeftButton;
174     if (state & XCB_KEY_BUT_MASK_BUTTON_2)
175         ret |= Qt::MiddleButton;
176     if (state & XCB_KEY_BUT_MASK_BUTTON_3)
177         ret |= Qt::RightButton;
178     if (state & XCB_KEY_BUT_MASK_BUTTON_4)
179         ret |= Qt::XButton1;
180     if (state & XCB_KEY_BUT_MASK_BUTTON_5)
181         ret |= Qt::XButton2;
182     return ret;
183 }
184 
x11ToQtKeyboardModifiers(int state)185 Qt::KeyboardModifiers x11ToQtKeyboardModifiers(int state)
186 {
187     Qt::KeyboardModifiers ret = {};
188     if (state & XCB_KEY_BUT_MASK_SHIFT)
189         ret |= Qt::ShiftModifier;
190     if (state & XCB_KEY_BUT_MASK_CONTROL)
191         ret |= Qt::ControlModifier;
192     if (state & KKeyServer::modXAlt())
193         ret |= Qt::AltModifier;
194     if (state & KKeyServer::modXMeta())
195         ret |= Qt::MetaModifier;
196     return ret;
197 }
198 
qPainterEffectiveDevicePixelRatio(const QPainter * painter)199 qreal qPainterEffectiveDevicePixelRatio(const QPainter *painter)
200 {
201     return std::max(qreal(1), painter->device()->devicePixelRatioF());
202 }
203 
204 } // namespace
205 
206 #ifndef KCMRULES
207 #endif
208