KWin
Loading...
Searching...
No Matches
netinfo.cpp
Go to the documentation of this file.
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 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
8
9 SPDX-License-Identifier: GPL-2.0-or-later
10*/
11// own
12#include "netinfo.h"
13// kwin
14#include "rootinfo_filter.h"
15#include "virtualdesktops.h"
16#include "workspace.h"
17#include "x11window.h"
18// Qt
19#include <QDebug>
20
21namespace KWin
22{
23
24std::unique_ptr<RootInfo> RootInfo::s_self;
25
27{
28 Q_ASSERT(!s_self);
29 xcb_window_t supportWindow = xcb_generate_id(kwinApp()->x11Connection());
30 const uint32_t values[] = {true};
31 xcb_create_window(kwinApp()->x11Connection(), XCB_COPY_FROM_PARENT, supportWindow, kwinApp()->x11RootWindow(),
32 0, 0, 1, 1, 0, XCB_COPY_FROM_PARENT,
33 XCB_COPY_FROM_PARENT, XCB_CW_OVERRIDE_REDIRECT, values);
34 const uint32_t lowerValues[] = {XCB_STACK_MODE_BELOW}; // See usage in layers.cpp
35 // we need to do the lower window with a roundtrip, otherwise NETRootInfo is not functioning
36 UniqueCPtr<xcb_generic_error_t> error(xcb_request_check(kwinApp()->x11Connection(),
37 xcb_configure_window_checked(kwinApp()->x11Connection(), supportWindow, XCB_CONFIG_WINDOW_STACK_MODE, lowerValues)));
38 if (error) {
39 qCDebug(KWIN_CORE) << "Error occurred while lowering support window: " << error->error_code;
40 }
41
42 const NET::Properties properties = NET::Supported
43 | NET::SupportingWMCheck
44 | NET::ClientList
45 | NET::ClientListStacking
46 | NET::DesktopGeometry
47 | NET::NumberOfDesktops
48 | NET::CurrentDesktop
49 | NET::ActiveWindow
50 | NET::WorkArea
51 | NET::CloseWindow
52 | NET::DesktopNames
53 | NET::WMName
54 | NET::WMVisibleName
55 | NET::WMDesktop
56 | NET::WMWindowType
57 | NET::WMState
58 | NET::WMStrut
59 | NET::WMIconGeometry
60 | NET::WMIcon
61 | NET::WMPid
62 | NET::WMMoveResize
63 | NET::WMFrameExtents
64 | NET::WMPing;
65 const NET::WindowTypes types = NET::NormalMask
66 | NET::DesktopMask
67 | NET::DockMask
68 | NET::ToolbarMask
69 | NET::MenuMask
70 | NET::DialogMask
71 | NET::OverrideMask
72 | NET::UtilityMask
73 | NET::SplashMask; // No compositing window types here unless we support them also as managed window types
74 const NET::States states = NET::Modal
75 // | NET::Sticky // Large desktops not supported (and probably never will be)
76 | NET::MaxVert
77 | NET::MaxHoriz
78 | NET::Shaded
79 | NET::SkipTaskbar
80 | NET::KeepAbove
81 // | NET::StaysOnTop // The same like KeepAbove
82 | NET::SkipPager
83 | NET::Hidden
84 | NET::FullScreen
85 | NET::KeepBelow
86 | NET::DemandsAttention
87 | NET::SkipSwitcher
88 | NET::Focused;
89 NET::Properties2 properties2 = NET::WM2UserTime
90 | NET::WM2StartupId
91 | NET::WM2AllowedActions
92 | NET::WM2RestackWindow
93 | NET::WM2MoveResizeWindow
94 | NET::WM2ExtendedStrut
95 | NET::WM2ShowingDesktop
96 | NET::WM2DesktopLayout
97 | NET::WM2FullPlacement
98 | NET::WM2FullscreenMonitors
99 | NET::WM2KDEShadow
100 | NET::WM2OpaqueRegion
101 | NET::WM2GTKFrameExtents
102 | NET::WM2GTKShowWindowMenu
103 | NET::WM2Opacity;
104#if KWIN_BUILD_ACTIVITIES
105 properties2 |= NET::WM2Activities;
106#endif
107 const NET::Actions actions = NET::ActionMove
108 | NET::ActionResize
109 | NET::ActionMinimize
110 | NET::ActionShade
111 // | NET::ActionStick // Sticky state is not supported
112 | NET::ActionMaxVert
113 | NET::ActionMaxHoriz
114 | NET::ActionFullScreen
115 | NET::ActionChangeDesktop
116 | NET::ActionClose;
117
118 s_self = std::make_unique<RootInfo>(supportWindow, "KWin", properties, types, states, properties2, actions);
119 return s_self.get();
120}
121
123{
124 if (!s_self) {
125 return;
126 }
127 xcb_window_t supportWindow = s_self->supportWindow();
128 s_self.reset();
129 xcb_destroy_window(kwinApp()->x11Connection(), supportWindow);
130}
131
132RootInfo::RootInfo(xcb_window_t w, const char *name, NET::Properties properties, NET::WindowTypes types,
133 NET::States states, NET::Properties2 properties2, NET::Actions actions, int scr)
134 : NETRootInfo(kwinApp()->x11Connection(), w, name, properties, types, states, properties2, actions, scr)
135 , m_activeWindow(activeWindow())
136 , m_eventFilter(std::make_unique<RootInfoFilter>(this))
137{
138}
139
141{
142 VirtualDesktopManager::self()->setCount(n);
143}
144
146{
147 VirtualDesktopManager::self()->setCurrent(d);
148}
149
150void RootInfo::changeActiveWindow(xcb_window_t w, NET::RequestSource src, xcb_timestamp_t timestamp, xcb_window_t active_window)
151{
154 if (timestamp == XCB_CURRENT_TIME) {
155 timestamp = c->userTime();
156 }
157 if (src != NET::FromApplication && src != FromTool) {
158 src = NET::FromTool;
159 }
160 if (src == NET::FromTool) {
161 workspace->activateWindow(c, true); // force
162 } else if (c == workspace->mostRecentlyActivatedWindow()) {
163 return; // WORKAROUND? With > 1 plasma activities, we cause this ourselves. bug #240673
164 } else { // NET::FromApplication
165 X11Window *c2;
166 if (c->allowWindowActivation(timestamp, false)) {
168 // if activation of the requestor's window would be allowed, allow activation too
169 } else if (active_window != XCB_WINDOW_NONE
170 && (c2 = workspace->findClient(Predicate::WindowMatch, active_window)) != nullptr
171 && c2->allowWindowActivation(timestampCompare(timestamp, c2->userTime() > 0 ? timestamp : c2->userTime()), false)) {
173 } else {
174 c->demandAttention();
175 }
176 }
177 }
178}
179
180void RootInfo::restackWindow(xcb_window_t w, RequestSource src, xcb_window_t above, int detail, xcb_timestamp_t timestamp)
181{
182 if (X11Window *c = Workspace::self()->findClient(Predicate::WindowMatch, w)) {
183 if (timestamp == XCB_CURRENT_TIME) {
184 timestamp = c->userTime();
185 }
186 if (src != NET::FromApplication && src != FromTool) {
187 src = NET::FromTool;
188 }
189 c->restackWindow(above, detail, src, timestamp, true);
190 }
191}
192
193void RootInfo::closeWindow(xcb_window_t w)
194{
196 if (c) {
197 c->closeWindow();
198 }
199}
200
201void RootInfo::moveResize(xcb_window_t w, int x_root, int y_root, unsigned long direction, xcb_button_t button, RequestSource source)
202{
204 if (c) {
205 kwinApp()->updateXTime(); // otherwise grabbing may have old timestamp - this message should include timestamp
206 c->NETMoveResize(Xcb::fromXNative(x_root), Xcb::fromXNative(y_root), (Direction)direction, button);
207 }
208}
209
210void RootInfo::moveResizeWindow(xcb_window_t w, int flags, int x, int y, int width, int height)
211{
213 if (c) {
215 }
216}
217
218void RootInfo::showWindowMenu(xcb_window_t w, int device_id, int x_root, int y_root)
219{
220 if (X11Window *c = Workspace::self()->findClient(Predicate::WindowMatch, w)) {
221 c->GTKShowWindowMenu(Xcb::fromXNative(x_root), Xcb::fromXNative(y_root));
222 }
223}
224
225void RootInfo::gotPing(xcb_window_t w, xcb_timestamp_t timestamp)
226{
227 if (X11Window *c = Workspace::self()->findClient(Predicate::WindowMatch, w)) {
228 c->gotPing(timestamp);
229 }
230}
231
233{
235}
236
238{
239 xcb_window_t windowId = XCB_WINDOW_NONE;
240 if (auto x11Window = qobject_cast<X11Window *>(client)) {
241 windowId = x11Window->window();
242 }
243 if (m_activeWindow == windowId) {
244 return;
245 }
246 m_activeWindow = windowId;
247 setActiveWindow(m_activeWindow);
248}
249
250// ****************************************
251// WinInfo
252// ****************************************
253
254WinInfo::WinInfo(X11Window *c, xcb_window_t window,
255 xcb_window_t rwin, NET::Properties properties, NET::Properties2 properties2)
256 : NETWinInfo(kwinApp()->x11Connection(), window, rwin, properties, properties2, NET::WindowManager)
257 , m_client(c)
258{
259}
260
261void WinInfo::changeDesktop(int desktopId)
262{
263 if (VirtualDesktop *desktop = VirtualDesktopManager::self()->desktopForX11Id(desktopId)) {
264 Workspace::self()->sendWindowToDesktops(m_client, {desktop}, true);
265 }
266}
267
268void WinInfo::changeFullscreenMonitors(NETFullscreenMonitors topology)
269{
270 m_client->updateFullscreenMonitors(topology);
271}
272
273void WinInfo::changeState(NET::States state, NET::States mask)
274{
275 mask &= ~NET::Sticky; // KWin doesn't support large desktops, ignore
276 mask &= ~NET::Hidden; // clients are not allowed to change this directly
277 state &= mask; // for safety, clear all other bits
278
279 if ((mask & NET::FullScreen) != 0 && (state & NET::FullScreen) == 0) {
280 m_client->setFullScreen(false);
281 }
282 if ((mask & NET::Max) == NET::Max) {
283 m_client->setMaximize(state & NET::MaxVert, state & NET::MaxHoriz);
284 } else if (mask & NET::MaxVert) {
285 m_client->setMaximize(state & NET::MaxVert, m_client->maximizeMode() & MaximizeHorizontal);
286 } else if (mask & NET::MaxHoriz) {
287 m_client->setMaximize(m_client->maximizeMode() & MaximizeVertical, state & NET::MaxHoriz);
288 }
289
290 if (mask & NET::Shaded) {
291 m_client->setShade(state & NET::Shaded ? ShadeNormal : ShadeNone);
292 }
293 if (mask & NET::KeepAbove) {
294 m_client->setKeepAbove((state & NET::KeepAbove) != 0);
295 }
296 if (mask & NET::KeepBelow) {
297 m_client->setKeepBelow((state & NET::KeepBelow) != 0);
298 }
299 if (mask & NET::SkipTaskbar) {
300 m_client->setOriginalSkipTaskbar((state & NET::SkipTaskbar) != 0);
301 }
302 if (mask & NET::SkipPager) {
303 m_client->setSkipPager((state & NET::SkipPager) != 0);
304 }
305 if (mask & NET::SkipSwitcher) {
306 m_client->setSkipSwitcher((state & NET::SkipSwitcher) != 0);
307 }
308 if (mask & NET::DemandsAttention) {
309 m_client->demandAttention((state & NET::DemandsAttention) != 0);
310 }
311 if (mask & NET::Modal) {
312 m_client->setModal((state & NET::Modal) != 0);
313 }
314 // unsetting fullscreen first, setting it last (because e.g. maximize works only for !isFullScreen() )
315 if ((mask & NET::FullScreen) != 0 && (state & NET::FullScreen) != 0) {
316 m_client->setFullScreen(true);
317 }
318}
319
321{
322 m_client = nullptr; // only used when the object is passed to Deleted
323}
324
325} // namespace
void restackWindow(xcb_window_t w, RequestSource source, xcb_window_t above, int detail, xcb_timestamp_t timestamp) override
Definition netinfo.cpp:180
RootInfo(xcb_window_t w, const char *name, NET::Properties properties, NET::WindowTypes types, NET::States states, NET::Properties2 properties2, NET::Actions actions, int scr=-1)
Definition netinfo.cpp:132
void showWindowMenu(xcb_window_t w, int device_id, int x_root, int y_root) override
Definition netinfo.cpp:218
void moveResizeWindow(xcb_window_t w, int flags, int x, int y, int width, int height) override
Definition netinfo.cpp:210
void changeCurrentDesktop(int d) override
Definition netinfo.cpp:145
static RootInfo * create()
Definition netinfo.cpp:26
void setActiveClient(Window *client)
Definition netinfo.cpp:237
void gotPing(xcb_window_t w, xcb_timestamp_t timestamp) override
Definition netinfo.cpp:225
void moveResize(xcb_window_t w, int x_root, int y_root, unsigned long direction, xcb_button_t button, RequestSource source) override
Definition netinfo.cpp:201
void changeNumberOfDesktops(int n) override
Definition netinfo.cpp:140
void changeShowingDesktop(bool showing) override
Definition netinfo.cpp:232
void closeWindow(xcb_window_t w) override
Definition netinfo.cpp:193
void changeActiveWindow(xcb_window_t w, NET::RequestSource src, xcb_timestamp_t timestamp, xcb_window_t active_window) override
Definition netinfo.cpp:150
static void destroy()
Definition netinfo.cpp:122
void changeFullscreenMonitors(NETFullscreenMonitors topology) override
Definition netinfo.cpp:268
WinInfo(X11Window *c, xcb_window_t window, xcb_window_t rwin, NET::Properties properties, NET::Properties2 properties2)
Definition netinfo.cpp:254
void changeState(NET::States state, NET::States mask) override
Definition netinfo.cpp:273
void changeDesktop(int desktop) override
Definition netinfo.cpp:261
void disable()
Definition netinfo.cpp:320
void setShade(bool set)
Definition window.cpp:863
void setModal(bool modal)
Definition window.cpp:2273
void demandAttention(bool set=true)
Definition window.cpp:708
void setKeepBelow(bool)
Definition window.cpp:649
void setOriginalSkipTaskbar(bool set)
Definition window.cpp:479
void setSkipPager(bool set)
Definition window.cpp:448
void setKeepAbove(bool)
Definition window.cpp:628
void setSkipSwitcher(bool set)
Definition window.cpp:436
Q_INVOKABLE void setMaximize(bool vertically, bool horizontally)
Definition window.cpp:1172
Window * mostRecentlyActivatedWindow() const
Definition workspace.h:772
X11Window * findClient(std::function< bool(const X11Window *)> func) const
Finds the first Client matching the condition expressed by passed in func.
void activateWindow(Window *window, bool force=false)
static Workspace * self()
Definition workspace.h:91
void sendWindowToDesktops(Window *window, const QList< VirtualDesktop * > &desktops, bool dont_activate)
void setShowingDesktop(bool showing, bool animated=true)
void NETMoveResizeWindow(int flags, qreal x, qreal y, qreal width, qreal height)
void closeWindow() override
void setFullScreen(bool set) override
void NETMoveResize(qreal x_root, qreal y_root, NET::Direction direction, xcb_button_t button)
Definition events.cpp:1273
void updateFullscreenMonitors(NETFullscreenMonitors topology)
bool allowWindowActivation(xcb_timestamp_t time=-1U, bool focus_in=false)
MaximizeMode maximizeMode() const override
Definition x11window.h:575
xcb_timestamp_t userTime() const override
qreal fromXNative(int value)
Definition xcbutils.cpp:632
@ ShadeNone
Definition common.h:63
@ ShadeNormal
Definition common.h:64
@ MaximizeVertical
The window is maximized vertically.
Definition common.h:76
@ MaximizeHorizontal
Definition common.h:77
Workspace * workspace()
Definition workspace.h:830
std::unique_ptr< T, CDeleter > UniqueCPtr
Definition c_ptr.h:28