Warning, file /plasma/kwin/src/netinfo.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich <ettrich@kde.org> 0006 SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org> 0007 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 // own 0012 #include "netinfo.h" 0013 // kwin 0014 #include "rootinfo_filter.h" 0015 #include "virtualdesktops.h" 0016 #include "workspace.h" 0017 #include "x11window.h" 0018 // Qt 0019 #include <QDebug> 0020 0021 namespace KWin 0022 { 0023 0024 std::unique_ptr<RootInfo> RootInfo::s_self; 0025 0026 RootInfo *RootInfo::create() 0027 { 0028 Q_ASSERT(!s_self); 0029 xcb_window_t supportWindow = xcb_generate_id(kwinApp()->x11Connection()); 0030 const uint32_t values[] = {true}; 0031 xcb_create_window(kwinApp()->x11Connection(), XCB_COPY_FROM_PARENT, supportWindow, kwinApp()->x11RootWindow(), 0032 0, 0, 1, 1, 0, XCB_COPY_FROM_PARENT, 0033 XCB_COPY_FROM_PARENT, XCB_CW_OVERRIDE_REDIRECT, values); 0034 const uint32_t lowerValues[] = {XCB_STACK_MODE_BELOW}; // See usage in layers.cpp 0035 // we need to do the lower window with a roundtrip, otherwise NETRootInfo is not functioning 0036 UniqueCPtr<xcb_generic_error_t> error(xcb_request_check(kwinApp()->x11Connection(), 0037 xcb_configure_window_checked(kwinApp()->x11Connection(), supportWindow, XCB_CONFIG_WINDOW_STACK_MODE, lowerValues))); 0038 if (error) { 0039 qCDebug(KWIN_CORE) << "Error occurred while lowering support window: " << error->error_code; 0040 } 0041 0042 const NET::Properties properties = NET::Supported 0043 | NET::SupportingWMCheck 0044 | NET::ClientList 0045 | NET::ClientListStacking 0046 | NET::DesktopGeometry 0047 | NET::NumberOfDesktops 0048 | NET::CurrentDesktop 0049 | NET::ActiveWindow 0050 | NET::WorkArea 0051 | NET::CloseWindow 0052 | NET::DesktopNames 0053 | NET::WMName 0054 | NET::WMVisibleName 0055 | NET::WMDesktop 0056 | NET::WMWindowType 0057 | NET::WMState 0058 | NET::WMStrut 0059 | NET::WMIconGeometry 0060 | NET::WMIcon 0061 | NET::WMPid 0062 | NET::WMMoveResize 0063 | NET::WMFrameExtents 0064 | NET::WMPing; 0065 const NET::WindowTypes types = NET::NormalMask 0066 | NET::DesktopMask 0067 | NET::DockMask 0068 | NET::ToolbarMask 0069 | NET::MenuMask 0070 | NET::DialogMask 0071 | NET::OverrideMask 0072 | NET::UtilityMask 0073 | NET::SplashMask; // No compositing window types here unless we support them also as managed window types 0074 const NET::States states = NET::Modal 0075 // | NET::Sticky // Large desktops not supported (and probably never will be) 0076 | NET::MaxVert 0077 | NET::MaxHoriz 0078 | NET::Shaded 0079 | NET::SkipTaskbar 0080 | NET::KeepAbove 0081 // | NET::StaysOnTop // The same like KeepAbove 0082 | NET::SkipPager 0083 | NET::Hidden 0084 | NET::FullScreen 0085 | NET::KeepBelow 0086 | NET::DemandsAttention 0087 | NET::SkipSwitcher 0088 | NET::Focused; 0089 NET::Properties2 properties2 = NET::WM2UserTime 0090 | NET::WM2StartupId 0091 | NET::WM2AllowedActions 0092 | NET::WM2RestackWindow 0093 | NET::WM2MoveResizeWindow 0094 | NET::WM2ExtendedStrut 0095 | NET::WM2KDETemporaryRules 0096 | NET::WM2ShowingDesktop 0097 | NET::WM2DesktopLayout 0098 | NET::WM2FullPlacement 0099 | NET::WM2FullscreenMonitors 0100 | NET::WM2KDEShadow 0101 | NET::WM2OpaqueRegion 0102 | NET::WM2GTKFrameExtents 0103 | NET::WM2GTKShowWindowMenu 0104 | NET::WM2Opacity; 0105 #if KWIN_BUILD_ACTIVITIES 0106 properties2 |= NET::WM2Activities; 0107 #endif 0108 const NET::Actions actions = NET::ActionMove 0109 | NET::ActionResize 0110 | NET::ActionMinimize 0111 | NET::ActionShade 0112 // | NET::ActionStick // Sticky state is not supported 0113 | NET::ActionMaxVert 0114 | NET::ActionMaxHoriz 0115 | NET::ActionFullScreen 0116 | NET::ActionChangeDesktop 0117 | NET::ActionClose; 0118 0119 s_self.reset(new RootInfo(supportWindow, "KWin", properties, types, states, properties2, actions)); 0120 return s_self.get(); 0121 } 0122 0123 void RootInfo::destroy() 0124 { 0125 if (!s_self) { 0126 return; 0127 } 0128 xcb_window_t supportWindow = s_self->supportWindow(); 0129 s_self.reset(); 0130 xcb_destroy_window(kwinApp()->x11Connection(), supportWindow); 0131 } 0132 0133 RootInfo::RootInfo(xcb_window_t w, const char *name, NET::Properties properties, NET::WindowTypes types, 0134 NET::States states, NET::Properties2 properties2, NET::Actions actions, int scr) 0135 : NETRootInfo(kwinApp()->x11Connection(), w, name, properties, types, states, properties2, actions, scr) 0136 , m_activeWindow(activeWindow()) 0137 , m_eventFilter(std::make_unique<RootInfoFilter>(this)) 0138 { 0139 } 0140 0141 void RootInfo::changeNumberOfDesktops(int n) 0142 { 0143 VirtualDesktopManager::self()->setCount(n); 0144 } 0145 0146 void RootInfo::changeCurrentDesktop(int d) 0147 { 0148 VirtualDesktopManager::self()->setCurrent(d); 0149 } 0150 0151 void RootInfo::changeActiveWindow(xcb_window_t w, NET::RequestSource src, xcb_timestamp_t timestamp, xcb_window_t active_window) 0152 { 0153 Workspace *workspace = Workspace::self(); 0154 if (X11Window *c = workspace->findClient(Predicate::WindowMatch, w)) { 0155 if (timestamp == XCB_CURRENT_TIME) { 0156 timestamp = c->userTime(); 0157 } 0158 if (src != NET::FromApplication && src != FromTool) { 0159 src = NET::FromTool; 0160 } 0161 if (src == NET::FromTool) { 0162 workspace->activateWindow(c, true); // force 0163 } else if (c == workspace->mostRecentlyActivatedWindow()) { 0164 return; // WORKAROUND? With > 1 plasma activities, we cause this ourselves. bug #240673 0165 } else { // NET::FromApplication 0166 X11Window *c2; 0167 if (c->allowWindowActivation(timestamp, false, true)) { 0168 workspace->activateWindow(c); 0169 // if activation of the requestor's window would be allowed, allow activation too 0170 } else if (active_window != XCB_WINDOW_NONE 0171 && (c2 = workspace->findClient(Predicate::WindowMatch, active_window)) != nullptr 0172 && c2->allowWindowActivation(timestampCompare(timestamp, c2->userTime() > 0 ? timestamp : c2->userTime()), false, true)) { 0173 workspace->activateWindow(c); 0174 } else { 0175 c->demandAttention(); 0176 } 0177 } 0178 } 0179 } 0180 0181 void RootInfo::restackWindow(xcb_window_t w, RequestSource src, xcb_window_t above, int detail, xcb_timestamp_t timestamp) 0182 { 0183 if (X11Window *c = Workspace::self()->findClient(Predicate::WindowMatch, w)) { 0184 if (timestamp == XCB_CURRENT_TIME) { 0185 timestamp = c->userTime(); 0186 } 0187 if (src != NET::FromApplication && src != FromTool) { 0188 src = NET::FromTool; 0189 } 0190 c->restackWindow(above, detail, src, timestamp, true); 0191 } 0192 } 0193 0194 void RootInfo::closeWindow(xcb_window_t w) 0195 { 0196 X11Window *c = Workspace::self()->findClient(Predicate::WindowMatch, w); 0197 if (c) { 0198 c->closeWindow(); 0199 } 0200 } 0201 0202 void RootInfo::moveResize(xcb_window_t w, int x_root, int y_root, unsigned long direction) 0203 { 0204 X11Window *c = Workspace::self()->findClient(Predicate::WindowMatch, w); 0205 if (c) { 0206 kwinApp()->updateXTime(); // otherwise grabbing may have old timestamp - this message should include timestamp 0207 c->NETMoveResize(Xcb::fromXNative(x_root), Xcb::fromXNative(y_root), (Direction)direction); 0208 } 0209 } 0210 0211 void RootInfo::moveResizeWindow(xcb_window_t w, int flags, int x, int y, int width, int height) 0212 { 0213 X11Window *c = Workspace::self()->findClient(Predicate::WindowMatch, w); 0214 if (c) { 0215 c->NETMoveResizeWindow(flags, Xcb::fromXNative(x), Xcb::fromXNative(y), Xcb::fromXNative(width), Xcb::fromXNative(height)); 0216 } 0217 } 0218 0219 void RootInfo::showWindowMenu(xcb_window_t w, int device_id, int x_root, int y_root) 0220 { 0221 if (X11Window *c = Workspace::self()->findClient(Predicate::WindowMatch, w)) { 0222 c->GTKShowWindowMenu(Xcb::fromXNative(x_root), Xcb::fromXNative(y_root)); 0223 } 0224 } 0225 0226 void RootInfo::gotPing(xcb_window_t w, xcb_timestamp_t timestamp) 0227 { 0228 if (X11Window *c = Workspace::self()->findClient(Predicate::WindowMatch, w)) { 0229 c->gotPing(timestamp); 0230 } 0231 } 0232 0233 void RootInfo::changeShowingDesktop(bool showing) 0234 { 0235 Workspace::self()->setShowingDesktop(showing); 0236 } 0237 0238 void RootInfo::setActiveClient(Window *client) 0239 { 0240 const xcb_window_t w = client ? client->window() : xcb_window_t{XCB_WINDOW_NONE}; 0241 if (m_activeWindow == w) { 0242 return; 0243 } 0244 m_activeWindow = w; 0245 setActiveWindow(m_activeWindow); 0246 } 0247 0248 // **************************************** 0249 // WinInfo 0250 // **************************************** 0251 0252 WinInfo::WinInfo(X11Window *c, xcb_window_t window, 0253 xcb_window_t rwin, NET::Properties properties, NET::Properties2 properties2) 0254 : NETWinInfo(kwinApp()->x11Connection(), window, rwin, properties, properties2, NET::WindowManager) 0255 , m_client(c) 0256 { 0257 } 0258 0259 void WinInfo::changeDesktop(int desktop) 0260 { 0261 Workspace::self()->sendWindowToDesktop(m_client, desktop, true); 0262 } 0263 0264 void WinInfo::changeFullscreenMonitors(NETFullscreenMonitors topology) 0265 { 0266 m_client->updateFullscreenMonitors(topology); 0267 } 0268 0269 void WinInfo::changeState(NET::States state, NET::States mask) 0270 { 0271 mask &= ~NET::Sticky; // KWin doesn't support large desktops, ignore 0272 mask &= ~NET::Hidden; // clients are not allowed to change this directly 0273 state &= mask; // for safety, clear all other bits 0274 0275 if ((mask & NET::FullScreen) != 0 && (state & NET::FullScreen) == 0) { 0276 m_client->setFullScreen(false, false); 0277 } 0278 if ((mask & NET::Max) == NET::Max) { 0279 m_client->setMaximize(state & NET::MaxVert, state & NET::MaxHoriz); 0280 } else if (mask & NET::MaxVert) { 0281 m_client->setMaximize(state & NET::MaxVert, m_client->maximizeMode() & MaximizeHorizontal); 0282 } else if (mask & NET::MaxHoriz) { 0283 m_client->setMaximize(m_client->maximizeMode() & MaximizeVertical, state & NET::MaxHoriz); 0284 } 0285 0286 if (mask & NET::Shaded) { 0287 m_client->setShade(state & NET::Shaded ? ShadeNormal : ShadeNone); 0288 } 0289 if (mask & NET::KeepAbove) { 0290 m_client->setKeepAbove((state & NET::KeepAbove) != 0); 0291 } 0292 if (mask & NET::KeepBelow) { 0293 m_client->setKeepBelow((state & NET::KeepBelow) != 0); 0294 } 0295 if (mask & NET::SkipTaskbar) { 0296 m_client->setOriginalSkipTaskbar((state & NET::SkipTaskbar) != 0); 0297 } 0298 if (mask & NET::SkipPager) { 0299 m_client->setSkipPager((state & NET::SkipPager) != 0); 0300 } 0301 if (mask & NET::SkipSwitcher) { 0302 m_client->setSkipSwitcher((state & NET::SkipSwitcher) != 0); 0303 } 0304 if (mask & NET::DemandsAttention) { 0305 m_client->demandAttention((state & NET::DemandsAttention) != 0); 0306 } 0307 if (mask & NET::Modal) { 0308 m_client->setModal((state & NET::Modal) != 0); 0309 } 0310 // unsetting fullscreen first, setting it last (because e.g. maximize works only for !isFullScreen() ) 0311 if ((mask & NET::FullScreen) != 0 && (state & NET::FullScreen) != 0) { 0312 m_client->setFullScreen(true, false); 0313 } 0314 } 0315 0316 void WinInfo::disable() 0317 { 0318 m_client = nullptr; // only used when the object is passed to Deleted 0319 } 0320 0321 } // namespace