File indexing completed on 2024-04-14 15:37:26
0001 /* 0002 * Copyright 2016 Smith AR <audoban@openmailbox.org> 0003 * Michail Vourlakos <mvourlakos@gmail.com> 0004 * 0005 * This file is part of Latte-Dock 0006 * 0007 * Latte-Dock is free software; you can redistribute it and/or 0008 * modify it under the terms of the GNU General Public License as 0009 * published by the Free Software Foundation; either version 2 of 0010 * the License, or (at your option) any later version. 0011 * 0012 * Latte-Dock is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU General Public License 0018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 0021 #include "xwindowinterface.h" 0022 0023 // local 0024 #include "tasktools.h" 0025 #include "view/screenedgeghostwindow.h" 0026 #include "view/view.h" 0027 #include "../liblatte2/extras.h" 0028 0029 // Qt 0030 #include <QDebug> 0031 #include <QTimer> 0032 #include <QtX11Extras/QX11Info> 0033 0034 // KDE 0035 #include <KDesktopFile> 0036 #include <KWindowSystem> 0037 #include <KWindowInfo> 0038 #include <KIconThemes/KIconLoader> 0039 0040 // X11 0041 #include <NETWM> 0042 #include <xcb/xcb.h> 0043 0044 namespace Latte { 0045 namespace WindowSystem { 0046 0047 XWindowInterface::XWindowInterface(QObject *parent) 0048 : AbstractWindowInterface(parent) 0049 { 0050 m_currentDesktop = QString(KWindowSystem::self()->currentDesktop()); 0051 0052 connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, this, &AbstractWindowInterface::activeWindowChanged); 0053 connect(KWindowSystem::self(), &KWindowSystem::windowAdded, this, &AbstractWindowInterface::windowAdded); 0054 connect(KWindowSystem::self(), &KWindowSystem::windowRemoved, this, &AbstractWindowInterface::windowRemoved); 0055 0056 connect(KWindowSystem::self(), &KWindowSystem::currentDesktopChanged, this, [&](int desktop) { 0057 m_currentDesktop = QString(desktop); 0058 emit currentDesktopChanged(); 0059 }); 0060 0061 connect(KWindowSystem::self() 0062 , static_cast<void (KWindowSystem::*)(WId, NET::Properties, NET::Properties2)> 0063 (&KWindowSystem::windowChanged) 0064 , this, &XWindowInterface::windowChangedProxy); 0065 0066 0067 for(auto wid : KWindowSystem::self()->windows()) { 0068 emit windowAdded(wid); 0069 windowChangedProxy(wid,0,0); 0070 } 0071 } 0072 0073 XWindowInterface::~XWindowInterface() 0074 { 0075 } 0076 0077 void XWindowInterface::setViewExtraFlags(QWindow &view) 0078 { 0079 NETWinInfo winfo(QX11Info::connection() 0080 , static_cast<xcb_window_t>(view.winId()) 0081 , static_cast<xcb_window_t>(view.winId()) 0082 , 0, 0); 0083 0084 winfo.setAllowedActions(NET::ActionChangeDesktop); 0085 KWindowSystem::setType(view.winId(), NET::Dock); 0086 KWindowSystem::setState(view.winId(), NET::SkipTaskbar | NET::SkipPager); 0087 KWindowSystem::setOnAllDesktops(view.winId(), true); 0088 } 0089 0090 void XWindowInterface::setViewStruts(QWindow &view, const QRect &rect 0091 , Plasma::Types::Location location) 0092 { 0093 NETExtendedStrut strut; 0094 0095 const auto screen = view.screen(); 0096 0097 const QRect currentScreen {screen->geometry()}; 0098 const QRect wholeScreen {{0, 0}, screen->virtualSize()}; 0099 0100 switch (location) { 0101 case Plasma::Types::TopEdge: { 0102 const int topOffset {screen->geometry().top()}; 0103 strut.top_width = rect.height() + topOffset; 0104 strut.top_start = rect.x(); 0105 strut.top_end = rect.x() + rect.width() - 1; 0106 break; 0107 } 0108 0109 case Plasma::Types::BottomEdge: { 0110 const int bottomOffset {wholeScreen.bottom() - currentScreen.bottom()}; 0111 strut.bottom_width = rect.height() + bottomOffset; 0112 strut.bottom_start = rect.x(); 0113 strut.bottom_end = rect.x() + rect.width() - 1; 0114 break; 0115 } 0116 0117 case Plasma::Types::LeftEdge: { 0118 const int leftOffset = {screen->geometry().left()}; 0119 strut.left_width = rect.width() + leftOffset; 0120 strut.left_start = rect.y(); 0121 strut.left_end = rect.y() + rect.height() - 1; 0122 break; 0123 } 0124 0125 case Plasma::Types::RightEdge: { 0126 const int rightOffset = {wholeScreen.right() - currentScreen.right()}; 0127 strut.right_width = rect.width() + rightOffset; 0128 strut.right_start = rect.y(); 0129 strut.right_end = rect.y() + rect.height() - 1; 0130 break; 0131 } 0132 0133 default: 0134 qWarning() << "wrong location:" << qEnumToStr(location); 0135 return; 0136 } 0137 0138 KWindowSystem::setExtendedStrut(view.winId(), 0139 strut.left_width, strut.left_start, strut.left_end, 0140 strut.right_width, strut.right_start, strut.right_end, 0141 strut.top_width, strut.top_start, strut.top_end, 0142 strut.bottom_width, strut.bottom_start, strut.bottom_end 0143 ); 0144 } 0145 0146 void XWindowInterface::switchToNextVirtualDesktop() const 0147 { 0148 int desktops = KWindowSystem::numberOfDesktops(); 0149 0150 if (desktops <= 1) { 0151 return; 0152 } 0153 0154 int curPos = KWindowSystem::currentDesktop(); 0155 int nextPos = curPos + 1; 0156 0157 if (curPos == desktops) { 0158 nextPos = 1; 0159 } 0160 0161 KWindowSystem::setCurrentDesktop(nextPos); 0162 } 0163 0164 void XWindowInterface::switchToPreviousVirtualDesktop() const 0165 { 0166 int desktops = KWindowSystem::numberOfDesktops(); 0167 if (desktops <= 1) { 0168 return; 0169 } 0170 0171 int curPos = KWindowSystem::currentDesktop(); 0172 int nextPos = curPos - 1; 0173 0174 if (curPos == 1) { 0175 nextPos = desktops; 0176 } 0177 0178 KWindowSystem::setCurrentDesktop(nextPos); 0179 } 0180 0181 void XWindowInterface::setWindowOnActivities(QWindow &window, const QStringList &activities) 0182 { 0183 KWindowSystem::setOnActivities(window.winId(), activities); 0184 } 0185 0186 void XWindowInterface::removeViewStruts(QWindow &view) const 0187 { 0188 KWindowSystem::setStrut(view.winId(), 0, 0, 0, 0); 0189 } 0190 0191 WindowId XWindowInterface::activeWindow() const 0192 { 0193 return KWindowSystem::self()->activeWindow(); 0194 } 0195 0196 void XWindowInterface::setKeepAbove(const QDialog &dialog, bool above) const 0197 { 0198 if (above) { 0199 KWindowSystem::setState(dialog.winId(), NET::KeepAbove); 0200 } else { 0201 KWindowSystem::clearState(dialog.winId(), NET::KeepAbove); 0202 } 0203 } 0204 0205 void XWindowInterface::skipTaskBar(const QDialog &dialog) const 0206 { 0207 KWindowSystem::setState(dialog.winId(), NET::SkipTaskbar); 0208 } 0209 0210 void XWindowInterface::slideWindow(QWindow &view, AbstractWindowInterface::Slide location) const 0211 { 0212 auto slideLocation = KWindowEffects::NoEdge; 0213 0214 switch (location) { 0215 case Slide::Top: 0216 slideLocation = KWindowEffects::TopEdge; 0217 break; 0218 0219 case Slide::Bottom: 0220 slideLocation = KWindowEffects::BottomEdge; 0221 break; 0222 0223 case Slide::Left: 0224 slideLocation = KWindowEffects::LeftEdge; 0225 break; 0226 0227 case Slide::Right: 0228 slideLocation = KWindowEffects::RightEdge; 0229 break; 0230 0231 default: 0232 break; 0233 } 0234 0235 KWindowEffects::slideWindow(view.winId(), slideLocation, -1); 0236 } 0237 0238 void XWindowInterface::enableBlurBehind(QWindow &view) const 0239 { 0240 KWindowEffects::enableBlurBehind(view.winId()); 0241 } 0242 0243 void XWindowInterface::setActiveEdge(QWindow *view, bool active) const 0244 { 0245 ViewPart::ScreenEdgeGhostWindow *window = qobject_cast<ViewPart::ScreenEdgeGhostWindow *>(view); 0246 0247 if (!window) { 0248 return; 0249 } 0250 0251 xcb_connection_t *c = QX11Info::connection(); 0252 0253 const QByteArray effectName = QByteArrayLiteral("_KDE_NET_WM_SCREEN_EDGE_SHOW"); 0254 xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, effectName.length(), effectName.constData()); 0255 0256 QScopedPointer<xcb_intern_atom_reply_t, QScopedPointerPodDeleter> atom(xcb_intern_atom_reply(c, atomCookie, nullptr)); 0257 0258 if (!atom) { 0259 return; 0260 } 0261 0262 if (!active) { 0263 xcb_delete_property(c, window->winId(), atom->atom); 0264 window->hideWithMask(); 0265 return; 0266 } 0267 0268 window->showWithMask(); 0269 0270 uint32_t value = 0; 0271 0272 switch (window->location()) { 0273 case Plasma::Types::TopEdge: 0274 value = 0; 0275 break; 0276 0277 case Plasma::Types::RightEdge: 0278 value = 1; 0279 break; 0280 0281 case Plasma::Types::BottomEdge: 0282 value = 2; 0283 break; 0284 0285 case Plasma::Types::LeftEdge: 0286 value = 3; 0287 break; 0288 0289 case Plasma::Types::Floating: 0290 default: 0291 value = 4; 0292 break; 0293 } 0294 0295 int hideType = 0; 0296 0297 value |= hideType << 8; 0298 0299 xcb_change_property(c, XCB_PROP_MODE_REPLACE, window->winId(), atom->atom, XCB_ATOM_CARDINAL, 32, 1, &value); 0300 } 0301 0302 WindowInfoWrap XWindowInterface::requestInfoActive() const 0303 { 0304 return requestInfo(KWindowSystem::activeWindow()); 0305 } 0306 0307 WindowInfoWrap XWindowInterface::requestInfo(WindowId wid) const 0308 { 0309 const KWindowInfo winfo{wid.value<WId>(), NET::WMFrameExtents 0310 | NET::WMWindowType 0311 | NET::WMGeometry 0312 | NET::WMDesktop 0313 | NET::WMState 0314 | NET::WMName 0315 | NET::WMVisibleName, 0316 NET::WM2WindowClass 0317 | NET::WM2Activities 0318 | NET::WM2AllowedActions 0319 | NET::WM2TransientFor}; 0320 0321 //! update desktop id 0322 0323 bool isDesktop{false}; 0324 if (winfo.windowClassName() == "plasmashell" && isPlasmaDesktop(winfo.geometry())) { 0325 isDesktop = true; 0326 windowsTracker()->setPlasmaDesktop(wid); 0327 } 0328 0329 WindowInfoWrap winfoWrap; 0330 0331 if (!winfo.valid()) { 0332 winfoWrap.setIsValid(false); 0333 } else if (isValidWindow(winfo) && !isDesktop) { 0334 winfoWrap.setIsValid(true); 0335 winfoWrap.setWid(wid); 0336 winfoWrap.setParentId(winfo.transientFor()); 0337 winfoWrap.setIsActive(KWindowSystem::activeWindow() == wid.value<WId>()); 0338 winfoWrap.setIsMinimized(winfo.hasState(NET::Hidden)); 0339 winfoWrap.setIsMaxVert(winfo.hasState(NET::MaxVert)); 0340 winfoWrap.setIsMaxHoriz(winfo.hasState(NET::MaxHoriz)); 0341 winfoWrap.setIsFullscreen(winfo.hasState(NET::FullScreen)); 0342 winfoWrap.setIsShaded(winfo.hasState(NET::Shaded)); 0343 winfoWrap.setIsOnAllDesktops(winfo.onAllDesktops()); 0344 winfoWrap.setIsOnAllActivities(winfo.activities().empty()); 0345 winfoWrap.setGeometry(winfo.frameGeometry()); 0346 winfoWrap.setIsKeepAbove(winfo.hasState(NET::KeepAbove)); 0347 winfoWrap.setHasSkipTaskbar(winfo.hasState(NET::SkipTaskbar)); 0348 0349 //! Window Abilities 0350 winfoWrap.setIsClosable(winfo.actionSupported(NET::ActionClose)); 0351 winfoWrap.setIsFullScreenable(winfo.actionSupported(NET::ActionFullScreen)); 0352 winfoWrap.setIsMaximizable(winfo.actionSupported(NET::ActionMax)); 0353 winfoWrap.setIsMinimizable(winfo.actionSupported(NET::ActionMinimize)); 0354 winfoWrap.setIsMovable(winfo.actionSupported(NET::ActionMove)); 0355 winfoWrap.setIsResizable(winfo.actionSupported(NET::ActionResize)); 0356 winfoWrap.setIsShadeable(winfo.actionSupported(NET::ActionShade)); 0357 winfoWrap.setIsVirtualDesktopsChangeable(winfo.actionSupported(NET::ActionChangeDesktop)); 0358 //! Window Abilities 0359 0360 winfoWrap.setDisplay(winfo.visibleName()); 0361 winfoWrap.setDesktops({QString(winfo.desktop())}); 0362 winfoWrap.setActivities(winfo.activities()); 0363 } else if (m_desktopId == wid) { 0364 winfoWrap.setIsValid(true); 0365 winfoWrap.setIsPlasmaDesktop(true); 0366 winfoWrap.setWid(wid); 0367 winfoWrap.setParentId(0); 0368 winfoWrap.setHasSkipTaskbar(true); 0369 0370 //! Window Abilities 0371 winfoWrap.setIsClosable(false); 0372 winfoWrap.setIsFullScreenable(false); 0373 winfoWrap.setIsGroupable(false); 0374 winfoWrap.setIsMaximizable(false); 0375 winfoWrap.setIsMinimizable(false); 0376 winfoWrap.setIsMovable(false); 0377 winfoWrap.setIsResizable(false); 0378 winfoWrap.setIsShadeable(false); 0379 winfoWrap.setIsVirtualDesktopsChangeable(false); 0380 //! Window Abilities 0381 } 0382 0383 return winfoWrap; 0384 } 0385 0386 AppData XWindowInterface::appDataFor(WindowId wid) const 0387 { 0388 return appDataFromUrl(windowUrl(wid)); 0389 } 0390 0391 QUrl XWindowInterface::windowUrl(WindowId wid) const 0392 { 0393 const KWindowInfo info(wid.value<WId>(), 0, NET::WM2WindowClass | NET::WM2DesktopFileName); 0394 0395 QString desktopFile = QString::fromUtf8(info.desktopFileName()); 0396 0397 if (!desktopFile.isEmpty()) { 0398 KService::Ptr service = KService::serviceByStorageId(desktopFile); 0399 0400 if (service) { 0401 const QString &menuId = service->menuId(); 0402 0403 // applications: URLs are used to refer to applications by their KService::menuId 0404 // (i.e. .desktop file name) rather than the absolute path to a .desktop file. 0405 if (!menuId.isEmpty()) { 0406 return QUrl(QStringLiteral("applications:") + menuId); 0407 } 0408 0409 return QUrl::fromLocalFile(service->entryPath()); 0410 } 0411 0412 if (!desktopFile.endsWith(QLatin1String(".desktop"))) { 0413 desktopFile.append(QLatin1String(".desktop")); 0414 } 0415 0416 if (KDesktopFile::isDesktopFile(desktopFile) && QFile::exists(desktopFile)) { 0417 return QUrl::fromLocalFile(desktopFile); 0418 } 0419 } 0420 0421 return windowUrlFromMetadata(info.windowClassClass(), 0422 NETWinInfo(QX11Info::connection(), wid.value<WId>(), QX11Info::appRootWindow(), NET::WMPid, NET::Properties2()).pid(), 0423 rulesConfig, info.windowClassName()); 0424 } 0425 0426 0427 bool XWindowInterface::windowCanBeDragged(WindowId wid) const 0428 { 0429 WindowInfoWrap winfo = requestInfo(wid); 0430 return (winfo.isValid() 0431 && !winfo.isMinimized() 0432 && winfo.isMovable() 0433 && inCurrentDesktopActivity(winfo) 0434 && !winfo.isPlasmaDesktop()); 0435 } 0436 0437 bool XWindowInterface::windowCanBeMaximized(WindowId wid) const 0438 { 0439 0440 WindowInfoWrap winfo = requestInfo(wid); 0441 return (winfo.isValid() 0442 && !winfo.isMinimized() 0443 && winfo.isMaximizable() 0444 && inCurrentDesktopActivity(winfo) 0445 && !winfo.isPlasmaDesktop()); 0446 } 0447 0448 void XWindowInterface::requestActivate(WindowId wid) const 0449 { 0450 KWindowSystem::activateWindow(wid.toInt()); 0451 } 0452 0453 QIcon XWindowInterface::iconFor(WindowId wid) const 0454 { 0455 QIcon icon; 0456 0457 icon.addPixmap(KWindowSystem::icon(wid.value<WId>(), KIconLoader::SizeSmall, KIconLoader::SizeSmall, false)); 0458 icon.addPixmap(KWindowSystem::icon(wid.value<WId>(), KIconLoader::SizeSmallMedium, KIconLoader::SizeSmallMedium, false)); 0459 icon.addPixmap(KWindowSystem::icon(wid.value<WId>(), KIconLoader::SizeMedium, KIconLoader::SizeMedium, false)); 0460 icon.addPixmap(KWindowSystem::icon(wid.value<WId>(), KIconLoader::SizeLarge, KIconLoader::SizeLarge, false)); 0461 0462 return icon; 0463 } 0464 0465 WindowId XWindowInterface::winIdFor(QString appId, QRect geometry) const 0466 { 0467 return activeWindow(); 0468 } 0469 0470 void XWindowInterface::requestClose(WindowId wid) const 0471 { 0472 WindowInfoWrap wInfo = requestInfo(wid); 0473 0474 if (!wInfo.isValid() || wInfo.isPlasmaDesktop()) { 0475 return; 0476 } 0477 0478 NETRootInfo ri(QX11Info::connection(), NET::CloseWindow); 0479 ri.closeWindowRequest(wInfo.wid().toUInt()); 0480 } 0481 0482 void XWindowInterface::requestMoveWindow(WindowId wid, QPoint from) const 0483 { 0484 WindowInfoWrap wInfo = requestInfo(wid); 0485 0486 if (!wInfo.isValid() || wInfo.isPlasmaDesktop() || !inCurrentDesktopActivity(wInfo)) { 0487 return; 0488 } 0489 0490 int borderX = wInfo.geometry().width() > 120 ? 60 : 10; 0491 int borderY{10}; 0492 0493 //! find min/max values for x,y based on active window geometry 0494 int minX = wInfo.geometry().x() + borderX; 0495 int maxX = wInfo.geometry().x() + wInfo.geometry().width() - borderX; 0496 int minY = wInfo.geometry().y() + borderY; 0497 int maxY = wInfo.geometry().y() + wInfo.geometry().height() - borderY; 0498 0499 //! set the point from which this window will be moved, 0500 //! make sure that it is in window boundaries 0501 int validX = qBound(minX, from.x(), maxX); 0502 int validY = qBound(minY, from.y(), maxY); 0503 0504 NETRootInfo ri(QX11Info::connection(), NET::WMMoveResize); 0505 ri.moveResizeRequest(wInfo.wid().toUInt(), validX, validY, NET::Move); 0506 } 0507 0508 void XWindowInterface::requestToggleIsOnAllDesktops(WindowId wid) const 0509 { 0510 WindowInfoWrap wInfo = requestInfo(wid); 0511 0512 if (!wInfo.isValid() || wInfo.isPlasmaDesktop()) { 0513 return; 0514 } 0515 0516 if (KWindowSystem::numberOfDesktops() <= 1) { 0517 return; 0518 } 0519 0520 if (wInfo.isOnAllDesktops()) { 0521 KWindowSystem::setOnDesktop(wid.toUInt(), KWindowSystem::currentDesktop()); 0522 KWindowSystem::forceActiveWindow(wid.toUInt()); 0523 } else { 0524 KWindowSystem::setOnAllDesktops(wid.toUInt(), true); 0525 } 0526 } 0527 0528 void XWindowInterface::requestToggleKeepAbove(WindowId wid) const 0529 { 0530 WindowInfoWrap wInfo = requestInfo(wid); 0531 0532 if (!wInfo.isValid() || wInfo.isPlasmaDesktop()) { 0533 return; 0534 } 0535 0536 NETWinInfo ni(QX11Info::connection(), wid.toUInt(), QX11Info::appRootWindow(), NET::WMState, NET::Properties2()); 0537 0538 if (wInfo.isKeepAbove()) { 0539 ni.setState(NET::States(), NET::StaysOnTop); 0540 } else { 0541 ni.setState(NET::StaysOnTop, NET::StaysOnTop); 0542 } 0543 } 0544 0545 void XWindowInterface::requestToggleMinimized(WindowId wid) const 0546 { 0547 WindowInfoWrap wInfo = requestInfo(wid); 0548 0549 if (!wInfo.isValid() || wInfo.isPlasmaDesktop() || !inCurrentDesktopActivity(wInfo)) { 0550 return; 0551 } 0552 0553 if (wInfo.isMinimized()) { 0554 bool onCurrent = wInfo.isOnDesktop(m_currentDesktop); 0555 0556 KWindowSystem::unminimizeWindow(wid.toUInt()); 0557 0558 if (onCurrent) { 0559 KWindowSystem::forceActiveWindow(wid.toUInt()); 0560 } 0561 } else { 0562 KWindowSystem::minimizeWindow(wid.toUInt()); 0563 } 0564 } 0565 0566 void XWindowInterface::requestToggleMaximized(WindowId wid) const 0567 { 0568 WindowInfoWrap wInfo = requestInfo(wid); 0569 0570 if (!windowCanBeMaximized(wid) || !inCurrentDesktopActivity(wInfo)) { 0571 return; 0572 } 0573 0574 bool restore = wInfo.isMaxHoriz() && wInfo.isMaxVert(); 0575 0576 if (wInfo.isMinimized()) { 0577 KWindowSystem::unminimizeWindow(wid.toUInt()); 0578 } 0579 0580 NETWinInfo ni(QX11Info::connection(), wid.toInt(), QX11Info::appRootWindow(), NET::WMState, NET::Properties2()); 0581 0582 if (restore) { 0583 ni.setState(NET::States(), NET::Max); 0584 } else { 0585 ni.setState(NET::Max, NET::Max); 0586 } 0587 } 0588 0589 bool XWindowInterface::isValidWindow(WindowId wid) const 0590 { 0591 if (windowsTracker()->isValidFor(wid)) { 0592 return true; 0593 } 0594 0595 const KWindowInfo winfo{wid.value<WId>(), NET::WMWindowType | NET::WMState}; 0596 0597 return isValidWindow(winfo); 0598 } 0599 0600 bool XWindowInterface::isValidWindow(const KWindowInfo &winfo) const 0601 { 0602 if (windowsTracker()->isValidFor(winfo.win())) { 0603 return true; 0604 } 0605 0606 //! ignored windows from tracking 0607 if (m_ignoredWindows.contains(winfo.win())) { 0608 return false; 0609 } 0610 0611 if (m_desktopId == winfo.win()) { 0612 return false; 0613 } 0614 0615 bool hasSkipTaskbar = winfo.hasState(NET::SkipTaskbar); 0616 bool hasSkipPager = winfo.hasState(NET::SkipPager); 0617 0618 bool isSkipped = hasSkipTaskbar && hasSkipPager; 0619 0620 return !isSkipped; 0621 } 0622 0623 void XWindowInterface::windowChangedProxy(WId wid, NET::Properties prop1, NET::Properties2 prop2) 0624 { 0625 const KWindowInfo info(wid, NET::WMGeometry, NET::WM2WindowClass); 0626 0627 const auto winClass = info.windowClassName(); 0628 0629 //! ignored windows do not trackd 0630 if (m_ignoredWindows.contains(wid)) { 0631 return; 0632 } 0633 0634 if (winClass == "plasmashell") { 0635 //! update desktop id 0636 if (isPlasmaDesktop(info.geometry())) { 0637 m_desktopId = wid; 0638 windowsTracker()->setPlasmaDesktop(wid); 0639 considerWindowChanged(wid); 0640 return; 0641 } else if (isPlasmaPanel(info.geometry())) { 0642 registerPlasmaPanel(wid); 0643 return; 0644 } 0645 } 0646 0647 //! accept only NET::Properties events, 0648 //! ignore when the user presses a key, or a window is sending X events etc. 0649 //! without needing to (e.g. Firefox, https://bugzilla.mozilla.org/show_bug.cgi?id=1389953) 0650 //! NET::WM2UserTime, NET::WM2IconPixmap etc.... 0651 if (prop1 == 0 && !(prop2 & (NET::WM2Activities | NET::WM2TransientFor))) { 0652 return; 0653 } 0654 0655 //! accept only the following NET:Properties changed signals 0656 //! NET::WMState, NET::WMGeometry, NET::ActiveWindow 0657 if ( !(prop1 & NET::WMState) 0658 && !(prop1 & NET::WMGeometry) 0659 && !(prop1 & NET::ActiveWindow) 0660 && !(prop1 & NET::WMDesktop) 0661 && !(prop1 & (NET::WMName | NET::WMVisibleName) 0662 && !(prop2 & NET::WM2TransientFor) 0663 && !(prop2 & NET::WM2Activities)) ) { 0664 return; 0665 } 0666 0667 if (!isValidWindow(wid)) { 0668 return; 0669 } 0670 0671 considerWindowChanged(wid); 0672 } 0673 0674 } 0675 }