12#if KWIN_BUILD_ACTIVITIES
41#include <KDecoration2/DecoratedClient>
42#include <KDecoration2/Decoration>
43#include <KDesktopFile>
53static inline int sign(
int v)
55 return (v > 0) - (v < 0);
63 , ready_for_painting(false)
64 , m_internalId(QUuid::createUuid())
66 , m_skipCloseAnimation(false)
67 , m_colorScheme(QStringLiteral(
"kdeglobals"))
68 , m_moveResizeOutput(
workspace()->activeOutput())
108 m_tile->removeWindow(
this);
132 QDebugStateSaver saver(debug);
135 debug << window->metaObject()->className() <<
'(' <<
static_cast<const void *
>(window);
137 debug <<
", surface=" << surface;
141 debug <<
", caption=" << window->
caption();
147 if (debug.verbosity() > 2) {
154 debug <<
"Window(0x0)";
162 return item->mapToGlobal(item->boundingRect());
433 return XCB_TIME_CURRENT_TIME;
525 for (
auto it = mainwindows.constBegin(); it != mainwindows.constEnd(); ++it) {
526 if ((*it)->isFullScreen()) {
527 (*it)->updateLayer();
571 (*it)->updateLayer();
631 if (b && !
rules()->checkKeepBelow(
false)) {
652 if (b && !
rules()->checkKeepAbove(
false)) {
746 for (
auto desktop : std::as_const(
m_desktops)) {
747 if (!currentDesktops.contains(desktop->id())) {
750 currentDesktops.removeOne(desktop->id());
753 for (
const auto &desktopId : std::as_const(currentDesktops)) {
760 for (
auto it = transients_stacking_order.constBegin(); it != transients_stacking_order.constEnd(); ++it) {
769 for (
Window *other : windows) {
798 QList<VirtualDesktop *> currentDesktops;
800 currentDesktops = VirtualDesktopManager::self()->desktops();
805 if (!currentDesktops.contains(virtualDesktop)) {
821 setDesktops({VirtualDesktopManager::self()->currentDesktop()});
834 ids.reserve(desks.count());
835 std::transform(desks.constBegin(), desks.constEnd(),
836 std::back_inserter(ids),
850 return isOnDesktop(VirtualDesktopManager::self()->currentDesktop());
885 const bool wasShade =
isShade();
964 const auto sectionUnderMouse =
decoration()->sectionUnderMouse();
965 if (sectionUnderMouse == Qt::TitleBarArea) {
971 return (sectionUnderMouse == Qt::TopLeftSection || sectionUnderMouse == Qt::TopSection || sectionUnderMouse == Qt::TopRightSection);
973 return (sectionUnderMouse == Qt::TopLeftSection || sectionUnderMouse == Qt::LeftSection || sectionUnderMouse == Qt::BottomLeftSection);
975 return (sectionUnderMouse == Qt::BottomRightSection || sectionUnderMouse == Qt::RightSection || sectionUnderMouse == Qt::TopRightSection);
977 return (sectionUnderMouse == Qt::BottomLeftSection || sectionUnderMouse == Qt::BottomSection || sectionUnderMouse == Qt::BottomRightSection);
1031 if (requestedColorScheme.isEmpty()) {
1032 requestedColorScheme = QStringLiteral(
"kdeglobals");
1066 if (it ==
s_palettes.end() || it->expired()) {
1072 s_defaultPalette = std::make_shared<Decoration::DecorationPalette>(QStringLiteral(
"kdeglobals"));
1101 area.setLeft(std::min(area.left() - geometry.width() + 100, area.left()));
1102 area.setTop(std::min(area.top() - geometry.height() + 100, area.top()));
1103 area.setRight(std::max(area.right() + geometry.width() - 100, area.right()));
1104 area.setBottom(std::max(area.bottom() + geometry.height() - 100, area.bottom()));
1108 if (area.width() < geometry.width() || area.height() < geometry.height()) {
1109 geometry =
resizeWithChecks(geometry, geometry.size().boundedTo(area.size()));
1113 if (geometry.right() > area.right() && geometry.width() <= area.width()) {
1114 geometry.moveRight(area.right());
1116 if (geometry.bottom() > area.bottom() && geometry.height() <= area.height()) {
1117 geometry.moveBottom(area.bottom());
1120 if (geometry.left() < area.left()) {
1121 geometry.moveLeft(area.left());
1123 if (geometry.top() < area.top()) {
1124 geometry.moveTop(area.top());
1169 qCWarning(KWIN_CORE,
"%s doesn't support setting maximized state", metaObject()->className());
1188 Q_ASSERT(QWidget::keyboardGrabber() ==
nullptr);
1189 Q_ASSERT(QWidget::mouseGrabber() ==
nullptr);
1191 if (QApplication::activePopupWidget() !=
nullptr) {
1256 if (
workspace()->screenEdges()->isDesktopSwitchingMovingClients()) {
1289 }
else if (wasMove && (
input()->keyboardModifiers() & Qt::ShiftModifier)) {
1310 int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
1313 left_marge = std::min(100. +
borderRight(), moveResizeGeom.width());
1314 right_marge = std::min(100. +
borderLeft(), moveResizeGeom.width());
1320 if (moveResizeGeom.bottom() < desktopArea.top() + top_marge) {
1323 if (moveResizeGeom.top() > desktopArea.bottom() - bottom_marge) {
1326 if (moveResizeGeom.right() < desktopArea.left() + left_marge) {
1329 if (moveResizeGeom.left() > desktopArea.right() - right_marge) {
1337 if (moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge) {
1341 if (moveResizeGeom.top() > desktopArea.bottom() - bottom_marge) {
1344 if (moveResizeGeom.right() < desktopArea.left() + left_marge) {
1347 if (moveResizeGeom.left() > desktopArea.right() - right_marge) {
1362 Q_ASSERT(isInteractiveMoveResizePointerButtonDown());
1363 if (!startInteractiveMoveResize()) {
1364 setInteractiveMoveResizePointerButtonDown(false);
1369 m_interactiveMoveResize.delayedTimer->start(QApplication::startDragTime());
1372void Window::stopDelayedInteractiveMoveResize()
1374 delete m_interactiveMoveResize.delayedTimer;
1375 m_interactiveMoveResize.delayedTimer =
nullptr;
1378void Window::updateInteractiveMoveResize(
const QPointF ¤tGlobalCursor)
1380 handleInteractiveMoveResize(pos(), currentGlobalCursor);
1383void Window::handleInteractiveMoveResize(
const QPointF &local,
const QPointF &global)
1385 const QRectF oldGeo = moveResizeGeometry();
1386 handleInteractiveMoveResize(local.x(), local.y(), global.x(), global.y());
1387 if (!isRequestedFullScreen() && isInteractiveMove()) {
1388 if (quickTileMode() != QuickTileMode(QuickTileFlag::None) && oldGeo != moveResizeGeometry()) {
1390 setQuickTileMode(QuickTileFlag::None);
1391 const QRectF &geom_restore = geometryRestore();
1392 setInteractiveMoveOffset(QPointF(
double(interactiveMoveOffset().x()) /
double(oldGeo.width()) *
double(geom_restore.width()),
1393 double(interactiveMoveOffset().y()) /
double(oldGeo.height()) *
double(geom_restore.height())));
1395 setMoveResizeGeometry(geom_restore);
1397 handleInteractiveMoveResize(local.x(), local.y(), global.x(), global.y());
1400 if (
input()->keyboardModifiers() & Qt::ShiftModifier) {
1401 resetQuickTilingMaximizationZones();
1402 const auto &r = quickTileGeometry(QuickTileFlag::Custom, global);
1406 if (!
workspace()->outline()->isActive() ||
workspace()->outline()->geometry() != r.toRect()) {
1411 if (quickTileMode() == QuickTileMode(QuickTileFlag::None) && isResizable()) {
1412 checkQuickTilingMaximizationZones(global.x(), global.y());
1414 if (!m_electricMaximizing) {
1423void Window::handleInteractiveMoveResize(qreal x, qreal y, qreal x_root, qreal y_root)
1425 if (isWaitingForInteractiveMoveResizeSync()) {
1429 const Gravity gravity = interactiveMoveResizeGravity();
1430 if ((gravity == Gravity::None && !isMovableAcrossScreens())
1431 || (gravity != Gravity::None && (isShade() || !isResizable()))) {
1435 if (!isInteractiveMoveResize()) {
1436 QPointF p(QPointF(x , y ) - interactiveMoveOffset());
1437 if (p.manhattanLength() >= QApplication::startDragDistance()) {
1438 if (!startInteractiveMoveResize()) {
1439 setInteractiveMoveResizePointerButtonDown(
false);
1450 if (gravity != Gravity::None && shadeMode() !=
ShadeNone) {
1454 QPointF globalPos(x_root, y_root);
1457 QPointF topleft = globalPos - interactiveMoveOffset();
1458 QPointF bottomright = globalPos + invertedInteractiveMoveOffset();
1459 const QRectF currentMoveResizeGeom = moveResizeGeometry();
1460 QRectF nextMoveResizeGeom = moveResizeGeometry();
1464 auto titleBarRect = [
this](
const QRectF &rect,
bool &transposed,
int &requiredPixels) -> QRectF {
1465 QRectF titleRect = rect;
1466 titleRect.moveTopLeft(QPointF(0, 0));
1467 switch (titlebarPosition()) {
1470 titleRect.setHeight(borderTop());
1473 titleRect.setWidth(borderLeft());
1476 case Qt::BottomEdge:
1477 titleRect.setTop(titleRect.bottom() - borderBottom());
1480 titleRect.setLeft(titleRect.right() - borderRight());
1486 requiredPixels = std::min(100 * (transposed ? titleRect.width() : titleRect.height()),
1487 rect.width() * rect.height());
1491 if (isInteractiveResize()) {
1492 if (m_tile && m_tile->supportsResizeGravity(gravity)) {
1493 m_tile->resizeFromGravity(gravity, x_root, y_root);
1497 QRectF orig = initialInteractiveMoveResizeGeometry();
1499 auto calculateMoveResizeGeom = [&topleft, &bottomright, &orig, &nextMoveResizeGeom, &sizeMode, &gravity]() {
1501 case Gravity::TopLeft:
1502 nextMoveResizeGeom = QRectF(topleft, orig.bottomRight());
1504 case Gravity::BottomRight:
1505 nextMoveResizeGeom = QRectF(orig.topLeft(), bottomright);
1507 case Gravity::BottomLeft:
1508 nextMoveResizeGeom = QRectF(QPointF(topleft.x(), orig.y()), QPointF(orig.right(), bottomright.y()));
1510 case Gravity::TopRight:
1511 nextMoveResizeGeom = QRectF(QPointF(orig.x(), topleft.y()), QPointF(bottomright.x(), orig.bottom()));
1514 nextMoveResizeGeom = QRectF(QPointF(orig.left(), topleft.y()), orig.bottomRight());
1515 sizeMode = SizeModeFixedH;
1517 case Gravity::Bottom:
1518 nextMoveResizeGeom = QRectF(orig.topLeft(), QPointF(orig.right(), bottomright.y()));
1519 sizeMode = SizeModeFixedH;
1522 nextMoveResizeGeom = QRectF(QPointF(topleft.x(), orig.top()), orig.bottomRight());
1523 sizeMode = SizeModeFixedW;
1525 case Gravity::Right:
1526 nextMoveResizeGeom = QRectF(orig.topLeft(), QPointF(bottomright.x(), orig.bottom()));
1527 sizeMode = SizeModeFixedW;
1536 calculateMoveResizeGeom();
1540 if (!isUnrestrictedInteractiveMoveResize()) {
1546 for (
const QRect &rect : strut) {
1547 availableArea -= rect;
1549 bool transposed =
false;
1551 QRectF bTitleRect = titleBarRect(nextMoveResizeGeom, transposed, requiredPixels);
1552 int lastVisiblePixels = -1;
1553 QRectF lastTry = nextMoveResizeGeom;
1554 bool titleFailed =
false;
1556 const QRect titleRect = bTitleRect.translated(nextMoveResizeGeom.topLeft()).toRect();
1557 int visiblePixels = 0;
1558 int realVisiblePixels = 0;
1559 for (
const QRect &rect : availableArea) {
1560 const QRect r = rect & titleRect;
1561 realVisiblePixels += r.width() * r.height();
1562 if ((transposed && r.width() == titleRect.width()) ||
1563 (!transposed && r.height() == titleRect.height())) {
1564 visiblePixels += r.width() * r.height();
1568 if (visiblePixels >= requiredPixels) {
1572 if (realVisiblePixels <= lastVisiblePixels) {
1573 if (titleFailed && realVisiblePixels < lastVisiblePixels) {
1577 nextMoveResizeGeom = lastTry;
1582 lastVisiblePixels = realVisiblePixels;
1583 QRectF currentTry = nextMoveResizeGeom;
1584 lastTry = currentTry;
1592 bool leftChanged = !qFuzzyCompare(currentMoveResizeGeom.left(), currentTry.left());
1593 bool rightChanged = !qFuzzyCompare(currentMoveResizeGeom.right(), currentTry.right());
1594 bool topChanged = !qFuzzyCompare(currentMoveResizeGeom.top(), currentTry.top());
1595 bool btmChanged = !qFuzzyCompare(currentMoveResizeGeom.bottom(), currentTry.bottom());
1596 auto fixChangedState = [titleFailed](
bool &major,
bool &counter,
bool &ad1,
bool &ad2) {
1605 switch (titlebarPosition()) {
1608 fixChangedState(topChanged, btmChanged, leftChanged, rightChanged);
1611 fixChangedState(leftChanged, rightChanged, topChanged, btmChanged);
1613 case Qt::BottomEdge:
1614 fixChangedState(btmChanged, topChanged, leftChanged, rightChanged);
1617 fixChangedState(rightChanged, leftChanged, topChanged, btmChanged);
1621 currentTry.setTop(currentTry.y() + qBound(-1.0, currentMoveResizeGeom.y() - currentTry.y(), 1.0));
1622 }
else if (leftChanged) {
1623 currentTry.setLeft(currentTry.x() + qBound(-1.0, currentMoveResizeGeom.x() - currentTry.x(), 1.0));
1624 }
else if (btmChanged) {
1625 currentTry.setBottom(currentTry.bottom() + qBound(-1.0, currentMoveResizeGeom.bottom() - currentTry.bottom(), 1.0));
1626 }
else if (rightChanged) {
1627 currentTry.setRight(currentTry.right() + qBound(-1.0, currentMoveResizeGeom.right() - currentTry.right(), 1.0));
1631 nextMoveResizeGeom = currentTry;
1636 QSizeF size = constrainFrameSize(nextMoveResizeGeom.size(), sizeMode);
1638 topleft = QPointF(nextMoveResizeGeom.right() - size.width(), nextMoveResizeGeom.bottom() - size.height());
1639 bottomright = QPointF(nextMoveResizeGeom.left() + size.width(), nextMoveResizeGeom.top() + size.height());
1640 orig = nextMoveResizeGeom;
1645 if (sizeMode == SizeModeFixedH) {
1646 orig.setRight(bottomright.x());
1647 }
else if (sizeMode == SizeModeFixedW) {
1648 orig.setBottom(bottomright.y());
1651 calculateMoveResizeGeom();
1652 }
else if (isInteractiveMove()) {
1653 Q_ASSERT(gravity == Gravity::None);
1657 if (isRequestedFullScreen()) {
1661 const QSizeF adjSize = constrainFrameSize(nextMoveResizeGeom.size(), SizeModeMax);
1662 if (adjSize != nextMoveResizeGeom.size()) {
1663 QRectF r(nextMoveResizeGeom);
1664 nextMoveResizeGeom.setSize(adjSize);
1665 nextMoveResizeGeom.moveCenter(r.center());
1670 QRectF geometry = nextMoveResizeGeom;
1671 geometry.moveTopLeft(topleft);
1672 geometry.moveTopLeft(
workspace()->adjustWindowPosition(
this, geometry.topLeft(),
1673 isUnrestrictedInteractiveMoveResize()));
1674 nextMoveResizeGeom = geometry;
1676 if (!isUnrestrictedInteractiveMoveResize()) {
1679 for (
const QRect &rect : strut) {
1680 availableArea -= rect;
1682 bool transposed =
false;
1684 QRectF bTitleRect = titleBarRect(nextMoveResizeGeom, transposed, requiredPixels);
1686 QRectF currentTry = nextMoveResizeGeom;
1687 const QRect titleRect = bTitleRect.translated(currentTry.topLeft()).toRect();
1688 int visiblePixels = 0;
1689 for (
const QRect &rect : availableArea) {
1690 const QRect r = rect & titleRect;
1691 if ((transposed && r.width() == titleRect.width()) ||
1692 (!transposed && r.height() == titleRect.height())) {
1693 visiblePixels += r.width() * r.height();
1696 if (visiblePixels >= requiredPixels) {
1711 int newTitleTop = -1;
1712 for (
const QRect ®ion : strut) {
1714 if (r.top() == 0 && r.width() > r.height() &&
1715 r.intersects(currentTry) && currentTry.top() < r.bottom()) {
1716 newTitleTop = r.bottom();
1720 if (newTitleTop > -1) {
1721 currentTry.moveTop(newTitleTop);
1722 nextMoveResizeGeom = currentTry;
1727 int dx = sign(currentMoveResizeGeom.x() - currentTry.x()),
1728 dy = sign(currentMoveResizeGeom.y() - currentTry.y());
1729 if (visiblePixels && dx) {
1736 currentTry.translate(dx, dy);
1737 nextMoveResizeGeom = currentTry;
1740 if (std::abs(currentMoveResizeGeom.left() - nextMoveResizeGeom.left()) <= 1.0
1741 && std::abs(currentMoveResizeGeom.right() - nextMoveResizeGeom.right()) <= 1.0
1742 && std::abs(currentMoveResizeGeom.top() - nextMoveResizeGeom.top()) <= 1.0
1743 && std::abs(currentMoveResizeGeom.bottom() - nextMoveResizeGeom.bottom()) <= 1.0) {
1753 if (nextMoveResizeGeom != currentMoveResizeGeom) {
1754 if (isInteractiveMove()) {
1755 move(nextMoveResizeGeom.topLeft());
1757 doInteractiveResizeSync(nextMoveResizeGeom);
1760 Q_EMIT interactiveMoveResizeStepped(nextMoveResizeGeom);
1787bool Window::hasStrut()
const
1792void Window::setupWindowManagementInterface()
1794 if (m_windowManagementInterface) {
1803 w->setActive(isActive());
1804 w->setFullscreen(isFullScreen());
1805 w->setKeepAbove(keepAbove());
1806 w->setKeepBelow(keepBelow());
1808 w->setMinimized(isMinimized());
1809 w->setDemandsAttention(isDemandingAttention());
1810 w->setCloseable(isCloseable());
1811 w->setMaximizeable(isMaximizable());
1812 w->setMinimizeable(isMinimizable());
1813 w->setFullscreenable(isFullScreenable());
1814 w->setApplicationMenuPaths(applicationMenuServiceName(), applicationMenuObjectPath());
1816 auto updateAppId = [
this, w] {
1817 w->setResourceName(resourceName());
1818 w->setAppId(m_desktopFileName.isEmpty() ? resourceClass() : m_desktopFileName);
1821 w->setSkipTaskbar(skipTaskbar());
1822 w->setSkipSwitcher(skipSwitcher());
1824 w->setShadeable(isShadeable());
1825 w->setShaded(isShade());
1826 w->setResizable(isResizable());
1827 w->setMovable(isMovable());
1828 w->setVirtualDesktopChangeable(
true);
1829 w->setParentWindow(transientFor() ? transientFor()->windowManagementInterface() :
nullptr);
1830 w->setGeometry(frameGeometry().toRect());
1831 connect(
this, &Window::skipTaskbarChanged, w, [w,
this]() {
1832 w->setSkipTaskbar(skipTaskbar());
1834 connect(
this, &Window::skipSwitcherChanged, w, [w,
this]() {
1835 w->setSkipSwitcher(skipSwitcher());
1837 connect(
this, &Window::captionChanged, w, [w,
this] {
1838 w->setTitle(caption());
1841 connect(
this, &Window::activeChanged, w, [w,
this] {
1842 w->setActive(isActive());
1844 connect(
this, &Window::fullScreenChanged, w, [w,
this] {
1845 w->setFullscreen(isFullScreen());
1847 connect(
this, &Window::keepAboveChanged, w, &PlasmaWindowInterface::setKeepAbove);
1848 connect(
this, &Window::keepBelowChanged, w, &PlasmaWindowInterface::setKeepBelow);
1849 connect(
this, &Window::minimizedChanged, w, [w,
this] {
1850 w->setMinimized(isMinimized());
1852 connect(
this, &Window::maximizedChanged, w, [w,
this]() {
1855 connect(
this, &Window::demandsAttentionChanged, w, [w,
this] {
1856 w->setDemandsAttention(isDemandingAttention());
1858 connect(
this, &Window::iconChanged, w, [w,
this]() {
1861 connect(
this, &Window::windowClassChanged, w, updateAppId);
1862 connect(
this, &Window::desktopFileNameChanged, w, updateAppId);
1863 connect(
this, &Window::shadeChanged, w, [w,
this] {
1864 w->setShaded(isShade());
1866 connect(
this, &Window::transientChanged, w, [w,
this]() {
1867 w->setParentWindow(transientFor() ? transientFor()->windowManagementInterface() :
nullptr);
1869 connect(
this, &Window::frameGeometryChanged, w, [w,
this]() {
1870 w->setGeometry(frameGeometry().toRect());
1872 connect(
this, &Window::applicationMenuChanged, w, [w,
this]() {
1873 w->setApplicationMenuPaths(applicationMenuServiceName(), applicationMenuObjectPath());
1875 connect(w, &PlasmaWindowInterface::closeRequested,
this, [
this] {
1878 connect(w, &PlasmaWindowInterface::moveRequested,
this, [
this]() {
1879 Cursors::self()->mouse()->setPos(frameGeometry().center());
1880 performMouseCommand(Options::MouseMove, Cursors::self()->mouse()->pos());
1882 connect(w, &PlasmaWindowInterface::resizeRequested,
this, [
this]() {
1883 Cursors::self()->mouse()->setPos(frameGeometry().bottomRight());
1884 performMouseCommand(Options::MouseResize, Cursors::self()->mouse()->pos());
1886 connect(w, &PlasmaWindowInterface::fullscreenRequested,
this, [
this](
bool set) {
1889 connect(w, &PlasmaWindowInterface::minimizedRequested,
this, [
this](
bool set) {
1892 connect(w, &PlasmaWindowInterface::maximizedRequested,
this, [
this](
bool set) {
1895 connect(w, &PlasmaWindowInterface::keepAboveRequested,
this, [
this](
bool set) {
1898 connect(w, &PlasmaWindowInterface::keepBelowRequested,
this, [
this](
bool set) {
1901 connect(w, &PlasmaWindowInterface::demandsAttentionRequested,
this, [
this](
bool set) {
1902 demandAttention(set);
1904 connect(w, &PlasmaWindowInterface::activeRequested,
this, [
this](
bool set) {
1909 connect(w, &PlasmaWindowInterface::shadedRequested,
this, [
this](
bool set) {
1913 for (
const auto vd : std::as_const(m_desktops)) {
1914 w->addPlasmaVirtualDesktop(vd->id());
1919 w->setOnAllDesktops(isOnAllDesktops());
1923 connect(w, &PlasmaWindowInterface::enterPlasmaVirtualDesktopRequested,
this, [
this](
const QString &desktopId) {
1924 VirtualDesktop *vd = VirtualDesktopManager::self()->desktopForId(desktopId);
1929 connect(w, &PlasmaWindowInterface::enterNewPlasmaVirtualDesktopRequested,
this, [
this]() {
1930 VirtualDesktopManager::self()->setCount(VirtualDesktopManager::self()->count() + 1);
1931 enterDesktop(VirtualDesktopManager::self()->desktops().last());
1933 connect(w, &PlasmaWindowInterface::leavePlasmaVirtualDesktopRequested,
this, [
this](
const QString &desktopId) {
1934 VirtualDesktop *vd = VirtualDesktopManager::self()->desktopForId(desktopId);
1940 for (
const auto &activity : std::as_const(m_activityList)) {
1941 w->addPlasmaActivity(activity);
1944 connect(
this, &Window::activitiesChanged, w, [w,
this] {
1945 const auto newActivities = QSet<QString>(m_activityList.begin(), m_activityList.end());
1946 const auto oldActivitiesList = w->plasmaActivities();
1947 const auto oldActivities = QSet<QString>(oldActivitiesList.begin(), oldActivitiesList.end());
1949 const auto activitiesToAdd = newActivities - oldActivities;
1950 for (
const auto &activity : activitiesToAdd) {
1951 w->addPlasmaActivity(activity);
1954 const auto activitiesToRemove = oldActivities - newActivities;
1955 for (
const auto &activity : activitiesToRemove) {
1956 w->removePlasmaActivity(activity);
1962 connect(w, &PlasmaWindowInterface::enterPlasmaActivityRequested,
this, [
this](
const QString &activityId) {
1963 setOnActivity(activityId,
true);
1965 connect(w, &PlasmaWindowInterface::leavePlasmaActivityRequested,
this, [
this](
const QString &activityId) {
1966 setOnActivity(activityId,
false);
1968 connect(w, &PlasmaWindowInterface::sendToOutput,
this, [
this](
OutputInterface *output) {
1969 sendToOutput(output->
handle());
1972 m_windowManagementInterface = w;
1975void Window::destroyWindowManagementInterface()
1977 delete m_windowManagementInterface;
1978 m_windowManagementInterface =
nullptr;
1984 if (button == Qt::NoButton) {
1985 return Options::MouseNothing;
1990 return Options::MouseActivateRaiseAndPassClick;
1995 case Qt::LeftButton:
1997 case Qt::MiddleButton:
1999 case Qt::RightButton:
2003 return Options::MouseActivateAndPassClick;
2006 return Options::MouseNothing;
2012 if (orientation != Qt::Vertical) {
2013 return Options::MouseNothing;
2019 return Options::MouseNothing;
2024 bool replay =
false;
2026 case Options::MouseRaise:
2029 case Options::MouseLower: {
2035 if (next && next !=
this) {
2041 case Options::MouseOperationsMenu:
2047 case Options::MouseToggleRaiseAndLower:
2050 case Options::MouseActivateAndRaise: {
2051 replay = isActive();
2052 bool mustReplay = !rules()->checkAcceptFocus(acceptsFocus());
2056 while (mustReplay && --it != begin && *it !=
this) {
2058 if (!c->isClient() || (c->keepAbove() && !keepAbove()) || (keepBelow() && !c->keepBelow())) {
2061 mustReplay = !(c->isOnCurrentDesktop() && c->isOnCurrentActivity() && c->frameGeometry().intersects(frameGeometry()));
2066 replay = replay || mustReplay;
2069 case Options::MouseActivateAndLower:
2073 replay = replay || !rules()->checkAcceptFocus(acceptsFocus());
2075 case Options::MouseActivate:
2076 replay = isActive();
2079 replay = replay || !rules()->checkAcceptFocus(acceptsFocus());
2081 case Options::MouseActivateRaiseAndPassClick:
2086 case Options::MouseActivateAndPassClick:
2091 case Options::MouseMaximize:
2094 case Options::MouseRestore:
2097 case Options::MouseMinimize:
2100 case Options::MouseAbove: {
2103 setKeepBelow(
false);
2109 case Options::MouseBelow: {
2112 setKeepAbove(
false);
2118 case Options::MousePreviousDesktop:
2121 case Options::MouseNextDesktop:
2124 case Options::MouseOpacityMore:
2126 setOpacity(std::min(opacity() + 0.1, 1.0));
2129 case Options::MouseOpacityLess:
2131 setOpacity(std::max(opacity() - 0.1, 0.1));
2134 case Options::MouseClose:
2137 case Options::MouseActivateRaiseAndMove:
2138 case Options::MouseActivateRaiseAndUnrestrictedMove:
2143 case Options::MouseMove:
2144 case Options::MouseUnrestrictedMove: {
2145 if (!isMovableAcrossScreens()) {
2149 if (isInteractiveMoveResize()) {
2150 finishInteractiveMoveResize(
false);
2152 setInteractiveMoveResizeGravity(Gravity::None);
2153 setInteractiveMoveResizePointerButtonDown(
true);
2154 setInteractiveMoveOffset(QPointF(globalPos.x() - x(), globalPos.y() - y()));
2155 setInvertedInteractiveMoveOffset(rect().bottomRight() - interactiveMoveOffset());
2156 setUnrestrictedInteractiveMoveResize((cmd == Options::MouseActivateRaiseAndUnrestrictedMove
2157 || cmd == Options::MouseUnrestrictedMove));
2158 if (!startInteractiveMoveResize()) {
2159 setInteractiveMoveResizePointerButtonDown(
false);
2164 case Options::MouseResize:
2165 case Options::MouseUnrestrictedResize: {
2166 if (!isResizable() || isShade()) {
2169 if (isInteractiveMoveResize()) {
2170 finishInteractiveMoveResize(
false);
2172 setInteractiveMoveResizePointerButtonDown(
true);
2173 const QPointF moveOffset = QPointF(globalPos.x() - x(), globalPos.y() - y());
2174 setInteractiveMoveOffset(moveOffset);
2175 int x = moveOffset.x(), y = moveOffset.y();
2176 bool left = x < width() / 3;
2177 bool right = x >= 2 * width() / 3;
2178 bool top = y < height() / 3;
2179 bool bot = y >= 2 * height() / 3;
2182 gravity = left ? Gravity::TopLeft : (right ? Gravity::TopRight : Gravity::Top);
2184 gravity = left ? Gravity::BottomLeft : (right ? Gravity::BottomRight : Gravity::Bottom);
2186 gravity = (x < width() / 2) ? Gravity::Left : Gravity::Right;
2188 setInteractiveMoveResizeGravity(gravity);
2189 setInvertedInteractiveMoveOffset(rect().bottomRight() - moveOffset);
2190 setUnrestrictedInteractiveMoveResize((cmd == Options::MouseUnrestrictedResize));
2191 if (!startInteractiveMoveResize()) {
2192 setInteractiveMoveResizePointerButtonDown(
false);
2197 case Options::MouseShade:
2199 cancelShadeHoverTimer();
2201 case Options::MouseSetShade:
2203 cancelShadeHoverTimer();
2205 case Options::MouseUnsetShade:
2207 cancelShadeHoverTimer();
2209 case Options::MouseNothing:
2217void Window::setTransientFor(
Window *transientFor)
2219 if (transientFor ==
this) {
2223 if (m_transientFor == transientFor) {
2226 m_transientFor = transientFor;
2227 Q_EMIT transientChanged();
2232 return m_transientFor;
2235Window *Window::transientFor()
2237 return m_transientFor;
2240bool Window::hasTransientPlacementHint()
const
2245QRectF Window::transientPlacement()
const
2251bool Window::hasTransient(
const Window *c,
bool indirect)
const
2256QList<Window *> Window::mainWindows()
const
2258 if (
const Window *t = transientFor()) {
2259 return QList<Window *>{
const_cast<Window *
>(t)};
2261 return QList<Window *>();
2264QList<Window *> Window::allMainWindows()
const
2266 auto result = mainWindows();
2267 for (
const auto *window : result) {
2268 result += window->allMainWindows();
2273void Window::setModal(
bool m)
2280 Q_EMIT modalChanged();
2285bool Window::isModal()
const
2290bool Window::isTransient()
const
2297static bool shouldKeepTransientAbove(
const Window *parent,
const Window *transient)
2321 Q_ASSERT(!m_transients.contains(cl));
2322 Q_ASSERT(cl !=
this);
2323 m_transients.append(cl);
2324 if (shouldKeepTransientAbove(
this, cl)) {
2331 m_transients.removeAll(cl);
2338void Window::removeTransientFromList(
Window *cl)
2340 m_transients.removeAll(cl);
2343bool Window::isActiveFullScreen()
const
2345 if (!isFullScreen()) {
2353 return ac && (ac ==
this || !ac->isOnOutput(output()) || ac->allMainWindows().contains(
const_cast<Window *
>(
this)));
2356int Window::borderBottom()
const
2358 return isDecorated() ? decoration()->
borderBottom() : 0;
2361int Window::borderLeft()
const
2363 return isDecorated() ? decoration()->borderLeft() : 0;
2366int Window::borderRight()
const
2368 return isDecorated() ? decoration()->borderRight() : 0;
2371int Window::borderTop()
const
2373 return isDecorated() ? decoration()->borderTop() : 0;
2376void Window::updateCursor()
2378 Gravity gravity = interactiveMoveResizeGravity();
2379 if (!isResizable() || isShade()) {
2380 gravity = Gravity::None;
2384 case Gravity::TopLeft:
2387 case Gravity::BottomRight:
2390 case Gravity::BottomLeft:
2393 case Gravity::TopRight:
2399 case Gravity::Bottom:
2405 case Gravity::Right:
2409 if (isInteractiveMoveResize()) {
2410 c = Qt::SizeAllCursor;
2412 c = Qt::ArrowCursor;
2416 if (c == m_interactiveMoveResize.cursor) {
2419 m_interactiveMoveResize.cursor = c;
2420 Q_EMIT moveResizeCursorChanged(c);
2423void Window::leaveInteractiveMoveResize()
2426 setInteractiveMoveResize(
false);
2427 if (
workspace()->screenEdges()->isDesktopSwitchingMovingClients()) {
2430 if (isElectricBorderMaximizing()) {
2436bool Window::doStartInteractiveMoveResize()
2441void Window::doFinishInteractiveMoveResize()
2445bool Window::isWaitingForInteractiveMoveResizeSync()
const
2450void Window::doInteractiveResizeSync(
const QRectF &)
2454void Window::checkQuickTilingMaximizationZones(
int xroot,
int yroot)
2456 QuickTileMode mode = QuickTileFlag::None;
2457 bool innerBorder =
false;
2460 for (
const Output *output : outputs) {
2461 if (!output->geometry().contains(QPoint(xroot, yroot))) {
2465 auto isInScreen = [&output, &outputs](
const QPoint &pt) {
2466 for (
const Output *other : outputs) {
2467 if (other == output) {
2470 if (other->geometry().contains(pt)) {
2479 if (xroot <= area.x() + 20) {
2480 mode |= QuickTileFlag::Left;
2481 innerBorder = isInScreen(QPoint(area.x() - 1, yroot));
2482 }
else if (xroot >= area.x() + area.width() - 20) {
2483 mode |= QuickTileFlag::Right;
2484 innerBorder = isInScreen(QPoint(area.right() + 1, yroot));
2488 if (mode != QuickTileMode(QuickTileFlag::None)) {
2490 mode |= QuickTileFlag::Top;
2492 mode |= QuickTileFlag::Bottom;
2495 mode = QuickTileFlag::Maximize;
2496 innerBorder = isInScreen(QPoint(xroot, area.y() - 1));
2500 if (mode != electricBorderMode()) {
2501 setElectricBorderMode(mode);
2503 if (!m_electricMaximizingDelay) {
2504 m_electricMaximizingDelay =
new QTimer(
this);
2505 m_electricMaximizingDelay->setInterval(250);
2506 m_electricMaximizingDelay->setSingleShot(
true);
2507 connect(m_electricMaximizingDelay, &QTimer::timeout,
this, [
this]() {
2508 if (isInteractiveMove()) {
2509 setElectricBorderMaximizing(electricBorderMode() != QuickTileMode(QuickTileFlag::None));
2513 m_electricMaximizingDelay->start();
2515 setElectricBorderMaximizing(mode != QuickTileMode(QuickTileFlag::None));
2520void Window::resetQuickTilingMaximizationZones()
2522 if (electricBorderMode() != QuickTileMode(QuickTileFlag::None)) {
2523 if (m_electricMaximizingDelay) {
2524 m_electricMaximizingDelay->stop();
2526 setElectricBorderMaximizing(
false);
2527 setElectricBorderMode(QuickTileFlag::None);
2531void Window::keyPressEvent(uint key_code)
2533 if (!isInteractiveMove() && !isInteractiveResize()) {
2536 bool is_control = key_code & Qt::CTRL;
2537 bool is_alt = key_code & Qt::ALT;
2538 key_code = key_code & ~Qt::KeyboardModifierMask;
2539 int delta = is_control ? 1 : is_alt ? 32
2541 QPointF pos = Cursors::self()->mouse()->pos();
2556 case Qt::Key_Return:
2558 setInteractiveMoveResizePointerButtonDown(
false);
2559 finishInteractiveMoveResize(
false);
2562 case Qt::Key_Escape:
2563 setInteractiveMoveResizePointerButtonDown(
false);
2564 finishInteractiveMoveResize(
true);
2570 Cursors::self()->mouse()->setPos(pos);
2573QSizeF Window::resizeIncrements()
const
2575 return QSizeF(1, 1);
2578void Window::dontInteractiveMoveResize()
2580 setInteractiveMoveResizePointerButtonDown(
false);
2581 stopDelayedInteractiveMoveResize();
2582 if (isInteractiveMoveResize()) {
2583 finishInteractiveMoveResize(
false);
2589 if (isDecorated()) {
2590 switch (decoration()->sectionUnderMouse()) {
2591 case Qt::BottomLeftSection:
2592 return Gravity::BottomLeft;
2593 case Qt::BottomRightSection:
2594 return Gravity::BottomRight;
2595 case Qt::BottomSection:
2596 return Gravity::Bottom;
2597 case Qt::LeftSection:
2598 return Gravity::Left;
2599 case Qt::RightSection:
2600 return Gravity::Right;
2601 case Qt::TopSection:
2602 return Gravity::Top;
2603 case Qt::TopLeftSection:
2604 return Gravity::TopLeft;
2605 case Qt::TopRightSection:
2606 return Gravity::TopRight;
2608 return Gravity::None;
2611 return Gravity::None;
2614void Window::endInteractiveMoveResize()
2616 setInteractiveMoveResizePointerButtonDown(
false);
2617 stopDelayedInteractiveMoveResize();
2618 if (isInteractiveMoveResize()) {
2619 finishInteractiveMoveResize(
false);
2620 setInteractiveMoveResizeGravity(mouseGravity());
2625void Window::setDecoration(std::shared_ptr<KDecoration2::Decoration> decoration)
2627 if (m_decoration.decoration == decoration) {
2631 QMetaObject::invokeMethod(decoration.get(), QOverload<>::of(&KDecoration2::Decoration::update), Qt::QueuedConnection);
2632 connect(decoration.get(), &KDecoration2::Decoration::shadowChanged,
this, [
this]() {
2637 connect(decoration.get(), &KDecoration2::Decoration::bordersChanged,
this, [
this]() {
2639 updateDecorationInputShape();
2642 connect(decoration.get(), &KDecoration2::Decoration::resizeOnlyBordersChanged,
this, [
this]() {
2644 updateDecorationInputShape();
2647 connect(decoratedClient()->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged,
this, [
this]() {
2649 updateDecorationInputShape();
2653 m_decoration.decoration = decoration;
2654 updateDecorationInputShape();
2655 Q_EMIT decorationChanged();
2658void Window::updateDecorationInputShape()
2660 if (!isDecorated()) {
2661 m_decoration.inputRegion = QRegion();
2665 const QMargins borders = decoration()->borders();
2666 const QMargins resizeBorders = decoration()->resizeOnlyBorders();
2668 const QRectF innerRect = QRectF(QPointF(borderLeft(), borderTop()), decoratedClient()->size());
2669 const QRectF outerRect = innerRect + borders + resizeBorders;
2671 m_decoration.inputRegion = QRegion(outerRect.toAlignedRect()) - innerRect.toAlignedRect();
2674bool Window::decorationHasAlpha()
const
2676 if (!isDecorated() || decoration()->isOpaque()) {
2683void Window::triggerDecorationRepaint()
2685 if (isDecorated()) {
2686 decoration()->update();
2690void Window::layoutDecorationRects(QRectF &left, QRectF &top, QRectF &right, QRectF &bottom)
const
2692 if (!isDecorated()) {
2695 QRectF r = decoration()->rect();
2697 top = QRectF(r.x(), r.y(), r.width(), borderTop());
2698 bottom = QRectF(r.x(), r.y() + r.height() - borderBottom(),
2699 r.width(), borderBottom());
2700 left = QRectF(r.x(), r.y() + top.height(),
2701 borderLeft(), r.height() - top.height() - bottom.height());
2702 right = QRectF(r.x() + r.width() - borderRight(), r.y() + top.height(),
2703 borderRight(), r.height() - top.height() - bottom.height());
2706void Window::processDecorationMove(
const QPointF &localPos,
const QPointF &globalPos)
2708 if (isInteractiveMoveResizePointerButtonDown()) {
2709 handleInteractiveMoveResize(localPos.x(), localPos.y(), globalPos.x(), globalPos.y());
2713 Gravity newGravity = mouseGravity();
2714 if (newGravity != interactiveMoveResizeGravity()) {
2715 setInteractiveMoveResizeGravity(newGravity);
2720bool Window::processDecorationButtonPress(QMouseEvent *event,
bool ignoreMenu)
2723 bool active = isActive();
2724 if (!wantsInput()) {
2729 if (event->button() == Qt::LeftButton && titlebarPositionUnderMouse()) {
2730 if (m_decoration.doubleClickTimer.isValid()) {
2731 const qint64 interval = m_decoration.doubleClickTimer.elapsed();
2732 m_decoration.doubleClickTimer.invalidate();
2733 if (interval > QGuiApplication::styleHints()->mouseDoubleClickInterval()) {
2734 m_decoration.doubleClickTimer.start();
2737 dontInteractiveMoveResize();
2741 m_decoration.doubleClickTimer.start();
2745 if (event->button() == Qt::LeftButton) {
2747 }
else if (event->button() == Qt::MiddleButton) {
2749 }
else if (event->button() == Qt::RightButton) {
2752 if (event->button() == Qt::LeftButton
2753 && com != Options::MouseOperationsMenu
2754 && com != Options::MouseMinimize)
2756 setInteractiveMoveResizeGravity(mouseGravity());
2757 setInteractiveMoveResizePointerButtonDown(
true);
2758 setInteractiveMoveOffset(event->pos());
2759 setInvertedInteractiveMoveOffset(rect().bottomRight() - interactiveMoveOffset());
2760 setUnrestrictedInteractiveMoveResize(
false);
2761 startDelayedInteractiveMoveResize();
2766 if (!ignoreMenu || com != Options::MouseOperationsMenu) {
2767 performMouseCommand(com, event->globalPos());
2770 com == Options::MouseRaise || com == Options::MouseOperationsMenu || com == Options::MouseActivateAndRaise || com == Options::MouseActivate || com == Options::MouseActivateRaiseAndPassClick || com == Options::MouseActivateAndPassClick || com == Options::MouseNothing);
2773void Window::processDecorationButtonRelease(QMouseEvent *event)
2775 if (isDecorated()) {
2776 if (event->isAccepted() || !titlebarPositionUnderMouse()) {
2777 invalidateDecorationDoubleClickTimer();
2781 if (event->buttons() == Qt::NoButton) {
2782 setInteractiveMoveResizePointerButtonDown(
false);
2783 stopDelayedInteractiveMoveResize();
2784 if (isInteractiveMoveResize()) {
2785 finishInteractiveMoveResize(
false);
2786 setInteractiveMoveResizeGravity(mouseGravity());
2792void Window::startDecorationDoubleClickTimer()
2794 m_decoration.doubleClickTimer.start();
2797void Window::invalidateDecorationDoubleClickTimer()
2799 m_decoration.doubleClickTimer.invalidate();
2802bool Window::providesContextHelp()
const
2807void Window::showContextHelp()
2813 return m_decoration.client;
2818 m_decoration.client = client;
2821void Window::pointerEnterEvent(
const QPointF &globalPos)
2824 cancelShadeHoverTimer();
2825 startShadeHoverTimer();
2836 if (isDesktop() || isDock()) {
2842 || globalPos !=
workspace()->focusMousePosition()) {
2847void Window::pointerLeaveEvent()
2851 cancelShadeHoverTimer();
2852 startShadeUnhoverTimer();
2857QRectF Window::iconGeometry()
const
2864 int minDistance = INT_MAX;
2865 Window *candidatePanel =
nullptr;
2866 QRectF candidateGeom;
2868 const auto minGeometries = windowManagementInterface()->minimizedGeometries();
2869 for (
auto i = minGeometries.constBegin(), end = minGeometries.constEnd(); i != end; ++i) {
2874 const int distance = QPointF(panel->
pos() - pos()).manhattanLength();
2875 if (distance < minDistance) {
2876 minDistance = distance;
2877 candidatePanel = panel;
2878 candidateGeom = i.value();
2881 if (!candidatePanel) {
2883 const auto windows = mainWindows();
2884 for (
Window *mainWindow : windows) {
2885 const auto geom = mainWindow->iconGeometry();
2886 if (geom.isValid()) {
2892 return candidateGeom.translated(candidatePanel->
pos());
2895QRectF Window::virtualKeyboardGeometry()
const
2897 return m_virtualKeyboardGeometry;
2900void Window::setVirtualKeyboardGeometry(
const QRectF &geo)
2903 if (geo.isEmpty() && !m_keyboardGeometryRestore.isEmpty()) {
2905 QRectF newWindowGeometry = (requestedMaximizeMode() &
MaximizeHorizontal) ? availableArea : m_keyboardGeometryRestore;
2906 moveResize(newWindowGeometry);
2907 m_keyboardGeometryRestore = QRectF();
2908 }
else if (geo.isEmpty()) {
2911 }
else if (m_keyboardGeometryRestore.isEmpty()) {
2912 m_keyboardGeometryRestore = moveResizeGeometry();
2915 m_virtualKeyboardGeometry = geo;
2918 if (isRequestedFullScreen() || isDesktop()) {
2922 if (!geo.intersects(m_keyboardGeometryRestore)) {
2927 QRectF newWindowGeometry = (requestedMaximizeMode() &
MaximizeHorizontal) ? availableArea : m_keyboardGeometryRestore;
2928 newWindowGeometry.setHeight(std::min(newWindowGeometry.height(), geo.top() - availableArea.top()));
2929 newWindowGeometry.moveTop(std::max(geo.top() - newWindowGeometry.height(), availableArea.top()));
2930 newWindowGeometry = newWindowGeometry.intersected(availableArea);
2931 moveResize(newWindowGeometry);
2934QRectF Window::keyboardGeometryRestore()
const
2936 return m_keyboardGeometryRestore;
2939void Window::setKeyboardGeometryRestore(
const QRectF &geom)
2941 m_keyboardGeometryRestore = geom;
2944bool Window::dockWantsInput()
const
2949void Window::setDesktopFileName(
const QString &name)
2951 const QString effectiveName = rules()->checkDesktopFile(name);
2952 if (effectiveName == m_desktopFileName) {
2955 m_desktopFileName = effectiveName;
2956 updateWindowRules(Rules::DesktopFile);
2957 Q_EMIT desktopFileNameChanged();
2960QString Window::iconFromDesktopFile(
const QString &desktopFileName)
2962 const QString absolutePath = findDesktopFile(desktopFileName);
2963 if (absolutePath.isEmpty()) {
2967 KDesktopFile df(absolutePath);
2968 return df.readIcon();
2971QString Window::iconFromDesktopFile()
const
2973 return iconFromDesktopFile(m_desktopFileName);
2976QString Window::findDesktopFile(
const QString &desktopFileName)
2978 if (desktopFileName.isEmpty()) {
2982 const QString desktopFileNameWithPrefix = desktopFileName + QLatin1String(
".desktop");
2983 QString desktopFilePath;
2985 if (QDir::isAbsolutePath(desktopFileName)) {
2986 if (QFile::exists(desktopFileNameWithPrefix)) {
2987 desktopFilePath = desktopFileNameWithPrefix;
2989 desktopFilePath = desktopFileName;
2993 if (desktopFilePath.isEmpty()) {
2994 desktopFilePath = QStandardPaths::locate(QStandardPaths::ApplicationsLocation,
2995 desktopFileNameWithPrefix);
2997 if (desktopFilePath.isEmpty()) {
2998 desktopFilePath = QStandardPaths::locate(QStandardPaths::ApplicationsLocation,
3001 return desktopFilePath;
3004bool Window::hasApplicationMenu()
const
3006 return Workspace::self()->applicationMenu()->applicationMenuEnabled() && !m_applicationMenuServiceName.isEmpty() && !m_applicationMenuObjectPath.isEmpty();
3009void Window::updateApplicationMenuServiceName(
const QString &serviceName)
3011 const bool old_hasApplicationMenu = hasApplicationMenu();
3013 m_applicationMenuServiceName = serviceName;
3015 const bool new_hasApplicationMenu = hasApplicationMenu();
3017 Q_EMIT applicationMenuChanged();
3018 if (old_hasApplicationMenu != new_hasApplicationMenu) {
3019 Q_EMIT hasApplicationMenuChanged(new_hasApplicationMenu);
3023void Window::updateApplicationMenuObjectPath(
const QString &objectPath)
3025 const bool old_hasApplicationMenu = hasApplicationMenu();
3027 m_applicationMenuObjectPath = objectPath;
3029 const bool new_hasApplicationMenu = hasApplicationMenu();
3031 Q_EMIT applicationMenuChanged();
3032 if (old_hasApplicationMenu != new_hasApplicationMenu) {
3033 Q_EMIT hasApplicationMenuChanged(new_hasApplicationMenu);
3037void Window::setApplicationMenuActive(
bool applicationMenuActive)
3039 if (m_applicationMenuActive != applicationMenuActive) {
3040 m_applicationMenuActive = applicationMenuActive;
3041 Q_EMIT applicationMenuActiveChanged(applicationMenuActive);
3045void Window::showApplicationMenu(
int actionId)
3047 if (isDecorated()) {
3048 decoration()->showApplicationMenu(actionId);
3051 Workspace::self()->showApplicationMenu(QRect(),
this, actionId);
3055bool Window::unresponsive()
const
3057 return m_unresponsive;
3060void Window::setUnresponsive(
bool unresponsive)
3062 if (m_unresponsive != unresponsive) {
3063 m_unresponsive = unresponsive;
3064 Q_EMIT unresponsiveChanged(m_unresponsive);
3065 Q_EMIT captionChanged();
3069QString Window::shortcutCaptionSuffix()
const
3071 if (shortcut().isEmpty()) {
3074 return QLatin1String(
" {") + shortcut().toString() + QLatin1Char(
'}');
3077QString Window::caption()
const
3079 QString cap = captionNormal() + captionSuffix();
3080 if (unresponsive()) {
3081 cap += QLatin1String(
" ");
3082 cap += i18nc(
"Application is not responding, appended to window title",
"(Not Responding)");
3092QStringList Window::activities()
const
3094 return m_activityList;
3097bool Window::isOnCurrentActivity()
const
3099#if KWIN_BUILD_ACTIVITIES
3100 if (!Workspace::self()->activities()) {
3103 return isOnActivity(Workspace::self()->activities()->current());
3116void Window::setOnActivity(
const QString &activity,
bool enable)
3118#if KWIN_BUILD_ACTIVITIES
3119 if (!Workspace::self()->activities()) {
3122 QStringList newActivitiesList = activities();
3123 if (newActivitiesList.contains(activity) == enable) {
3128 QStringList allActivities = Workspace::self()->activities()->all();
3129 if (!allActivities.contains(activity)) {
3133 newActivitiesList.append(activity);
3135 newActivitiesList.removeOne(activity);
3137 setOnActivities(newActivitiesList);
3144void Window::setOnActivities(
const QStringList &newActivitiesList)
3146#if KWIN_BUILD_ACTIVITIES
3147 if (!Workspace::self()->activities()) {
3150 if (Workspace::self()->activities()->serviceStatus() != KActivities::Consumer::Running) {
3153 const auto allActivities = Workspace::self()->activities()->all();
3154 const auto activityList = [&] {
3155 auto result = rules()->checkActivity(newActivitiesList);
3157 const auto it = std::remove_if(result.begin(), result.end(), [=](
const QString &activity) {
3158 return !allActivities.contains(activity);
3160 result.erase(it, result.end());
3164 const auto allActivityExplicitlyRequested = activityList.isEmpty() || activityList.contains(Activities::nullUuid());
3165 const auto allActivitiesCovered = activityList.size() > 1 && activityList.size() == allActivities.size();
3167 if (allActivityExplicitlyRequested || allActivitiesCovered) {
3168 if (!m_activityList.isEmpty()) {
3169 m_activityList.clear();
3170 doSetOnActivities(m_activityList);
3173 if (m_activityList != activityList) {
3174 m_activityList = activityList;
3175 doSetOnActivities(m_activityList);
3179 updateActivities(
false);
3183void Window::doSetOnActivities(
const QStringList &activityList)
3191void Window::setOnAllActivities(
bool all)
3193#if KWIN_BUILD_ACTIVITIES
3194 if (all == isOnAllActivities()) {
3198 setOnActivities(QStringList());
3200 setOnActivity(Workspace::self()->activities()->current(),
true);
3208void Window::updateActivities(
bool includeTransients)
3210 if (m_activityUpdatesBlocked) {
3211 m_blockedActivityUpdatesRequireTransients |= includeTransients;
3214 Q_EMIT activitiesChanged();
3215 m_blockedActivityUpdatesRequireTransients =
false;
3216 Workspace::self()->focusChain()->update(
this, FocusChain::MakeFirst);
3217 updateWindowRules(Rules::Activity);
3220void Window::blockActivityUpdates(
bool b)
3223 ++m_activityUpdatesBlocked;
3225 Q_ASSERT(m_activityUpdatesBlocked);
3226 --m_activityUpdatesBlocked;
3227 if (!m_activityUpdatesBlocked) {
3228 updateActivities(m_blockedActivityUpdatesRequireTransients);
3233bool Window::groupTransient()
const
3248QPointF Window::framePosToClientPos(
const QPointF &point)
const
3250 return point + QPointF(borderLeft(), borderTop());
3253QPointF Window::clientPosToFramePos(
const QPointF &point)
const
3255 return point - QPointF(borderLeft(), borderTop());
3258QSizeF Window::frameSizeToClientSize(
const QSizeF &size)
const
3260 const qreal width = size.width() - borderLeft() - borderRight();
3261 const qreal height = size.height() - borderTop() - borderBottom();
3262 return QSizeF(width, height);
3265QSizeF Window::clientSizeToFrameSize(
const QSizeF &size)
const
3267 const qreal width = size.width() + borderLeft() + borderRight();
3268 const qreal height = size.height() + borderTop() + borderBottom();
3269 return QSizeF(width, height);
3272QRectF Window::frameRectToClientRect(
const QRectF &rect)
const
3274 const QPointF position = framePosToClientPos(rect.topLeft());
3275 const QSizeF size = frameSizeToClientSize(rect.size());
3276 return QRectF(position, size);
3279QRectF Window::clientRectToFrameRect(
const QRectF &rect)
const
3281 const QPointF position = clientPosToFramePos(rect.topLeft());
3282 const QSizeF size = clientSizeToFrameSize(rect.size());
3283 return QRectF(position, size);
3286QRectF Window::moveResizeGeometry()
const
3288 return m_moveResizeGeometry;
3291void Window::setMoveResizeGeometry(
const QRectF &geo)
3293 m_moveResizeGeometry = geo;
3299 return m_moveResizeOutput;
3302void Window::setMoveResizeOutput(
Output *output)
3304 m_moveResizeOutput = output;
3307void Window::move(
const QPointF &point)
3309 const QRectF rect = QRectF(point, m_moveResizeGeometry.size());
3311 setMoveResizeGeometry(rect);
3312 moveResizeInternal(rect, MoveResizeMode::Move);
3315void Window::resize(
const QSizeF &size)
3317 const QRectF rect = QRectF(m_moveResizeGeometry.topLeft(), size);
3319 setMoveResizeGeometry(rect);
3320 moveResizeInternal(rect, MoveResizeMode::Resize);
3323void Window::moveResize(
const QRectF &rect)
3325 setMoveResizeGeometry(rect);
3326 moveResizeInternal(rect, MoveResizeMode::MoveResize);
3329void Window::setElectricBorderMode(QuickTileMode mode)
3331 if (mode != QuickTileMode(QuickTileFlag::Maximize)) {
3333 if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Horizontal)) {
3334 mode &= ~QuickTileMode(QuickTileFlag::Horizontal);
3336 if ((mode & QuickTileFlag::Vertical) == QuickTileMode(QuickTileFlag::Vertical)) {
3337 mode &= ~QuickTileMode(QuickTileFlag::Vertical);
3340 m_electricMode = mode;
3343void Window::setElectricBorderMaximizing(
bool maximizing)
3345 m_electricMaximizing = maximizing;
3347 workspace()->
outline()->
show(quickTileGeometry(electricBorderMode(), Cursors::self()->mouse()->pos()).toRect(), moveResizeGeometry().toRect());
3351 elevate(maximizing);
3354QRectF Window::quickTileGeometry(QuickTileMode mode,
const QPointF &pos)
const
3356 if (mode == QuickTileMode(QuickTileFlag::Maximize)) {
3358 return geometryRestore();
3366 if (mode & QuickTileFlag::Custom) {
3382void Window::updateElectricGeometryRestore()
3384 m_electricGeometryRestore = geometryRestore();
3385 if (m_interactiveMoveResize.initialQuickTileMode == QuickTileMode(QuickTileFlag::None)) {
3387 m_electricGeometryRestore.setX(x());
3388 m_electricGeometryRestore.setWidth(width());
3391 m_electricGeometryRestore.setY(y());
3392 m_electricGeometryRestore.setHeight(height());
3397QRectF Window::quickTileGeometryRestore()
const
3399 if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
3401 return geometryRestore();
3404 if (isElectricBorderMaximizing()) {
3405 return m_electricGeometryRestore;
3407 return moveResizeGeometry();
3411void Window::setQuickTileMode(QuickTileMode mode,
bool keyboard)
3414 if (!isResizable()) {
3417 if (isAppletPopup()) {
3427 if (mode == QuickTileMode(QuickTileFlag::Maximize)) {
3429 m_quickTileMode = int(QuickTileFlag::None);
3430 setMaximize(
false,
false);
3432 QRectF effectiveGeometryRestore = quickTileGeometryRestore();
3433 m_quickTileMode = int(QuickTileFlag::Maximize);
3434 setMaximize(
true,
true);
3435 setGeometryRestore(effectiveGeometryRestore);
3437 doSetQuickTileMode();
3438 Q_EMIT quickTileModeChanged();
3443 if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Horizontal)) {
3444 mode &= ~QuickTileMode(QuickTileFlag::Horizontal);
3446 if ((mode & QuickTileFlag::Vertical) == QuickTileMode(QuickTileFlag::Vertical)) {
3447 mode &= ~QuickTileMode(QuickTileFlag::Vertical);
3453 if (mode != QuickTileMode(QuickTileFlag::None)) {
3454 m_quickTileMode = int(QuickTileFlag::None);
3456 setMaximize(
false,
false);
3458 moveResize(quickTileGeometry(mode, keyboard ? moveResizeGeometry().center() : Cursors::self()->mouse()->pos()));
3460 m_quickTileMode = mode;
3462 m_quickTileMode = mode;
3463 setMaximize(
false,
false);
3466 doSetQuickTileMode();
3467 Q_EMIT quickTileModeChanged();
3472 QPointF whichScreen = keyboard ? moveResizeGeometry().center() : Cursors::self()->mouse()->pos();
3473 if (mode != QuickTileMode(QuickTileFlag::None)) {
3476 if (quickTileMode() == mode) {
3477 Output *currentOutput = moveResizeOutput();
3478 Output *nextOutput = currentOutput;
3479 Output *candidateOutput = currentOutput;
3480 if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Left)) {
3482 }
else if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Right)) {
3485 bool shiftHorizontal = candidateOutput != nextOutput;
3486 nextOutput = candidateOutput;
3487 if ((mode & QuickTileFlag::Vertical) == QuickTileMode(QuickTileFlag::Top)) {
3489 }
else if ((mode & QuickTileFlag::Vertical) == QuickTileMode(QuickTileFlag::Bottom)) {
3492 bool shiftVertical = candidateOutput != nextOutput;
3493 nextOutput = candidateOutput;
3495 if (nextOutput == currentOutput) {
3496 mode = QuickTileFlag::None;
3499 moveResize(geometryRestore().translated(nextOutput->
geometry().topLeft() - currentOutput->
geometry().topLeft()));
3500 whichScreen = nextOutput->
geometry().center();
3503 if (shiftHorizontal) {
3504 mode = (~mode & QuickTileFlag::Horizontal) | (mode & QuickTileFlag::Vertical);
3506 if (shiftVertical) {
3507 mode = (~mode & QuickTileFlag::Vertical) | (mode & QuickTileFlag::Horizontal);
3510 }
else if (quickTileMode() == QuickTileMode(QuickTileFlag::None)) {
3513 setGeometryRestore(quickTileGeometryRestore());
3516 m_quickTileMode = mode;
3519 if (mode == QuickTileMode(QuickTileFlag::None)) {
3521 m_quickTileMode = int(QuickTileFlag::None);
3523 if (geometryRestore().isValid()) {
3524 moveResize(geometryRestore());
3526 checkWorkspacePosition();
3527 }
else if (mode == QuickTileMode(QuickTileFlag::Custom)) {
3528 Tile *tile =
nullptr;
3543 doSetQuickTileMode();
3544 Q_EMIT quickTileModeChanged();
3549 if (m_tile == tile) {
3551 }
else if (m_tile) {
3552 m_tile->removeWindow(
this);
3561 Q_EMIT tileChanged(tile);
3569void Window::doSetQuickTileMode()
3573void Window::doSetHidden()
3577void Window::doSetHiddenByShowDesktop()
3581QRectF Window::moveToArea(
const QRectF &geometry,
const QRectF &oldArea,
const QRectF &newArea)
3583 QRectF ret = geometry;
3586 QPointF center = geometry.center() - oldArea.center();
3587 center.setX(center.x() * newArea.width() / oldArea.width());
3588 center.setY(center.y() * newArea.height() / oldArea.height());
3589 center += newArea.center();
3590 ret.moveCenter(center);
3593 if (oldArea.contains(geometry)) {
3594 ret = keepInArea(ret, newArea);
3599QRectF Window::ensureSpecialStateGeometry(
const QRectF &geometry)
3601 if (isRequestedFullScreen()) {
3605 QRectF ret = geometry;
3607 ret.setX(maximizeArea.x());
3608 ret.setWidth(maximizeArea.width());
3611 ret.setY(maximizeArea.y());
3612 ret.setHeight(maximizeArea.height());
3615 }
else if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
3616 return quickTileGeometry(quickTileMode(), geometry.center());
3624 newOutput = rules()->checkOutput(newOutput);
3629 for (
Window *other : windows) {
3630 if (other->isFullScreen() && other->output() == newOutput) {
3631 other->updateLayer();
3635 if (moveResizeOutput() == newOutput) {
3639 const QRectF oldGeom = moveResizeGeometry();
3643 if (m_quickTileMode == QuickTileMode(QuickTileFlag::Custom)) {
3647 QRectF newGeom = moveToArea(oldGeom, oldScreenArea, screenArea);
3648 newGeom = ensureSpecialStateGeometry(newGeom);
3649 moveResize(newGeom);
3652 m_fullscreenGeometryRestore = moveToArea(m_fullscreenGeometryRestore, oldScreenArea, screenArea);
3653 m_maximizeGeometryRestore = moveToArea(m_maximizeGeometryRestore, oldScreenArea, screenArea);
3656 for (
auto it = tso.constBegin(), end = tso.constEnd(); it != end; ++it) {
3657 (*it)->sendToOutput(newOutput);
3661void Window::checkWorkspacePosition(QRectF oldGeometry,
const VirtualDesktop *oldDesktop)
3664 qCWarning(KWIN_CORE) <<
"Window::checkWorkspacePosition: called for a closed window. Consider this a bug";
3667 if (isDock() || isDesktop() || !isPlaceable()) {
3671 QRectF newGeom = moveResizeGeometry();
3673 if (!oldGeometry.isValid()) {
3674 oldGeometry = newGeom;
3677 VirtualDesktop *desktop = !isOnCurrentDesktop() ? desktops().constLast() : VirtualDesktopManager::self()->currentDesktop();
3679 oldDesktop = desktop;
3685 QRect oldScreenArea;
3687 if (
workspace()->inUpdateClientArea()) {
3689 Output *newOutput = moveResizeOutput();
3690 if (!
workspace()->outputs().contains(newOutput)) {
3695 if (oldScreenArea.isNull()) {
3696 oldScreenArea = newOutput->
geometry();
3698 screenArea = newOutput->
geometry();
3699 newGeom.translate(screenArea.topLeft() - oldScreenArea.topLeft());
3705 if (isRequestedFullScreen() || requestedMaximizeMode() !=
MaximizeRestore || quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
3706 moveResize(ensureSpecialStateGeometry(newGeom));
3707 m_fullscreenGeometryRestore = moveToArea(m_fullscreenGeometryRestore, oldScreenArea, screenArea);
3708 m_maximizeGeometryRestore = moveToArea(m_maximizeGeometryRestore, oldScreenArea, screenArea);
3712 const QRect oldGeomTall = QRect(oldGeometry.x(), oldScreenArea.y(), oldGeometry.width(), oldScreenArea.height());
3713 const QRect oldGeomWide = QRect(oldScreenArea.x(), oldGeometry.y(), oldScreenArea.width(), oldGeometry.height());
3714 int oldTopMax = oldScreenArea.y();
3715 int oldRightMax = oldScreenArea.x() + oldScreenArea.width();
3716 int oldBottomMax = oldScreenArea.y() + oldScreenArea.height();
3717 int oldLeftMax = oldScreenArea.x();
3718 int topMax = screenArea.y();
3719 int rightMax = screenArea.x() + screenArea.width();
3720 int bottomMax = screenArea.y() + screenArea.height();
3721 int leftMax = screenArea.x();
3722 const QRect newGeomTall = QRect(newGeom.x(), screenArea.y(), newGeom.width(), screenArea.height());
3723 const QRect newGeomWide = QRect(screenArea.x(), newGeom.y(), screenArea.width(), newGeom.height());
3729 &Workspace::restrictedMoveArea;
3732 QRect rect = r & oldGeomTall;
3733 if (!rect.isEmpty()) {
3734 oldTopMax = std::max(oldTopMax, rect.y() + rect.height());
3738 QRect rect = r & oldGeomWide;
3739 if (!rect.isEmpty()) {
3740 oldRightMax = std::min(oldRightMax, rect.x());
3744 QRect rect = r & oldGeomTall;
3745 if (!rect.isEmpty()) {
3746 oldBottomMax = std::min(oldBottomMax, rect.y());
3750 QRect rect = r & oldGeomWide;
3751 if (!rect.isEmpty()) {
3752 oldLeftMax = std::max(oldLeftMax, rect.x() + rect.width());
3758 QRect rect = r & newGeomTall;
3759 if (!rect.isEmpty()) {
3760 topMax = std::max(topMax, rect.y() + rect.height());
3764 QRect rect = r & newGeomWide;
3765 if (!rect.isEmpty()) {
3766 rightMax = std::min(rightMax, rect.x());
3770 QRect rect = r & newGeomTall;
3771 if (!rect.isEmpty()) {
3772 bottomMax = std::min(bottomMax, rect.y());
3776 QRect rect = r & newGeomWide;
3777 if (!rect.isEmpty()) {
3778 leftMax = std::max(leftMax, rect.x() + rect.width());
3789 bool keep[4] = {
false,
false,
false,
false};
3790 bool save[4] = {
false,
false,
false,
false};
3791 if (oldGeometry.x() >= oldLeftMax) {
3792 save[Left] = newGeom.x() < leftMax;
3794 if (oldGeometry.x() == oldLeftMax) {
3795 keep[Left] = newGeom.x() != leftMax;
3798 if (oldGeometry.y() >= oldTopMax) {
3799 save[
Top] = newGeom.y() < topMax;
3801 if (oldGeometry.y() == oldTopMax) {
3802 keep[
Top] = newGeom.y() != topMax;
3805 if (oldGeometry.right() <= oldRightMax) {
3806 save[Right] = newGeom.right() > rightMax;
3808 if (oldGeometry.right() == oldRightMax) {
3809 keep[Right] = newGeom.right() != rightMax;
3812 if (oldGeometry.bottom() <= oldBottomMax) {
3813 save[
Bottom] = newGeom.bottom() > bottomMax;
3815 if (oldGeometry.bottom() == oldBottomMax) {
3816 keep[
Bottom] = newGeom.bottom() != bottomMax;
3820 if (keep[Left] && keep[Right]) {
3821 keep[Left] = keep[Right] =
false;
3827 if (save[Left] || keep[Left]) {
3828 newGeom.moveLeft(std::max(leftMax, screenArea.x()));
3830 if (save[
Top] || keep[
Top]) {
3831 newGeom.moveTop(std::max(topMax, screenArea.y()));
3833 if (save[Right] || keep[Right]) {
3834 newGeom.moveRight(std::min(rightMax, screenArea.right()) + 1);
3837 newGeom.moveBottom(std::min(bottomMax, screenArea.bottom()) + 1);
3840 if (oldGeometry.x() >= oldLeftMax && newGeom.x() < leftMax) {
3841 newGeom.setLeft(std::max(leftMax, screenArea.x()));
3843 if (oldGeometry.y() >= oldTopMax && newGeom.y() < topMax) {
3844 newGeom.setTop(std::max(topMax, screenArea.y()));
3847 checkOffscreenPosition(&newGeom, screenArea);
3850 newGeom.setSize(constrainFrameSize(newGeom.size()));
3853 moveResize(newGeom);
3856void Window::checkOffscreenPosition(QRectF *geom,
const QRectF &screenArea)
3858 if (geom->left() > screenArea.right()) {
3859 geom->moveLeft(screenArea.right() - screenArea.width() / 4);
3860 }
else if (geom->right() < screenArea.left()) {
3861 geom->moveRight(screenArea.left() + screenArea.width() / 4);
3863 if (geom->top() > screenArea.bottom()) {
3864 geom->moveTop(screenArea.bottom() - screenArea.height() / 4);
3865 }
else if (geom->bottom() < screenArea.top()) {
3866 geom->moveBottom(screenArea.top() + screenArea.width() / 4);
3875QSizeF Window::constrainClientSize(
const QSizeF &size,
SizeMode mode)
const
3877 qreal width = size.width();
3878 qreal height = size.height();
3889 const QSizeF minimumSize = minSize();
3890 const QSizeF maximumSize = maxSize();
3892 width = std::clamp(width, minimumSize.width(), maximumSize.width());
3893 height = std::clamp(height, minimumSize.height(), maximumSize.height());
3895 return QSizeF(width, height);
3901QSizeF Window::constrainFrameSize(
const QSizeF &size,
SizeMode mode)
const
3903 const QSizeF unconstrainedClientSize = frameSizeToClientSize(size);
3904 const QSizeF constrainedClientSize = constrainClientSize(unconstrainedClientSize, mode);
3905 return clientSizeToFrameSize(constrainedClientSize);
3908QRectF Window::fullscreenGeometryRestore()
const
3910 return m_fullscreenGeometryRestore;
3913void Window::setFullscreenGeometryRestore(
const QRectF &geom)
3915 m_fullscreenGeometryRestore = geom;
3923bool Window::isFullScreenable()
const
3935bool Window::isFullScreen()
const
3940bool Window::isRequestedFullScreen()
const
3942 return isFullScreen();
3952void Window::setFullScreen(
bool set)
3954 qCWarning(KWIN_CORE,
"%s doesn't support setting fullscreen state", metaObject()->className());
3957bool Window::wantsAdaptiveSync()
const
3959 return rules()->checkAdaptiveSync(isFullScreen());
3967bool Window::isMinimizable()
const
3977bool Window::isMaximizable()
const
4001 return maximizeMode();
4007QRectF Window::geometryRestore()
const
4009 return m_maximizeGeometryRestore;
4015void Window::setGeometryRestore(
const QRectF &rect)
4017 m_maximizeGeometryRestore = rect;
4020void Window::invalidateDecoration()
4024bool Window::noBorder()
const
4029bool Window::userCanSetNoBorder()
const
4034void Window::setNoBorder(
bool set)
4036 qCWarning(KWIN_CORE,
"%s doesn't support setting decorations", metaObject()->className());
4039void Window::checkNoBorder()
4044void Window::showOnScreenEdge()
4046 qCWarning(KWIN_CORE,
"%s doesn't support screen edge activation", metaObject()->className());
4049bool Window::isPlaceable()
const
4054void Window::cleanTabBox()
4056#if KWIN_BUILD_TABBOX
4064bool Window::supportsWindowRules()
const
4071 m_rules.remove(rule);
4074void Window::evaluateWindowRules()
4080void Window::setupWindowRules()
4082 disconnect(
this, &Window::captionNormalChanged,
this, &Window::evaluateWindowRules);
4087void Window::updateWindowRules(Rules::Types selection)
4089 if (
workspace()->rulebook()->areUpdatesDisabled()) {
4092 m_rules.
update(
this, selection);
4095void Window::finishWindowRules()
4097 disconnect(
this, &Window::captionNormalChanged,
this, &Window::evaluateWindowRules);
4098 updateWindowRules(Rules::All);
4104void Window::applyWindowRules()
4106 Q_ASSERT(!isDeleted());
4110 auto client_rules = rules();
4111 const QRectF oldGeometry = moveResizeGeometry();
4112 const QRectF geometry = client_rules->checkGeometrySafe(oldGeometry);
4113 if (geometry != oldGeometry) {
4114 moveResize(geometry);
4118 setDesktops(desktops());
4120 setOnActivities(activities());
4122 maximize(requestedMaximizeMode());
4123 setMinimized(isMinimized());
4124 setShade(shadeMode());
4125 setOriginalSkipTaskbar(skipTaskbar());
4126 setSkipPager(skipPager());
4127 setSkipSwitcher(skipSwitcher());
4128 setKeepAbove(keepAbove());
4129 setKeepBelow(keepBelow());
4130 setFullScreen(isRequestedFullScreen());
4131 setNoBorder(noBorder());
4132 updateColorScheme();
4136 if (
workspace()->mostRecentlyActivatedWindow() ==
this
4137 && !client_rules->checkAcceptFocus(
true)) {
4144 setShortcut(rules()->checkShortcut(shortcut().toString()));
4147 setOpacity(rules()->checkOpacityActive(qRound(opacity() * 100.0)) / 100.0);
4150 setOpacity(rules()->checkOpacityInactive(qRound(opacity() * 100.0)) / 100.0);
4152 setDesktopFileName(rules()->checkDesktopFile(desktopFileName()));
4155void Window::setLastUsageSerial(quint32 serial)
4157 if (m_lastUsageSerial < serial) {
4158 m_lastUsageSerial = serial;
4162quint32 Window::lastUsageSerial()
const
4164 return m_lastUsageSerial;
4167uint32_t Window::interactiveMoveResizeCount()
const
4169 return m_interactiveMoveResize.counter;
4172void Window::setLockScreenOverlay(
bool allowed)
4174 if (m_lockScreenOverlay == allowed) {
4177 m_lockScreenOverlay = allowed;
4178 Q_EMIT lockScreenOverlayChanged();
4181bool Window::isLockScreenOverlay()
const
4183 return m_lockScreenOverlay;
4186void Window::refOffscreenRendering()
4188 if (m_offscreenRenderCount == 0) {
4189 m_offscreenFramecallbackTimer.start(1'000'000 / output()->refreshRate());
4191 m_offscreenRenderCount++;
4194void Window::unrefOffscreenRendering()
4196 Q_ASSERT(m_offscreenRenderCount);
4197 m_offscreenRenderCount--;
4198 if (m_offscreenRenderCount == 0) {
4199 m_offscreenFramecallbackTimer.stop();
4203void Window::maybeSendFrameCallback()
4205 if (m_surface && !m_windowItem->isVisible()) {
4206 const auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
4211 feedback->presented(std::chrono::nanoseconds(1'000'000'000'000 / output()->refreshRate()), std::chrono::steady_clock::now().time_since_epoch(), PresentationMode::VSync);
4215 m_offscreenFramecallbackTimer.start(1'000'000 / output()->refreshRate());
4219WindowOffscreenRenderRef::WindowOffscreenRenderRef(
Window *window)
4228 m_window->unrefOffscreenRendering();
4293#include "moc_window.cpp"
@ OperationModeX11
KWin uses only X11 for managing windows and compositing.
const QString & hostName() const
static QString localhost()
WorkspaceScene * scene() const
static Compositor * self()
Wrapper round Qt::CursorShape with extensions enums into a single entity.
Representation of a window used by/for Effect classes.
void update(Window *window, Change change)
Updates the position of the window according to the requested change in the focus chain.
void boundingRectChanged()
MouseCommand commandWindowWheel
KWin::Options::WindowOperation operationTitlebarDblClick
bool isShadeHover() const
MouseCommand commandInactiveTitlebar1
MouseCommand commandInactiveTitlebar2
bool isClickRaise() const
MouseCommand commandActiveTitlebar2
bool electricBorderTiling
MouseCommand commandWindow2
MouseCommand commandActiveTitlebar3
MouseCommand commandActiveTitlebar1
MouseCommand commandInactiveTitlebar3
MouseCommand commandWindow3
float electricBorderCornerRatio
bool focusPolicyIsReasonable
bool electricBorderMaximize
bool isSeparateScreenFocus() const
MouseCommand commandWindow1
void place(Window *c, const QRectF &area)
void removePlasmaVirtualDesktop(const QString &id)
void setTitle(const QString &title)
QStringList plasmaVirtualDesktops() const
void addPlasmaVirtualDesktop(const QString &id)
void setOnAllDesktops(bool set)
PlasmaWindowInterface * createWindow(QObject *parent, const QUuid &uuid)
WindowRules find(const Window *window) const
void reserveDesktopSwitching(bool isToReserve, Qt::Orientations o)
Class representing a Window's Shadow to be rendered by the Compositor.
static std::unique_ptr< Shadow > createShadow(Window *window)
Resource representing a wl_surface.
std::unique_ptr< PresentationFeedback > takePresentationFeedback(Output *output)
void frameRendered(quint32 msec)
QModelIndex nextPrev(bool forward) const
void addWindow(Window *window)
QRectF windowGeometry() const
KWin::Tile * quickTile(QuickTileMode mode) const
KWin::Tile * bestTileForPosition(const QPointF &pos)
PlasmaWindowManagementInterface * windowManagement() const
Window * findWindow(const SurfaceInterface *surface) const
std::unique_ptr< Shadow > m_shadow
virtual bool isLocalhost() const
void interactiveMoveResizeStarted()
QMatrix4x4 inputTransformation() const
void setOpacity(qreal opacity)
virtual QRectF resizeWithChecks(const QRectF &geometry, const QSizeF &s)=0
void updateElectricGeometryRestore()
QTimer m_offscreenFramecallbackTimer
void startDelayedInteractiveMoveResize()
bool isActiveFullScreen() const
void skipSwitcherChanged()
void triggerDecorationRepaint()
virtual bool hasTransientPlacementHint() const
WindowItem * windowItem() const
void setMinimized(bool set)
void stackingOrderChanged()
virtual void doSetSuspended()
bool m_originalSkipTaskbar
void invalidateDecorationDoubleClickTimer()
void setSurface(SurfaceInterface *surface)
void inputTransformationChanged()
virtual void doSetSkipSwitcher()
QList< VirtualDesktop * > m_desktops
virtual QList< Window * > mainWindows() const
void refOffscreenRendering()
bool isInteractiveMoveResizePointerButtonDown() const
virtual void doSetDesktop()
void setElectricBorderMode(QuickTileMode mode)
QPointF mapToLocal(const QPointF &point) const
virtual bool isClient() const
QString wmClientMachine(bool use_localhost) const
virtual void updateWindowRules(Rules::Types selection)
bool isInteractiveMove() const
virtual void doSetKeepAbove()
void skipCloseAnimationChanged()
MoveResizeMode m_pendingMoveResizeMode
void moveResize(const QRectF &rect)
virtual void updateMouseGrab()
void keepInArea(QRectF area, bool partial=false)
virtual QString preferredColorScheme() const
QRectF initialInteractiveMoveResizeGeometry() const
void stopDelayedInteractiveMoveResize()
bool isNotification() const
virtual void doSetHiddenByShowDesktop()
virtual bool isMinimizable() const
bool startInteractiveMoveResize()
bool isUnrestrictedInteractiveMoveResize() const
void setInteractiveMoveResize(bool enabled)
bool m_skipCloseAnimation
EffectWindow * effectWindow()
SurfaceInterface * surface() const
void setSkipTaskbar(bool set)
void maybeSendFrameCallback()
bool isMostRecentlyRaised() const
std::unique_ptr< WindowItem > m_windowItem
bool wantsTabFocus() const
void demandsAttentionChanged()
void readyForPaintingChanged()
bool isNormalWindow() const
void setTransientFor(Window *transientFor)
virtual void maximize(MaximizeMode mode)
void setGeometryRestore(const QRectF &rect)
virtual bool groupTransient() const
void setColorScheme(const QString &colorScheme)
QPointF mapToFrame(const QPointF &point) const
bool isOnScreenDisplay() const
void setOutput(Output *output)
bool isInteractiveMoveResize() const
void windowShown(KWin::Window *window)
SurfaceItem * surfaceItem() const
static std::shared_ptr< Decoration::DecorationPalette > s_defaultPalette
PlasmaWindowInterface * windowManagementInterface() const
static bool belongToSameApplication(const Window *c1, const Window *c2, SameApplicationChecks checks=SameApplicationChecks())
const Decoration::DecorationPalette * decorationPalette()
void demandAttention(bool set=true)
std::shared_ptr< KDecoration2::Decoration > decoration
bool isHiddenByShowDesktop() const
virtual bool isPopupWindow() const
void opacityChanged(KWin::Window *window, qreal oldOpacity)
void setOnAllDesktops(bool set)
virtual bool isFullScreen() const
bool isCriticalNotification() const
QuickTileMode electricBorderMode() const
virtual bool isMovableAcrossScreens() const =0
bool isOnAllDesktops() const
void handlePaletteChange()
QRectF visibleGeometry() const
virtual bool isInternal() const
bool isInteractiveResize() const
void setQuickTileMode(QuickTileMode mode, bool keyboard=false)
virtual bool isUnmanaged() const
void interactiveMoveResizeFinished()
void finishInteractiveMoveResize(bool cancel)
void leaveDesktop(VirtualDesktop *desktop)
bool isOnCurrentDesktop() const
void setDesktops(QList< VirtualDesktop * > desktops)
bool isAppletPopup() const
void hasApplicationMenuChanged(bool)
virtual MaximizeMode requestedMaximizeMode() const
void setOriginalSkipTaskbar(bool set)
virtual Layer belongsToLayer() const
void colorSchemeChanged()
QTimer * m_shadeHoverTimer
void elevate(bool elevate)
QuickTileMode quickTileMode() const
void setUnrestrictedInteractiveMoveResize(bool set)
void keepAboveChanged(bool)
void startShadeHoverTimer()
bool isLockScreenOverlay() const
virtual void doMinimize()
void setResourceClass(const QString &name, const QString &className=QString())
void checkUnrestrictedInteractiveMoveResize()
QPointer< SurfaceInterface > m_surface
virtual bool belongsToSameApplication(const Window *other, SameApplicationChecks checks) const =0
void setHidden(bool hidden)
struct KWin::Window::@32 m_interactiveMoveResize
QPointF mapFromLocal(const QPointF &point) const
virtual void doSetSkipPager()
void setSuspended(bool suspended)
virtual bool isLockScreen() const
QList< KWin::VirtualDesktop * > desktops
virtual bool setupCompositing()
void skipTaskbarChanged()
void moveResizedChanged()
Output * interactiveMoveResizeStartOutput() const
QMargins frameMargins() const
virtual bool doStartInteractiveMoveResize()
void paletteChanged(const QPalette &p)
void startShadeUnhoverTimer()
virtual void doSetDemandsAttention()
Qt::Edge titlebarPosition() const
virtual void leaveInteractiveMoveResize()
void enterDesktop(VirtualDesktop *desktop)
Output * moveResizeOutput() const
static QHash< QString, std::weak_ptr< Decoration::DecorationPalette > > s_palettes
virtual void doSetActive()
std::shared_ptr< Decoration::DecorationPalette > m_palette
virtual bool isRequestedFullScreen() const
QRectF moveResizeGeometry() const
virtual std::unique_ptr< WindowItem > createItem(Scene *scene)=0
QRectF geometryRestore() const
void hiddenByShowDesktopChanged()
virtual void doSetHidden()
bool isOnDesktop(VirtualDesktop *desktop) const
void bufferGeometryChanged(const QRectF &oldGeometry)
const WindowRules * rules() const
ShadeMode shadeMode() const
int m_blockGeometryUpdates
const QList< Window * > & transients() const
virtual xcb_timestamp_t userTime() const
void setStackingOrder(int order)
void setReadyForPainting()
void setSkipPager(bool set)
KWin::Window * transientFor
virtual bool isShadeable() const
bool wantsShadowToBeRendered() const
void checkWorkspacePosition(QRectF oldGeometry=QRectF(), const VirtualDesktop *oldDesktop=nullptr)
void blockGeometryUpdates()
QStringList desktopIds() const
bool isOnActiveOutput() const
bool isElectricBorderMaximizing() const
void setHiddenByShowDesktop(bool hidden)
void frameGeometryChanged(const QRectF &oldGeometry)
virtual bool isInputMethod() const
void setIcon(const QIcon &icon)
virtual void doSetSkipTaskbar()
virtual void doSetKeepBelow()
virtual bool hitTest(const QPointF &point) const
void keepBelowChanged(bool)
bool isSpecialWindow() const
void windowHidden(KWin::Window *window)
void setSkipCloseAnimation(bool set)
void visibleGeometryChanged()
void cancelShadeHoverTimer()
void windowClassChanged()
virtual bool belongsToDesktop() const
virtual void finishCompositing()
struct KWin::Window::@33 m_decoration
bool m_hiddenByShowDesktop
bool titlebarPositionUnderMouse() const
ClientMachine * m_clientMachine
virtual MaximizeMode maximizeMode() const
void setElectricBorderMaximizing(bool maximizing)
virtual void doSetShade(ShadeMode previousShadeMode)
Gravity interactiveMoveResizeGravity() const
virtual void doFinishInteractiveMoveResize()
void setSkipSwitcher(bool set)
QRectF m_keyboardGeometryRestore
bool isOnOutput(Output *output) const
Q_INVOKABLE void setMaximize(bool vertically, bool horizontally)
virtual bool isPlaceable() const
QTimer * m_autoRaiseTimer
virtual void moveResizeInternal(const QRectF &rect, MoveResizeMode mode)=0
~WindowOffscreenRenderRef()
QSizeF checkMaxSize(QSizeF s) const
Layer checkLayer(Layer layer) const
int checkOpacityInactive(int s) const
bool checkKeepBelow(bool below, bool init=false) const
bool checkSkipSwitcher(bool skip, bool init=false) const
QString checkDecoColor(QString schemeFile) const
bool checkSkipPager(bool skip, bool init=false) const
void update(Window *, int selection)
QList< VirtualDesktop * > checkDesktops(QList< VirtualDesktop * > desktops, bool init=false) const
ShadeMode checkShade(ShadeMode shade, bool init=false) const
bool checkMinimize(bool minimized, bool init=false) const
int checkOpacityActive(int s) const
bool checkSkipTaskbar(bool skip, bool init=false) const
QSizeF checkMinSize(QSizeF s) const
bool checkKeepAbove(bool above, bool init=false) const
TileManager * tileManager(Output *output)
bool inUpdateClientArea() const
void windowAttentionChanged(Window *, bool set)
Window * mostRecentlyActivatedWindow() const
QRectF clientArea(clientAreaOption, const Output *output, const VirtualDesktop *desktop) const
void windowHidden(Window *)
ScreenEdges * screenEdges() const
void constrain(Window *below, Window *above)
void activateWindow(Window *window, bool force=false)
const QList< Window * > & stackingOrder() const
void sendWindowToOutput(Window *window, Output *output)
void windowToNextDesktop(Window *window)
Window * windowUnderMouse(Output *output) const
void showWindowMenu(const QRect &pos, Window *cl)
Outline * outline() const
void raiseWindow(Window *window, bool nogroup=false)
Placement * placement() const
static Workspace * self()
Window * topWindowOnDesktop(VirtualDesktop *desktop, Output *output=nullptr, bool unconstrained=false, bool only_normal=true) const
QRectF adjustWindowSize(Window *window, QRectF moveResizeGeom, Gravity gravity)
StrutRects restrictedMoveArea(const VirtualDesktop *desktop, StrutAreas areas=StrutAreaAll) const
FocusChain * focusChain() const
void updateFocusMousePosition(const QPointF &pos)
RuleBook * rulebook() const
void setMoveResizeWindow(Window *window)
void lowerWindow(Window *window, bool nogroup=false)
QList< Output * > outputs() const
void setActiveWindow(Window *window)
const QList< Window * > windows() const
bool activateNextWindow(Window *window)
bool requestFocus(Window *window, bool force=false)
void setActiveOutput(Output *output)
bool takeActivity(Window *window, ActivityFlags flags)
Output * outputAt(const QPointF &pos) const
void removeDeleted(Window *)
void windowToPreviousDesktop(Window *window)
void unconstrain(Window *below, Window *above)
Output * findOutput(Output *reference, Direction direction, bool wrapAround=false) const
void addDeleted(Window *)
void raiseOrLowerWindow(Window *window)
QList< X11Window * > ensureStackingOrder(const QList< X11Window * > &windows) const
void disableGlobalShortcutsForClient(bool disable)
QHash< const Output *, QRect > previousScreenSizes() const
void requestDelayFocus(Window *)
Item * containerItem() const
QDebug & operator<<(QDebug &s, const KWin::DrmConnector *obj)
@ MaximizeVertical
The window is maximized vertically.
@ MaximizeRestore
The window is not maximized in any direction.
@ MaximizeFull
Equal to MaximizeVertical | MaximizeHorizontal.
WaylandServer * waylandServer()
QList< StrutRect > StrutRects
InputRedirection * input()
KWIN_EXPORT QPoint flooredPoint(const QPointF &point)
@ CriticalNotificationLayer