18#if KWIN_BUILD_ACTIVITIES
66#include <KConfigGroup>
67#include <KLocalizedString>
68#include <KStartupInfo>
70#include <QCryptographicHash>
71#include <QDBusConnection>
72#include <QDBusPendingCall>
73#include <QMetaProperty>
75#include <xcb/xinerama.h>
95 , m_quickTileCombineTimer(nullptr)
96 , active_popup(nullptr)
97 , m_activePopupWindow(nullptr)
99 , m_activeWindow(nullptr)
100 , m_lastActiveWindow(nullptr)
101 , m_moveResizeWindow(nullptr)
102 , m_delayFocusWindow(nullptr)
103 , force_restacking(false)
104 , showing_desktop(false)
105 , was_user_interaction(false)
109 , m_focusChain(std::make_unique<
FocusChain>())
118#if KWIN_BUILD_ACTIVITIES
119 if (kwinApp()->usesKActivities()) {
120 m_activities = std::make_unique<Activities>();
127 delayFocusTimer =
nullptr;
129 m_quickTileCombineTimer =
new QTimer(
this);
130 m_quickTileCombineTimer->setSingleShot(
true);
132 m_rulebook = std::make_unique<RuleBook>();
135 m_screenEdges = std::make_unique<ScreenEdges>();
140 VirtualDesktopManager::create(
this);
146 m_tabbox = std::make_unique<TabBox::TabBox>();
149 m_decorationBridge = std::make_unique<Decoration::DecorationBridge>();
150 m_decorationBridge->init();
154 m_outline = std::make_unique<Outline>();
161void Workspace::init()
163 KSharedConfigPtr config = kwinApp()->config();
164 m_screenEdges->setConfig(config);
165 m_screenEdges->init();
173 m_focusChain->setCurrentDesktop(VirtualDesktopManager::self()->currentDesktop());
178 slotOutputBackendOutputsQueried();
193 m_placement = std::make_unique<Placement>();
204 reconfigureTimer.setSingleShot(
true);
205 updateToolWindowsTimer.setSingleShot(
true);
208 connect(&updateToolWindowsTimer, &QTimer::timeout,
this, &Workspace::slotUpdateToolWindows);
212 QDBusConnection::sessionBus().connect(QString(),
213 QStringLiteral(
"/KDEPlatformTheme"),
214 QStringLiteral(
"org.kde.KDEPlatformTheme"),
215 QStringLiteral(
"refreshFonts"),
218 m_activeWindow =
nullptr;
240 m_placementTracker->init(getPlacementTrackerHash());
242 const auto applySensorChanges = [
this]() {
243 m_orientationSensor->setEnabled(m_outputConfigStore->isAutoRotateActive(kwinApp()->outputBackend()->
outputs(), kwinApp()->tabletModeManager()->effectiveTabletMode()));
244 const auto opt = m_outputConfigStore->queryConfig(kwinApp()->outputBackend()->outputs(), m_lidSwitchTracker->isLidClosed(), m_orientationSensor->reading(), kwinApp()->tabletModeManager()->effectiveTabletMode());
246 const auto &[config, order,
type] = *opt;
253 m_orientationSensor->setEnabled(m_outputConfigStore->isAutoRotateActive(kwinApp()->outputBackend()->
outputs(), kwinApp()->tabletModeManager()->effectiveTabletMode()));
256QString Workspace::getPlacementTrackerHash()
259 for (
const auto &output : std::as_const(m_outputs)) {
260 QCryptographicHash hash(QCryptographicHash::Md5);
261 if (output->edid().isValid()) {
262 hash.addData(output->edid().raw());
264 hash.addData(output->name().toLatin1());
266 const auto geometry = output->geometry();
268 hashes.push_back(QString::fromLatin1(hash.result().toHex()));
270 std::sort(hashes.begin(), hashes.end());
271 const auto hash = QCryptographicHash::hash(hashes.join(QString()).toLatin1(), QCryptographicHash::Md5);
272 return QString::fromLatin1(hash.toHex());
275void Workspace::initializeX11()
277 if (!kwinApp()->x11Connection()) {
287 m_startup = std::make_unique<KStartupInfo>(KStartupInfo::DisableKWinModule | KStartupInfo::AnnounceSilenceChanges,
this);
290 selectWmInputEventMask();
293 m_wasUserInteractionFilter = std::make_unique<WasUserInteractionX11Filter>();
294 m_movingClientFilter = std::make_unique<MovingClientX11Filter>();
297 m_syncAlarmFilter = std::make_unique<SyncAlarmX11Filter>();
299 kwinApp()->updateXTime();
301 const uint32_t nullFocusValues[] = {
true};
302 m_nullFocus = std::make_unique<Xcb::Window>(QRect(-1, -1, 1, 1), XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, nullFocusValues);
308 const auto vds = VirtualDesktopManager::self();
313 NETRootInfo client_info(kwinApp()->x11Connection(), NET::ActiveWindow | NET::CurrentDesktop);
314 bool sessionRestored =
false;
315#ifndef QT_NO_SESSIONMANAGER
316 sessionRestored = qApp->isSessionRestored();
319 if (!sessionRestored) {
320 m_initialDesktop = client_info.currentDesktop();
326 rootInfo->setActiveWindow(XCB_WINDOW_NONE);
329 if (!sessionRestored) {
337 Xcb::Tree tree(kwinApp()->x11RootWindow());
338 xcb_window_t *wins = xcb_query_tree_children(tree.data());
340 QList<Xcb::WindowAttributes> windowAttributes(tree->children_len);
341 QList<Xcb::WindowGeometry> windowGeometries(tree->children_len);
344 for (
int i = 0; i < tree->children_len; i++) {
345 windowAttributes[i] = Xcb::WindowAttributes(wins[i]);
346 windowGeometries[i] = Xcb::WindowGeometry(wins[i]);
350 for (
int i = 0; i < tree->children_len; i++) {
351 Xcb::WindowAttributes attr(windowAttributes.at(i));
357 if (attr->override_redirect) {
358 if (attr->map_state == XCB_MAP_STATE_VIEWABLE && attr->_class != XCB_WINDOW_CLASS_INPUT_ONLY) {
360 createUnmanaged(wins[i]);
362 }
else if (attr->map_state != XCB_MAP_STATE_UNMAPPED) {
364 fixPositionAfterCrash(wins[i], windowGeometries.at(i).data());
368 createX11Window(wins[i],
true);
378 NETPoint *viewports =
new NETPoint[VirtualDesktopManager::self()->count()];
379 rootInfo->setDesktopViewport(VirtualDesktopManager::self()->count(), *viewports);
382 NETSize desktop_geometry;
383 desktop_geometry.width = m_geometry.width();
384 desktop_geometry.height = m_geometry.height();
385 rootInfo->setDesktopGeometry(desktop_geometry);
390 Window *newActiveWindow =
nullptr;
391 if (!sessionRestored) {
395 if (newActiveWindow ==
nullptr &&
activeWindow() ==
nullptr && should_get_focus.count() == 0) {
397 if (newActiveWindow ==
nullptr) {
398 newActiveWindow =
topWindowOnDesktop(VirtualDesktopManager::self()->currentDesktop());
400 if (newActiveWindow ==
nullptr) {
401 newActiveWindow =
findDesktop(
true, VirtualDesktopManager::self()->currentDesktop());
404 if (newActiveWindow !=
nullptr) {
409void Workspace::cleanupX11()
417 const auto stack = stacking_order;
418 for (
Window *window : stack) {
419 if (
auto x11 = qobject_cast<X11Window *>(window); x11 && !x11->isDeleted()) {
420 x11->releaseWindow(
true);
421 removeFromStack(window);
425 manual_overlays.clear();
427 VirtualDesktopManager *desktopManager = VirtualDesktopManager::self();
428 desktopManager->setRootInfo(
nullptr);
434 m_movingClientFilter.reset();
437 m_syncAlarmFilter.reset();
438 m_wasUserInteractionFilter.reset();
443 blockStackingUpdates(
true);
449 for (
Window *window : waylandWindows) {
450 window->destroyWindow();
455 const QList<Window *>
windows = m_windows;
457 window->destroyWindow();
461 kwinApp()->config()->sync();
464 delete m_windowKeysDialog;
466 if (m_placeholderOutput) {
467 m_placeholderOutput->
unref();
469 m_tileManagers.clear();
471 for (
Output *output : std::as_const(m_outputs)) {
480 if (!kwinApp()->outputBackend()->applyOutputChanges(config)) {
484 m_outputConfigStore->storeConfig(kwinApp()->outputBackend()->
outputs(), m_lidSwitchTracker->isLidClosed(), config,
outputOrder);
485 KConfig cfg(QStringLiteral(
"kdeglobals"));
486 KConfigGroup kscreenGroup = cfg.group(QStringLiteral(
"KScreen"));
487 const bool xwaylandClientsScale = kscreenGroup.readEntry(
"XwaylandClientsScale",
true);
488 if (xwaylandClientsScale && !
outputOrder.isEmpty()) {
492 maxScale = std::max(maxScale, changeset ? changeset->scale.value_or(output->scale()) : output->scale());
494 kwinApp()->setXwaylandScale(maxScale);
496 kwinApp()->setXwaylandScale(1);
498 m_orientationSensor->setEnabled(m_outputConfigStore->isAutoRotateActive(kwinApp()->outputBackend()->
outputs(), kwinApp()->tabletModeManager()->effectiveTabletMode()));
502void Workspace::updateOutputConfiguration()
505 if (QStandardPaths::isTestModeEnabled()) {
509 const auto outputs = kwinApp()->outputBackend()->outputs();
517 const auto setFallbackOutputOrder = [
this, &
outputs]() {
519 newOrder.erase(std::remove_if(newOrder.begin(), newOrder.end(), [](Output *o) {
520 return !o->isEnabled();
523 std::sort(newOrder.begin(), newOrder.end(), [](Output *left, Output *right) {
524 return left->name() < right->name();
529 const auto opt = m_outputConfigStore->queryConfig(
outputs, m_lidSwitchTracker->isLidClosed(), m_orientationSensor->reading(), kwinApp()->tabletModeManager()->effectiveTabletMode());
533 const auto &[cfg, order,
type] = *opt;
535 qCWarning(KWIN_CORE) <<
"Applying output config failed!";
536 setFallbackOutputOrder();
541 const bool hasInternal = std::any_of(
outputs.begin(),
outputs.end(), [](Output *o) {
542 return o->isInternal();
544 if (hasInternal &&
outputs.size() == 2) {
546 QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral(
"org.kde.kscreen.osdService"),
547 QStringLiteral(
"/org/kde/kscreen/osdService"),
548 QStringLiteral(
"org.kde.kscreen.osdService"),
549 QStringLiteral(
"showActionSelector"));
550 QDBusConnection::sessionBus().asyncCall(message);
555void Workspace::setupWindowConnections(
Window *window)
563 if (below == above) {
567 QList<Constraint *> parents;
568 QList<Constraint *> children;
569 for (Constraint *constraint : std::as_const(m_constraints)) {
570 if (constraint->below == below && constraint->above == above) {
573 if (constraint->below == above) {
574 children << constraint;
575 }
else if (constraint->above == below) {
576 parents << constraint;
581 constraint->parents = parents;
582 constraint->below = below;
583 constraint->above = above;
584 constraint->children = children;
585 m_constraints << constraint;
587 for (Constraint *parent : std::as_const(parents)) {
588 parent->children << constraint;
591 for (Constraint *child : std::as_const(children)) {
592 child->parents << constraint;
600 Constraint *constraint =
nullptr;
601 for (
int i = 0; i < m_constraints.count(); ++i) {
602 if (m_constraints[i]->below == below && m_constraints[i]->above == above) {
603 constraint = m_constraints.takeAt(i);
612 const QList<Constraint *> parents = constraint->parents;
613 for (Constraint *parent : parents) {
614 parent->children.removeOne(constraint);
617 const QList<Constraint *> children = constraint->children;
618 for (Constraint *child : children) {
619 child->parents.removeOne(constraint);
626void Workspace::addToStack(
Window *window)
630 if (!unconstrained_stacking_order.contains(window)) {
631 unconstrained_stacking_order.append(window);
633 if (!stacking_order.contains(window)) {
634 stacking_order.append(window);
638void Workspace::removeFromStack(
Window *window)
640 unconstrained_stacking_order.removeAll(window);
641 stacking_order.removeAll(window);
643 for (
int i = m_constraints.count() - 1; i >= 0; --i) {
645 const bool isBelow = (constraint->below == window);
646 const bool isAbove = (constraint->above == window);
647 if (!isBelow && !isAbove) {
651 for (
Constraint *child : std::as_const(constraint->children)) {
652 child->parents.removeOne(constraint);
655 for (
Constraint *parent : std::as_const(constraint->parents)) {
656 parent->children.removeOne(constraint);
659 delete m_constraints.takeAt(i);
663X11Window *Workspace::createX11Window(xcb_window_t windowId,
bool is_mapped)
666 X11Window *window =
new X11Window();
667 setupWindowConnections(window);
668 if (!window->manage(windowId, is_mapped)) {
672 addX11Window(window);
677X11Window *Workspace::createUnmanaged(xcb_window_t windowId)
679 if (kwinApp()->x11CompositeWindow() == windowId) {
682 X11Window *window =
new X11Window();
683 if (!window->track(windowId)) {
687 addUnmanaged(window);
691void Workspace::addX11Window(X11Window *window)
697 Group *grp =
findGroup(window->window());
698 if (grp !=
nullptr) {
699 grp->gotLeader(window);
702 if (window->isDesktop()) {
703 if (m_activeWindow ==
nullptr && should_get_focus.isEmpty() && window->isOnCurrentDesktop()) {
709 Q_ASSERT(!m_windows.contains(window));
710 m_windows.append(window);
712 if (window->hasStrut()) {
715 window->updateLayer();
716 if (window->isDesktop()) {
719 if (
activeWindow() ==
nullptr && should_get_focus.count() == 0) {
723 window->checkActiveModal();
726 if (window->isUtility() || window->isMenu() || window->isToolbar()) {
727 updateToolWindows(
true);
732void Workspace::addUnmanaged(X11Window *window)
734 Q_ASSERT(!m_windows.contains(window));
735 m_windows.append(window);
746 Q_ASSERT(m_windows.contains(window));
748 if (group !=
nullptr) {
751 removeWindow(window);
756 Q_ASSERT(m_windows.contains(window));
757 m_windows.removeOne(window);
758 removeFromStack(window);
765 Q_ASSERT(!deleted.contains(c));
771 Q_ASSERT(deleted.contains(c));
773 deleted.removeAll(c);
777void Workspace::addWaylandWindow(
Window *window)
783 setupWindowConnections(window);
788 bool placementDone =
false;
790 placementDone =
true;
793 placementDone =
true;
796 placementDone =
true;
798 if (!placementDone) {
799 m_placement->place(window, area);
802 Q_ASSERT(!m_windows.contains(window));
803 m_windows.append(window);
820void Workspace::removeWaylandWindow(
Window *window)
823 removeWindow(window);
826void Workspace::removeWindow(
Window *window)
828 if (window == m_activePopupWindow) {
832 m_userActionsMenu->
close();
835 m_windows.removeAll(window);
836 if (window == m_delayFocusWindow) {
839 attention_chain.removeAll(window);
840 should_get_focus.removeAll(window);
841 if (window == m_activeWindow) {
842 m_activeWindow =
nullptr;
844 if (window == m_lastActiveWindow) {
845 m_lastActiveWindow =
nullptr;
847 if (m_windowKeysWindow == window) {
850 if (window->hasStrut()) {
860void Workspace::updateToolWindows(
bool also_hide)
864 for (
auto it = m_windows.constBegin(); it != m_windows.constEnd(); ++it) {
865 if (X11Window *x11Window = qobject_cast<X11Window *>(*it)) {
866 x11Window->setHidden(
false);
871 const Group *group =
nullptr;
872 auto window = m_activeWindow;
875 while (window !=
nullptr) {
876 if (!window->isTransient()) {
879 if (window->groupTransient()) {
880 group = window->group();
883 window = window->transientFor();
889 QList<Window *> to_show, to_hide;
890 for (
auto it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) {
892 if (!c->isClient()) {
895 if (c->isUtility() || c->isMenu() || c->isToolbar()) {
897 if (!c->isTransient()) {
898 if (!c->group() || c->group()->members().count() == 1) {
900 }
else if (window !=
nullptr && c->group() == window->group()) {
906 if (group !=
nullptr && c->group() == group) {
908 }
else if (window !=
nullptr && window->hasTransient(c,
true)) {
914 if (!show && also_hide) {
915 const auto mainwindows = c->mainWindows();
918 if (mainwindows.isEmpty()) {
921 for (
auto it2 = mainwindows.constBegin(); it2 != mainwindows.constEnd(); ++it2) {
922 if ((*it2)->isSpecialWindow()) {
935 for (
int i = to_show.size() - 1; i >= 0; --i) {
937 to_show.at(i)->setHidden(
false);
940 for (
auto it = to_hide.constBegin(); it != to_hide.constEnd(); ++it) {
941 (*it)->setHidden(
true);
943 updateToolWindowsTimer.stop();
952 updateToolWindowsTimer.start(200);
955void Workspace::slotUpdateToolWindows()
957 updateToolWindows(
true);
960void Workspace::slotReloadConfig()
967 reconfigureTimer.start(200);
976 qCDebug(KWIN_CORE) <<
"Workspace::slotReconfigure()";
977 reconfigureTimer.stop();
981 kwinApp()->config()->reparseConfiguration();
986 updateToolWindows(
true);
989 for (
Window *window : std::as_const(m_windows)) {
990 if (window->supportsWindowRules()) {
991 window->evaluateWindowRules();
992 m_rulebook->discardUsed(window,
false);
999 for (
auto it = m_windows.cbegin(); it != m_windows.cend(); ++it) {
1001 (*it)->checkNoBorder();
1012 updateWindowVisibilityOnDesktopChange(newDesktop);
1016 activateWindowOnNewDesktop(newDesktop);
1020void Workspace::slotCurrentDesktopChanging(VirtualDesktop *currentDesktop, QPointF offset)
1026void Workspace::slotCurrentDesktopChangingCancelled()
1031void Workspace::updateWindowVisibilityOnDesktopChange(VirtualDesktop *newDesktop)
1033 for (
auto it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) {
1034 X11Window *c = qobject_cast<X11Window *>(*it);
1038 if (!c->isOnDesktop(newDesktop) && c != m_moveResizeWindow && c->isOnCurrentActivity()) {
1039 (c)->updateVisibility();
1044 rootInfo()->setCurrentDesktop(VirtualDesktopManager::self()->current());
1047 if (m_moveResizeWindow && !m_moveResizeWindow->
isOnDesktop(newDesktop)) {
1051 for (
int i = stacking_order.size() - 1; i >= 0; --i) {
1052 X11Window *c = qobject_cast<X11Window *>(stacking_order.at(i));
1056 if (c->isOnDesktop(newDesktop) && c->isOnCurrentActivity()) {
1057 c->updateVisibility();
1065void Workspace::activateWindowOnNewDesktop(VirtualDesktop *desktop)
1067 Window *window =
nullptr;
1069 window = findWindowToActivateOnDesktop(desktop);
1075 window = m_activeWindow;
1082 if (window != m_activeWindow) {
1093Window *Workspace::findWindowToActivateOnDesktop(VirtualDesktop *desktop)
1095 if (m_moveResizeWindow !=
nullptr && m_activeWindow == m_moveResizeWindow && m_focusChain->contains(m_activeWindow, desktop) && m_activeWindow->
isShown() && m_activeWindow->
isOnCurrentDesktop()) {
1097 return m_activeWindow;
1103 auto window = *(--it);
1104 if (!window->isClient()) {
1108 if (!(!window->isShade() && window->isShown() && window->isOnDesktop(desktop) && window->isOnCurrentActivity() && window->isOnActiveOutput())) {
1113 if (!window->isDesktop()) {
1120 return m_focusChain->getForActivation(desktop);
1130void Workspace::updateCurrentActivity(
const QString &new_activity)
1132#if KWIN_BUILD_ACTIVITIES
1133 if (!m_activities) {
1145 for (
auto it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) {
1146 X11Window *window = qobject_cast<X11Window *>(*it);
1150 if (!window->isOnActivity(new_activity) && window != m_moveResizeWindow && window->isOnCurrentDesktop()) {
1151 window->updateVisibility();
1164 for (
int i = stacking_order.size() - 1; i >= 0; --i) {
1165 X11Window *window = qobject_cast<X11Window *>(stacking_order.at(i));
1169 if (window->isOnActivity(new_activity)) {
1170 window->updateVisibility();
1181 Window *window =
nullptr;
1186 window = m_activeWindow;
1189 window = m_focusChain->getForActivation(VirtualDesktopManager::self()->currentDesktop());
1193 window =
findDesktop(
true, VirtualDesktopManager::self()->currentDesktop());
1196 if (window != m_activeWindow) {
1212 Output *bestOutput =
nullptr;
1215 for (
Output *output : std::as_const(m_outputs)) {
1216 const QRectF geo = output->
geometry();
1218 const QPointF closestPoint(std::clamp(pos.x(), geo.x(), geo.x() + geo.width() - 1),
1219 std::clamp(pos.y(), geo.y(), geo.y() + geo.height() - 1));
1221 const QPointF ray = closestPoint - pos;
1222 const qreal distance = ray.x() * ray.x() + ray.y() * ray.y();
1223 if (!bestOutput || distance < minDistance) {
1224 minDistance = distance;
1225 bestOutput = output;
1233 QList<Output *> relevantOutputs;
1234 std::copy_if(m_outputs.begin(), m_outputs.end(), std::back_inserter(relevantOutputs), [reference, direction](
Output *output) {
1235 switch (direction) {
1239 return output->geometry().top() <= reference->geometry().bottom() && output->geometry().bottom() >= reference->geometry().top();
1240 case DirectionSouth:
1241 case DirectionNorth:
1243 return output->geometry().left() <= reference->geometry().right() && output->geometry().right() >= reference->geometry().left();
1250 std::sort(relevantOutputs.begin(), relevantOutputs.end(), [direction](
const Output *o1,
const Output *o2) {
1251 switch (direction) {
1255 return o1->geometry().center().x() < o2->geometry().center().x();
1256 case DirectionSouth:
1257 case DirectionNorth:
1259 return o1->geometry().center().y() < o2->geometry().center().y();
1264 return o1->geometry().y() + o1->geometry().height() <= o2->geometry().top() || (o1->geometry().top() < o2->geometry().y() + o2->geometry().height() && o1->geometry().left() < o2->geometry().left());
1268 const int index = relevantOutputs.indexOf(reference);
1269 Q_ASSERT(index != -1);
1270 switch (direction) {
1272 case DirectionSouth:
1275 return relevantOutputs[wrapAround ? (index + 1) % relevantOutputs.count() : std::min(index + 1, (
int)relevantOutputs.count() - 1)];
1277 case DirectionNorth:
1280 return relevantOutputs[wrapAround ? (index + relevantOutputs.count() - 1) % relevantOutputs.count() : std::max(index - 1, 0)];
1286void Workspace::slotOutputBackendOutputsQueried()
1289 updateOutputConfiguration();
1294void Workspace::updateOutputs(
const QList<Output *> &outputOrder)
1296 const auto availableOutputs = kwinApp()->outputBackend()->outputs();
1297 const auto oldOutputs = m_outputs;
1300 for (Output *output : availableOutputs) {
1301 if (!output->isNonDesktop() && output->isEnabled()) {
1302 m_outputs.append(output);
1307 if (m_outputs.isEmpty()) {
1308 if (!m_placeholderOutput) {
1309 m_placeholderOutput =
new PlaceholderOutput(QSize(1920, 1080), 1);
1310 m_placeholderFilter = std::make_unique<PlaceholderInputEventFilter>();
1313 m_outputs.append(m_placeholderOutput);
1315 if (m_placeholderOutput) {
1316 m_placeholderOutput->unref();
1317 m_placeholderOutput =
nullptr;
1318 m_placeholderFilter.reset();
1322 if (!m_activeOutput || !m_outputs.contains(m_activeOutput)) {
1323 setActiveOutput(m_outputs[0]);
1325 if (!m_outputs.contains(m_activeCursorOutput)) {
1326 m_activeCursorOutput =
nullptr;
1329 if (!outputOrder.empty()) {
1330 setOutputOrder(outputOrder);
1333 for (Output *output : std::as_const(m_outputs)) {
1334 if (output->isEnabled() && !m_outputOrder.contains(output)) {
1335 m_outputOrder.push_back(output);
1338 m_outputOrder.erase(std::remove_if(m_outputOrder.begin(), m_outputOrder.end(), [
this](Output *output) {
1339 return !m_outputs.contains(output);
1341 m_outputOrder.end());
1344 const QSet<Output *> oldOutputsSet(oldOutputs.constBegin(), oldOutputs.constEnd());
1345 const QSet<Output *> outputsSet(m_outputs.constBegin(), m_outputs.constEnd());
1347 const auto added = outputsSet - oldOutputsSet;
1348 for (Output *output : added) {
1350 m_tileManagers[output] = std::make_unique<TileManager>(output);
1351 connect(output, &Output::aboutToTurnOff,
this, &Workspace::createDpmsFilter);
1352 connect(output, &Output::wakeUp,
this, &Workspace::maybeDestroyDpmsFilter);
1353 if (output->dpmsMode() != Output::DpmsMode::On) {
1356 Q_EMIT outputAdded(output);
1358 maybeDestroyDpmsFilter();
1360 const auto removed = oldOutputsSet - outputsSet;
1361 for (Output *output : removed) {
1362 Q_EMIT outputRemoved(output);
1363 auto tileManager = std::move(m_tileManagers[output]);
1364 m_tileManagers.erase(output);
1367 tileManager->rootTile()->visitDescendants([](
const Tile *child) {
1368 const QList<Window *> windows = child->windows();
1369 for (
Window *window : windows) {
1370 window->setTile(
nullptr);
1375 static constexpr QuickTileMode quickTileModes[] = {
1376 QuickTileFlag::Left,
1377 QuickTileFlag::Right,
1379 QuickTileFlag::Bottom,
1380 QuickTileFlag::Top | QuickTileFlag::Left,
1381 QuickTileFlag::Top | QuickTileFlag::Right,
1382 QuickTileFlag::Bottom | QuickTileFlag::Left,
1383 QuickTileFlag::Bottom | QuickTileFlag::Right,
1386 for (
const QuickTileMode &quickTileMode : quickTileModes) {
1387 Tile *quickTile = tileManager->quickTile(quickTileMode);
1388 const QList<Window *> windows = quickTile->windows();
1389 if (windows.isEmpty()) {
1393 Output *bestOutput = outputAt(output->geometry().center());
1394 Tile *bestTile = m_tileManagers[bestOutput]->quickTile(quickTileMode);
1396 for (
Window *window : windows) {
1397 window->setTile(bestTile);
1404 for (Output *output : removed) {
1408 Q_EMIT outputsChanged();
1411void Workspace::createDpmsFilter()
1413 if (!m_dpmsFilter) {
1414 m_dpmsFilter = std::make_unique<DpmsInputEventFilter>();
1419void Workspace::maybeDestroyDpmsFilter()
1421 const bool allOn = std::all_of(m_outputs.begin(), m_outputs.end(), [](Output *output) {
1422 return output->dpmsMode() == Output::DpmsMode::On && !output->isPlaceholder();
1425 m_dpmsFilter.reset();
1429void Workspace::slotDesktopAdded(VirtualDesktop *desktop)
1431 m_focusChain->addDesktop(desktop);
1432 m_placement->reinitCascading();
1436void Workspace::slotDesktopRemoved(VirtualDesktop *desktop)
1438 for (
auto it = m_windows.constBegin(); it != m_windows.constEnd(); ++it) {
1439 if (!(*it)->desktops().contains(desktop)) {
1442 if ((*it)->desktops().count() > 1) {
1443 (*it)->leaveDesktop(desktop);
1445 const uint desktopId = std::min(desktop->x11DesktopNumber(), VirtualDesktopManager::self()->count());
1446 sendWindowToDesktops(*it, {VirtualDesktopManager::self()->desktopForX11Id(desktopId)},
true);
1450 for (
auto it = deleted.constBegin(); it != deleted.constEnd(); ++it) {
1451 if ((*it)->desktops().contains(desktop)) {
1452 (*it)->leaveDesktop(desktop);
1457 m_placement->reinitCascading();
1458 m_focusChain->removeDesktop(desktop);
1461void Workspace::selectWmInputEventMask()
1463 uint32_t presentMask = 0;
1464 Xcb::WindowAttributes attr(kwinApp()->x11RootWindow());
1465 if (!attr.isNull()) {
1466 presentMask = attr->your_event_mask;
1469 const uint32_t wmMask = XCB_EVENT_MASK_KEY_PRESS
1470 | XCB_EVENT_MASK_PROPERTY_CHANGE
1471 | XCB_EVENT_MASK_COLOR_MAP_CHANGE
1472 | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
1473 | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
1474 | XCB_EVENT_MASK_FOCUS_CHANGE
1475 | XCB_EVENT_MASK_EXPOSURE;
1477 Xcb::selectInput(kwinApp()->x11RootWindow(), presentMask | wmMask);
1485void Workspace::sendWindowToDesktops(
Window *window,
const QList<VirtualDesktop *> &desktops,
bool dont_activate)
1487 const QList<VirtualDesktop *> oldDesktops = window->
desktops();
1490 if (window->
desktops() != desktops) {
1497 requestFocus(window);
1499 restackWindowUnderActive(window);
1502 raiseWindow(window);
1507 auto transients_stacking_order = ensureStackingOrder(window->
transients());
1508 for (
auto it = transients_stacking_order.constBegin(); it != transients_stacking_order.constEnd(); ++it) {
1509 sendWindowToDesktops(*it, window->
desktops(), dont_activate);
1522void Workspace::delayFocus()
1524 requestFocus(m_delayFocusWindow);
1528void Workspace::requestDelayFocus(
Window *window)
1530 m_delayFocusWindow = window;
1531 delete delayFocusTimer;
1532 delayFocusTimer =
new QTimer(
this);
1533 connect(delayFocusTimer, &QTimer::timeout,
this, &Workspace::delayFocus);
1534 delayFocusTimer->setSingleShot(
true);
1538void Workspace::cancelDelayFocus()
1540 delete delayFocusTimer;
1541 delayFocusTimer =
nullptr;
1542 m_delayFocusWindow =
nullptr;
1545bool Workspace::checkStartupNotification(xcb_window_t w, KStartupInfoId &
id, KStartupInfoData &data)
1547 return m_startup->checkStartup(w,
id, data) == KStartupInfo::Match;
1554void Workspace::focusToNull()
1557 should_get_focus.clear();
1558 m_nullFocus->focus();
1562bool Workspace::breaksShowingDesktop(
Window *window)
const
1567void Workspace::setShowingDesktop(
bool showing,
bool animated)
1569 const bool changed = showing != showing_desktop;
1571 rootInfo()->setShowingDesktop(showing);
1573 showing_desktop = showing;
1575 for (
int i = stacking_order.count() - 1; i > -1; --i) {
1576 auto window = stacking_order.at(i);
1580 if (breaksShowingDesktop(window)) {
1585 if (showing_desktop) {
1586 Window *desktop = findDesktop(
true, VirtualDesktopManager::self()->currentDesktop());
1588 requestFocus(desktop);
1590 }
else if (!showing_desktop && changed) {
1591 const auto window = m_focusChain->getForActivation(VirtualDesktopManager::self()->currentDesktop());
1593 activateWindow(window);
1597 Q_EMIT showingDesktopChanged(showing, animated);
1601void Workspace::disableGlobalShortcutsForClient(
bool disable)
1603 if (m_globalShortcutsDisabledForWindow == disable) {
1606 QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral(
"org.kde.kglobalaccel"),
1607 QStringLiteral(
"/kglobalaccel"),
1608 QStringLiteral(
"org.kde.KGlobalAccel"),
1609 QStringLiteral(
"blockGlobalShortcuts"));
1610 message.setArguments(QList<QVariant>() << disable);
1611 QDBusConnection::sessionBus().asyncCall(message);
1613 m_globalShortcutsDisabledForWindow = disable;
1615 for (
auto it = m_windows.constBegin(); it != m_windows.constEnd(); ++it) {
1616 (*it)->updateMouseGrab();
1620QString Workspace::supportInformation()
const
1623 const QString yes = QStringLiteral(
"yes\n");
1624 const QString no = QStringLiteral(
"no\n");
1626 support.append(ki18nc(
"Introductory text shown in the support information.",
1627 "KWin Support Information:\n"
1628 "The following information should be used when requesting support on e.g. https://discuss.kde.org.\n"
1629 "It provides information about the currently running instance, which options are used,\n"
1630 "what OpenGL driver and which effects are running.\n"
1631 "Please post the information provided underneath this introductory text to a paste bin service\n"
1632 "like https://paste.kde.org instead of pasting into support threads.\n")
1634 support.append(QStringLiteral(
"\n==========================\n\n"));
1638 support.append(QStringLiteral(
"Version\n"));
1639 support.append(QStringLiteral(
"=======\n"));
1640 support.append(QStringLiteral(
"KWin version: "));
1641 support.append(KWIN_VERSION_STRING);
1642 support.append(QStringLiteral(
"\n"));
1643 support.append(QStringLiteral(
"Qt Version: "));
1644 support.append(QString::fromUtf8(qVersion()));
1645 support.append(QStringLiteral(
"\n"));
1646 support.append(QStringLiteral(
"Qt compile version: %1\n").arg(QStringLiteral(QT_VERSION_STR)));
1647 support.append(QStringLiteral(
"XCB compile version: %1\n\n").arg(XCB_VERSION_STRING));
1648 support.append(QStringLiteral(
"Operation Mode: "));
1649 switch (kwinApp()->operationMode()) {
1650 case Application::OperationModeX11:
1651 support.append(QStringLiteral(
"X11 only"));
1653 case Application::OperationModeWaylandOnly:
1654 support.append(QStringLiteral(
"Wayland Only"));
1656 case Application::OperationModeXwayland:
1657 support.append(QStringLiteral(
"Xwayland"));
1660 support.append(QStringLiteral(
"\n\n"));
1662 support.append(QStringLiteral(
"Build Options\n"));
1663 support.append(QStringLiteral(
"=============\n"));
1665 support.append(QStringLiteral(
"KWIN_BUILD_DECORATIONS: "));
1666 support.append(KWIN_BUILD_DECORATIONS ? yes : no);
1667 support.append(QStringLiteral(
"KWIN_BUILD_TABBOX: "));
1668 support.append(KWIN_BUILD_TABBOX ? yes : no);
1669 support.append(QStringLiteral(
"KWIN_BUILD_ACTIVITIES: "));
1670 support.append(KWIN_BUILD_ACTIVITIES ? yes : no);
1671 support.append(QStringLiteral(
"HAVE_X11_XCB: "));
1672 support.append(HAVE_X11_XCB ? yes : no);
1673 support.append(QStringLiteral(
"HAVE_GLX: "));
1674 support.append(HAVE_GLX ? yes : no);
1675 support.append(QStringLiteral(
"\n"));
1677 if (
auto c = kwinApp()->x11Connection()) {
1678 support.append(QStringLiteral(
"X11\n"));
1679 support.append(QStringLiteral(
"===\n"));
1680 auto x11setup = xcb_get_setup(c);
1681 support.append(QStringLiteral(
"Vendor: %1\n").arg(QString::fromUtf8(QByteArray::fromRawData(xcb_setup_vendor(x11setup), xcb_setup_vendor_length(x11setup)))));
1682 support.append(QStringLiteral(
"Vendor Release: %1\n").arg(x11setup->release_number));
1683 support.append(QStringLiteral(
"Protocol Version/Revision: %1/%2\n").arg(x11setup->protocol_major_version).arg(x11setup->protocol_minor_version));
1684 const auto extensions = Xcb::Extensions::self()->extensions();
1685 for (
const auto &e : extensions) {
1686 support.append(QStringLiteral(
"%1: %2; Version: 0x%3\n")
1687 .arg(QString::fromUtf8(e.name), e.present ? yes.trimmed() : no.trimmed(), QString::number(e.version, 16)));
1689 support.append(QStringLiteral(
"\n"));
1692 if (m_decorationBridge) {
1693 support.append(QStringLiteral(
"Decoration\n"));
1694 support.append(QStringLiteral(
"==========\n"));
1695 support.append(m_decorationBridge->supportInformation());
1696 support.append(QStringLiteral(
"\n"));
1698 support.append(QStringLiteral(
"Output backend\n"));
1699 support.append(QStringLiteral(
"==============\n"));
1700 support.append(kwinApp()->outputBackend()->supportInformation());
1701 support.append(QStringLiteral(
"\n"));
1703 const Cursor *cursor = Cursors::self()->mouse();
1704 support.append(QLatin1String(
"Cursor\n"));
1705 support.append(QLatin1String(
"======\n"));
1706 support.append(QLatin1String(
"themeName: ") + cursor->
themeName() + QLatin1Char(
'\n'));
1707 support.append(QLatin1String(
"themeSize: ") + QString::number(cursor->
themeSize()) + QLatin1Char(
'\n'));
1708 support.append(QLatin1Char(
'\n'));
1710 support.append(QStringLiteral(
"Options\n"));
1711 support.append(QStringLiteral(
"=======\n"));
1712 const QMetaObject *metaOptions =
options->metaObject();
1713 auto printProperty = [](
const QVariant &variant) {
1714 if (variant.type() == QVariant::Size) {
1715 const QSize &s = variant.toSize();
1716 return QStringLiteral(
"%1x%2").arg(s.width()).arg(s.height());
1718 if (QLatin1String(variant.typeName()) == QLatin1String(
"KWin::OpenGLPlatformInterface") || QLatin1String(variant.typeName()) == QLatin1String(
"KWin::Options::WindowOperation")) {
1719 return QString::number(variant.toInt());
1721 return variant.toString();
1723 for (
int i = 0; i < metaOptions->propertyCount(); ++i) {
1724 const QMetaProperty
property = metaOptions->property(i);
1725 if (QLatin1String(property.name()) == QLatin1String(
"objectName")) {
1728 support.append(QStringLiteral(
"%1: %2\n").arg(property.name(), printProperty(
options->property(property.name()))));
1730 support.append(QStringLiteral(
"\nScreen Edges\n"));
1731 support.append(QStringLiteral(
"============\n"));
1732 const QMetaObject *metaScreenEdges = m_screenEdges->metaObject();
1733 for (
int i = 0; i < metaScreenEdges->propertyCount(); ++i) {
1734 const QMetaProperty
property = metaScreenEdges->property(i);
1735 if (QLatin1String(property.name()) == QLatin1String(
"objectName")) {
1738 support.append(QStringLiteral(
"%1: %2\n").arg(property.name(), printProperty(m_screenEdges->property(property.name()))));
1740 support.append(QStringLiteral(
"\nScreens\n"));
1741 support.append(QStringLiteral(
"=======\n"));
1742 support.append(QStringLiteral(
"Active screen follows mouse: "));
1744 support.append(QStringLiteral(
" yes\n"));
1746 support.append(QStringLiteral(
" no\n"));
1748 const QList<Output *> outputs = kwinApp()->outputBackend()->outputs();
1749 support.append(QStringLiteral(
"Number of Screens: %1\n\n").arg(outputs.count()));
1750 for (
int i = 0; i < outputs.count(); ++i) {
1751 const auto output = outputs[i];
1752 const QRect geo = outputs[i]->geometry();
1753 support.append(QStringLiteral(
"Screen %1:\n").arg(i));
1754 support.append(QStringLiteral(
"---------\n"));
1755 support.append(QStringLiteral(
"Name: %1\n").arg(output->name()));
1756 support.append(QStringLiteral(
"Enabled: %1\n").arg(output->isEnabled()));
1757 if (output->isEnabled()) {
1758 support.append(QStringLiteral(
"Geometry: %1,%2,%3x%4\n")
1762 .arg(geo.height()));
1763 support.append(QStringLiteral(
"Scale: %1\n").arg(output->scale()));
1764 support.append(QStringLiteral(
"Refresh Rate: %1\n").arg(output->refreshRate()));
1765 QString vrr = QStringLiteral(
"incapable");
1766 if (output->capabilities() & Output::Capability::Vrr) {
1767 switch (output->vrrPolicy()) {
1768 case VrrPolicy::Never:
1769 vrr = QStringLiteral(
"never");
1771 case VrrPolicy::Always:
1772 vrr = QStringLiteral(
"always");
1774 case VrrPolicy::Automatic:
1775 vrr = QStringLiteral(
"automatic");
1779 support.append(QStringLiteral(
"Adaptive Sync: %1\n").arg(vrr));
1782 support.append(QStringLiteral(
"\nCompositing\n"));
1783 support.append(QStringLiteral(
"===========\n"));
1785 support.append(QStringLiteral(
"Compositing is active\n"));
1788 GLPlatform *platform = GLPlatform::instance();
1789 if (platform->
isGLES()) {
1790 support.append(QStringLiteral(
"Compositing Type: OpenGL ES 2.0\n"));
1792 support.append(QStringLiteral(
"Compositing Type: OpenGL\n"));
1794 support.append(QStringLiteral(
"OpenGL vendor string: ") + QString::fromUtf8(platform->
glVendorString()) + QStringLiteral(
"\n"));
1795 support.append(QStringLiteral(
"OpenGL renderer string: ") + QString::fromUtf8(platform->
glRendererString()) + QStringLiteral(
"\n"));
1796 support.append(QStringLiteral(
"OpenGL version string: ") + QString::fromUtf8(platform->
glVersionString()) + QStringLiteral(
"\n"));
1797 support.append(QStringLiteral(
"OpenGL platform interface: "));
1800 support.append(QStringLiteral(
"GLX"));
1803 support.append(QStringLiteral(
"EGL"));
1806 support.append(QStringLiteral(
"UNKNOWN"));
1808 support.append(QStringLiteral(
"\n"));
1810 support.append(QStringLiteral(
"OpenGL shading language version string: ") + QString::fromUtf8(platform->
glShadingLanguageVersionString()) + QStringLiteral(
"\n"));
1812 support.append(QStringLiteral(
"Driver: ") + GLPlatform::driverToString(platform->
driver()) + QStringLiteral(
"\n"));
1814 support.append(QStringLiteral(
"Driver version: ") + platform->
driverVersion().
toString() + QStringLiteral(
"\n"));
1817 support.append(QStringLiteral(
"GPU class: ") + GLPlatform::chipClassToString(platform->
chipClass()) + QStringLiteral(
"\n"));
1819 support.append(QStringLiteral(
"OpenGL version: ") + platform->
glVersion().
toString() + QStringLiteral(
"\n"));
1821 support.append(QStringLiteral(
"GLSL version: ") + platform->
glslVersion().
toString() + QStringLiteral(
"\n"));
1824 support.append(QStringLiteral(
"Mesa version: ") + platform->
mesaVersion().
toString() + QStringLiteral(
"\n"));
1826 if (
auto xVersion = Xcb::xServerVersion(); xVersion.isValid()) {
1827 support.append(QStringLiteral(
"X server version: ") + xVersion.toString() + QStringLiteral(
"\n"));
1829 if (
auto kernelVersion = linuxKernelVersion(); kernelVersion.isValid()) {
1830 support.append(QStringLiteral(
"Linux kernel version: ") + kernelVersion.toString() + QStringLiteral(
"\n"));
1833 support.append(QStringLiteral(
"Direct rendering: "));
1834 support.append(QStringLiteral(
"Requires strict binding: "));
1836 support.append(QStringLiteral(
"yes\n"));
1838 support.append(QStringLiteral(
"no\n"));
1840 support.append(QStringLiteral(
"Virtual Machine: "));
1842 support.append(QStringLiteral(
" yes\n"));
1844 support.append(QStringLiteral(
" no\n"));
1847 support.append(QStringLiteral(
"OpenGL 2 Shaders are used\n"));
1851 support.append(
"Compositing Type: QPainter\n");
1855 support.append(QStringLiteral(
"Something is really broken, neither OpenGL nor QPainter is used"));
1857 support.append(QStringLiteral(
"\nLoaded Effects:\n"));
1858 support.append(QStringLiteral(
"---------------\n"));
1860 for (
const QString &effect : loadedEffects) {
1861 support.append(effect + QStringLiteral(
"\n"));
1863 support.append(QStringLiteral(
"\nCurrently Active Effects:\n"));
1864 support.append(QStringLiteral(
"-------------------------\n"));
1866 for (
const QString &effect : activeEffects) {
1867 support.append(effect + QStringLiteral(
"\n"));
1869 support.append(QStringLiteral(
"\nEffect Settings:\n"));
1870 support.append(QStringLiteral(
"----------------\n"));
1871 for (
const QString &effect : loadedEffects) {
1873 support.append(QStringLiteral(
"\n"));
1875 support.append(QLatin1String(
"\nLoaded Plugins:\n"));
1876 support.append(QLatin1String(
"---------------\n"));
1877 QStringList loadedPlugins = kwinApp()->pluginManager()->loadedPlugins();
1878 loadedPlugins.sort();
1879 for (
const QString &plugin : std::as_const(loadedPlugins)) {
1880 support.append(plugin + QLatin1Char(
'\n'));
1882 support.append(QLatin1String(
"\nAvailable Plugins:\n"));
1883 support.append(QLatin1String(
"------------------\n"));
1884 QStringList availablePlugins = kwinApp()->pluginManager()->availablePlugins();
1885 availablePlugins.sort();
1886 for (
const QString &plugin : std::as_const(availablePlugins)) {
1887 support.append(plugin + QLatin1Char(
'\n'));
1890 support.append(QStringLiteral(
"Compositing is not active\n"));
1895void Workspace::forEachClient(std::function<
void(
X11Window *)> func)
1897 for (
Window *window : std::as_const(m_windows)) {
1898 X11Window *x11Window = qobject_cast<X11Window *>(window);
1907 for (
Window *window : std::as_const(m_windows)) {
1908 X11Window *x11Window = qobject_cast<X11Window *>(window);
1909 if (x11Window && !x11Window->
isUnmanaged() && func(x11Window)) {
1918 for (
Window *window : m_windows) {
1919 X11Window *x11Window = qobject_cast<X11Window *>(window);
1920 if (x11Window && x11Window->
isUnmanaged() && func(x11Window)) {
1929 return findUnmanaged([w](
const X11Window *u) {
1936 switch (predicate) {
1937 case Predicate::WindowMatch:
1938 return findClient([w](
const X11Window *c) {
1941 case Predicate::WrapperIdMatch:
1942 return findClient([w](
const X11Window *c) {
1945 case Predicate::FrameIdMatch:
1946 return findClient([w](
const X11Window *c) {
1949 case Predicate::InputIdMatch:
1950 return findClient([w](
const X11Window *c) {
1957Window *Workspace::findWindow(std::function<
bool(
const Window *)> func)
const
1959 return Window::findInList(m_windows, func);
1962Window *Workspace::findWindow(
const QUuid &internalId)
const
1964 return findWindow([internalId](
const KWin::Window *l) ->
bool {
1969void Workspace::forEachWindow(std::function<
void(
Window *)> func)
1971 std::for_each(m_windows.constBegin(), m_windows.constEnd(), func);
1976 return findWindow([&c](
const Window *test) {
1982Window *Workspace::findInternal(QWindow *w)
const
1987 if (kwinApp()->operationMode() == Application::OperationModeX11) {
1988 return findUnmanaged(w->winId());
1990 for (
Window *window : m_windows) {
1991 if (
InternalWindow *internal = qobject_cast<InternalWindow *>(window)) {
1992 if (internal->handle() == w) {
2000void Workspace::setWasUserInteraction()
2002 if (was_user_interaction) {
2005 was_user_interaction =
true;
2007 QTimer::singleShot(0,
this,
2009 m_wasUserInteractionFilter.reset();
2013void Workspace::updateTabbox()
2015#if KWIN_BUILD_TABBOX
2018 m_tabbox->reset(
true);
2024 Q_ASSERT(!m_windows.contains(window));
2025 m_windows.append(window);
2028 setupWindowConnections(window);
2033 m_placement->place(window, area);
2036 updateStackingOrder(
true);
2037 Q_EMIT windowAdded(window);
2042 m_windows.removeOne(window);
2044 updateStackingOrder();
2045 Q_EMIT windowRemoved(window);
2048void Workspace::setInitialDesktop(
int desktop)
2050 m_initialDesktop = desktop;
2053Group *Workspace::findGroup(xcb_window_t leader)
const
2055 Q_ASSERT(leader != XCB_WINDOW_NONE);
2056 for (
auto it = groups.constBegin(); it != groups.constEnd(); ++it) {
2057 if ((*it)->leader() == leader) {
2068 Group *ret =
nullptr;
2069 for (
auto it = m_windows.constBegin(); it != m_windows.constEnd(); ++it) {
2070 X11Window *candidate = qobject_cast<X11Window *>(*it);
2071 if (!candidate || candidate == window) {
2075 if (ret ==
nullptr || ret == candidate->
group()) {
2076 ret = candidate->
group();
2082 QList<X11Window *> old_group = candidate->
group()->
members();
2084 for (
int pos = 0; pos < old_group.count(); ++pos) {
2086 if (tmp != window) {
2096void Workspace::updateMinimizedOfTransients(
Window *window)
2100 for (
auto it = window->
transients().constBegin(); it != window->
transients().constEnd(); ++it) {
2101 if ((*it)->isModal()) {
2105 if (!(*it)->isMinimized()) {
2106 (*it)->setMinimized(
true);
2107 updateMinimizedOfTransients((*it));
2112 for (
Window *
main : std::as_const(windows)) {
2113 main->setMinimized(
true);
2118 for (
auto it = window->
transients().constBegin(); it != window->
transients().constEnd(); ++it) {
2119 if ((*it)->isMinimized()) {
2120 (*it)->setMinimized(
false);
2121 updateMinimizedOfTransients((*it));
2126 for (
Window *
main : std::as_const(windows)) {
2127 main->setMinimized(
false);
2136void Workspace::updateOnAllDesktopsOfTransients(
Window *window)
2138 for (
auto it = window->
transients().constBegin(); it != window->
transients().constEnd(); ++it) {
2146void Workspace::checkTransients(xcb_window_t w)
2148 for (
auto it = m_windows.constBegin(); it != m_windows.constEnd(); ++it) {
2149 if (
X11Window *x11Window = qobject_cast<X11Window *>(*it)) {
2150 x11Window->checkTransient(w);
2158void Workspace::desktopResized()
2160 m_placementTracker->inhibit();
2162 const QRect oldGeometry = m_geometry;
2163 m_geometry = QRect();
2164 for (
const Output *output : std::as_const(m_outputs)) {
2165 m_geometry = m_geometry.united(output->geometry());
2169 NETSize desktop_geometry;
2170 desktop_geometry.width = Xcb::toXNative(m_geometry.width());
2171 desktop_geometry.height = Xcb::toXNative(m_geometry.height());
2172 rootInfo()->setDesktopGeometry(desktop_geometry);
2177 const auto stack = stackingOrder();
2178 for (
Window *window : stack) {
2184 const auto oldCursorOutput = std::find_if(m_oldScreenGeometries.cbegin(), m_oldScreenGeometries.cend(), [](
const auto &geometry) {
2185 return exclusiveContains(geometry, Cursors::self()->mouse()->pos());
2187 if (oldCursorOutput != m_oldScreenGeometries.cend()) {
2188 const Output *cursorOutput = oldCursorOutput.key();
2189 if (std::find(m_outputs.cbegin(), m_outputs.cend(), cursorOutput) != m_outputs.cend()) {
2190 const QRect oldGeometry = oldCursorOutput.value();
2191 const QRect newGeometry = cursorOutput->geometry();
2192 const QPointF relativePosition = Cursors::self()->mouse()->pos() - oldGeometry.topLeft();
2193 const QPointF newRelativePosition(newGeometry.width() * relativePosition.x() /
float(oldGeometry.width()), newGeometry.height() * relativePosition.y() /
float(oldGeometry.height()));
2194 Cursors::self()->mouse()->setPos(newGeometry.topLeft() + newRelativePosition);
2198 saveOldScreenSizes();
2201 m_screenEdges->recreateEdges();
2203 m_placementTracker->uninhibit();
2204 m_placementTracker->restore(getPlacementTrackerHash());
2205 if (m_geometry != oldGeometry) {
2206 Q_EMIT geometryChanged();
2210void Workspace::saveOldScreenSizes()
2212 m_oldScreenGeometries.clear();
2213 for (
const Output *output : std::as_const(m_outputs)) {
2214 m_oldScreenGeometries.insert(output, output->geometry());
2222static bool hasOffscreenXineramaStrut(
Window *window)
2224 if (qobject_cast<X11Window *>(window)) {
2227 region += window->strutRect(StrutAreaTop);
2228 region += window->strutRect(StrutAreaRight);
2229 region += window->strutRect(StrutAreaBottom);
2230 region += window->strutRect(StrutAreaLeft);
2234 for (
const Output *output :
outputs) {
2235 region -= output->geometry();
2239 return !region.isEmpty();
2245QRectF Workspace::adjustClientArea(
Window *window,
const QRectF &area)
const
2247 QRectF adjustedArea = area;
2254 QRectF screenArea = clientArea(
ScreenArea, window);
2255 if (qobject_cast<X11Window *>(window)) {
2259 if (area == QRect(QPoint(0, 0), m_geometry.size())) {
2260 if (strutLeft.left() < screenArea.left()) {
2261 strutLeft = QRect();
2263 if (strutRight.right() > screenArea.right()) {
2264 strutRight = QRect();
2266 if (strutTop.top() < screenArea.top()) {
2269 if (strutBottom.bottom() < screenArea.bottom()) {
2270 strutBottom = QRect();
2278 strutLeft.setLeft(std::max(strutLeft.left(), screenArea.left()));
2279 strutRight.setRight(std::min(strutRight.right(), screenArea.right()));
2280 strutTop.setTop(std::max(strutTop.top(), screenArea.top()));
2281 strutBottom.setBottom(std::min(strutBottom.bottom(), screenArea.bottom()));
2283 if (strutLeft.intersects(area)) {
2284 adjustedArea.setLeft(strutLeft.right());
2286 if (strutRight.intersects(area)) {
2287 adjustedArea.setRight(strutRight.left());
2289 if (strutTop.intersects(area)) {
2290 adjustedArea.setTop(strutTop.bottom());
2292 if (strutBottom.intersects(area)) {
2293 adjustedArea.setBottom(strutBottom.top());
2296 return adjustedArea;
2308void Workspace::updateClientArea()
2310 const QList<VirtualDesktop *> desktops = VirtualDesktopManager::self()->desktops();
2312 QHash<const VirtualDesktop *, QRectF> workAreas;
2313 QHash<const VirtualDesktop *, StrutRects> restrictedAreas;
2314 QHash<const VirtualDesktop *, QHash<const Output *, QRectF>> screenAreas;
2317 workAreas[desktop] = m_geometry;
2319 for (
const Output *output : std::as_const(m_outputs)) {
2320 screenAreas[desktop][output] = output->geometryF();
2324 for (
Window *window : std::as_const(m_windows)) {
2325 if (!window->hasStrut()) {
2328 QRectF r = adjustClientArea(window, m_geometry);
2337 for (
const Output *output : std::as_const(m_outputs)) {
2338 if (!r.intersects(output->geometry())) {
2339 qCDebug(KWIN_CORE) <<
"Adjusted client area would exclude a complete screen, ignore";
2344 StrutRects strutRegion = window->strutRects();
2345 const QRect clientsScreenRect = window->output()->geometry();
2346 for (
int i = strutRegion.size() - 1; i >= 0; --i) {
2347 const StrutRect clipped =
StrutRect(strutRegion[i].intersected(clientsScreenRect), strutRegion[i].area());
2348 if (clipped.isEmpty()) {
2349 strutRegion.removeAt(i);
2351 strutRegion[i] = clipped;
2361 bool hasOffscreenStrut = hasOffscreenXineramaStrut(window);
2363 const auto vds = window->isOnAllDesktops() ? desktops : window->desktops();
2365 if (!hasOffscreenStrut) {
2368 restrictedAreas[vd] += strutRegion;
2369 for (
Output *output : std::as_const(m_outputs)) {
2370 const auto geo = screenAreas[vd][output].intersected(adjustClientArea(window, output->geometryF()));
2372 if (!geo.isEmpty()) {
2373 screenAreas[vd][output] = geo;
2379 if (m_workAreas != workAreas || m_restrictedAreas != restrictedAreas || m_screenAreas != screenAreas) {
2380 m_workAreas = workAreas;
2381 m_screenAreas = screenAreas;
2383 m_inUpdateClientArea =
true;
2384 m_oldRestrictedAreas = m_restrictedAreas;
2385 m_restrictedAreas = restrictedAreas;
2389 const QRectF &workArea = m_workAreas[desktop];
2390 NETRect r(Xcb::toXNative(workArea));
2391 rootInfo()->setWorkArea(desktop->x11DesktopNumber(), r);
2395 for (
auto it = m_windows.constBegin(); it != m_windows.constEnd(); ++it) {
2396 if ((*it)->isClient()) {
2397 (*it)->checkWorkspacePosition();
2401 m_oldRestrictedAreas.clear();
2402 m_inUpdateClientArea =
false;
2416 if (
auto desktopIt = m_screenAreas.constFind(desktop); desktopIt != m_screenAreas.constEnd()) {
2417 if (
auto outputIt = desktopIt->constFind(output); outputIt != desktopIt->constEnd()) {
2428 return m_workAreas.value(desktop, m_geometry);
2438 return clientArea(opt, window, window->
output());
2445 desktop = VirtualDesktopManager::self()->currentDesktop();
2447 desktop = window->
desktops().constLast();
2449 return clientArea(opt, output, desktop);
2454 return clientArea(opt, window, outputAt(pos));
2457QRect Workspace::geometry()
const
2464 const StrutRects strut = m_restrictedAreas.value(desktop);
2470 ret.reserve(strut.size());
2472 if (rect.area() & areas) {
2479bool Workspace::inUpdateClientArea()
const
2481 return m_inUpdateClientArea;
2486 const StrutRects strut = m_oldRestrictedAreas.value(desktop);
2492 ret.reserve(strut.size());
2494 if (rect.area() & areas) {
2501QHash<const Output *, QRect> Workspace::previousScreenSizes()
const
2503 return m_oldScreenGeometries;
2506Output *Workspace::xineramaIndexToOutput(
int index)
const
2508 xcb_connection_t *connection = kwinApp()->x11Connection();
2514 if (!active || !active->state) {
2523 const int infoCount = xcb_xinerama_query_screens_screen_info_length(screens.get());
2524 if (index >= infoCount) {
2528 const xcb_xinerama_screen_info_t *infos = xcb_xinerama_query_screens_screen_info(screens.get());
2529 const QRect needle(infos[index].x_org, infos[index].y_org, infos[index].width, infos[index].height);
2531 for (
Output *output : std::as_const(m_outputs)) {
2532 if (Xcb::toXNative(output->geometryF()) == needle) {
2540void Workspace::setOutputOrder(
const QList<Output *> &order)
2542 if (m_outputOrder != order) {
2543 m_outputOrder = order;
2544 Q_EMIT outputOrderChanged();
2548QList<Output *> Workspace::outputOrder()
const
2550 return m_outputOrder;
2556 if (m_activeCursorOutput) {
2557 return m_activeCursorOutput;
2559 return outputAt(Cursors::self()->mouse()->pos());
2563 if (m_activeWindow && !m_activeWindow->isOnOutput(m_activeOutput)) {
2564 return m_activeWindow->output();
2567 return m_activeOutput;
2570void Workspace::setActiveOutput(
Output *output)
2572 m_activeOutput = output;
2575void Workspace::setActiveOutput(
const QPointF &pos)
2577 setActiveOutput(outputAt(pos));
2580void Workspace::setActiveCursorOutput(
Output *output)
2582 m_activeCursorOutput = output;
2585void Workspace::setActiveCursorOutput(
const QPointF &pos)
2587 setActiveCursorOutput(outputAt(pos));
2599QPointF Workspace::adjustWindowPosition(
Window *window, QPointF pos,
bool unrestricted,
double snapAdjust)
2609 borderSnapZone.setWidth(std::max(borderSnapZone.width() + 2, maxRect.width() / 16));
2613 borderSnapZone.setHeight(std::max(borderSnapZone.height() + 2, maxRect.height() / 16));
2620 const Output *output = outputAt(pos + window->
rect().center());
2621 if (maxRect.isNull()) {
2624 const int xmin = maxRect.left();
2625 const int xmax = maxRect.right();
2626 const int ymin = maxRect.top();
2627 const int ymax = maxRect.bottom();
2629 const int cx(pos.x());
2630 const int cy(pos.y());
2631 const int cw(window->
width());
2632 const int ch(window->
height());
2633 const int rx(cx + cw);
2634 const int ry(cy + ch);
2640 int lx, ly, lrx, lry;
2643 const int borderXSnapZone = borderSnapZone.width() * snapAdjust;
2644 const int borderYSnapZone = borderSnapZone.height() * snapAdjust;
2645 if (borderXSnapZone > 0 || borderYSnapZone > 0) {
2646 if ((sOWO ? (cx < xmin) :
true) && (std::abs(xmin - cx) < borderXSnapZone)) {
2650 if ((sOWO ? (rx > xmax) :
true) && (std::abs(rx - xmax) < borderXSnapZone) && (std::abs(xmax - rx) < deltaX)) {
2655 if ((sOWO ? (cy < ymin) :
true) && (std::abs(ymin - cy) < borderYSnapZone)) {
2659 if ((sOWO ? (ry > ymax) :
true) && (std::abs(ry - ymax) < borderYSnapZone) && (std::abs(ymax - ry) < deltaY)) {
2667 if (windowSnapZone > 0) {
2668 for (
auto l = m_windows.constBegin(); l != m_windows.constEnd(); ++l) {
2669 if ((*l) == window) {
2672 if ((*l)->isMinimized()) {
2675 if (!(*l)->isShown()) {
2678 if (!(*l)->isOnCurrentDesktop()) {
2681 if (!(*l)->isOnCurrentActivity()) {
2684 if ((*l)->isUnmanaged() || (*l)->isDesktop() || (*l)->isSplash() || (*l)->isNotification() || (*l)->isCriticalNotification() || (*l)->isOnScreenDisplay() || (*l)->isAppletPopup()) {
2690 lrx = lx + (*l)->width();
2691 lry = ly + (*l)->height();
2693 if (!(guideMaximized &
MaximizeHorizontal) && (((cy <= lry) && (cy >= ly)) || ((ry >= ly) && (ry <= lry)) || ((cy <= ly) && (ry >= lry)))) {
2694 if ((sOWO ? (cx < lrx) :
true) && (std::abs(lrx - cx) < windowSnapZone) && (std::abs(lrx - cx) < deltaX)) {
2695 deltaX = std::abs(lrx - cx);
2698 if ((sOWO ? (rx > lx) :
true) && (std::abs(rx - lx) < windowSnapZone) && (std::abs(rx - lx) < deltaX)) {
2699 deltaX = std::abs(rx - lx);
2704 if (!(guideMaximized &
MaximizeVertical) && (((cx <= lrx) && (cx >= lx)) || ((rx >= lx) && (rx <= lrx)) || ((cx <= lx) && (rx >= lrx)))) {
2705 if ((sOWO ? (cy < lry) :
true) && (std::abs(lry - cy) < windowSnapZone) && (std::abs(lry - cy) < deltaY)) {
2706 deltaY = std::abs(lry - cy);
2710 if ((sOWO ? (ry > ly) :
true) && (std::abs(ry - ly) < windowSnapZone) && (std::abs(ry - ly) < deltaY)) {
2711 deltaY = std::abs(ry - ly);
2717 if (!(guideMaximized &
MaximizeVertical) && (nx == lrx || nx + cw == lx)) {
2718 if ((sOWO ? (ry > lry) :
true) && (std::abs(lry - ry) < windowSnapZone) && (std::abs(lry - ry) < deltaY)) {
2719 deltaY = std::abs(lry - ry);
2722 if ((sOWO ? (cy < ly) :
true) && (std::abs(cy - ly) < windowSnapZone) && (std::abs(cy - ly) < deltaY)) {
2723 deltaY = std::abs(cy - ly);
2728 if ((sOWO ? (rx > lrx) :
true) && (std::abs(lrx - rx) < windowSnapZone) && (std::abs(lrx - rx) < deltaX)) {
2729 deltaX = std::abs(lrx - rx);
2732 if ((sOWO ? (cx < lx) :
true) && (std::abs(cx - lx) < windowSnapZone) && (std::abs(cx - lx) < deltaX)) {
2733 deltaX = std::abs(cx - lx);
2742 if (centerSnapZone > 0) {
2743 int diffX = std::abs((xmin + xmax) / 2 - (cx + cw / 2));
2744 int diffY = std::abs((ymin + ymax) / 2 - (cy + ch / 2));
2745 if (diffX < centerSnapZone && diffY < centerSnapZone && diffX < deltaX && diffY < deltaY) {
2747 nx = (xmin + xmax) / 2 - cw / 2;
2748 ny = (ymin + ymax) / 2 - ch / 2;
2751 if ((nx == xmin || nx == xmax - cw) && diffY < centerSnapZone && diffY < deltaY) {
2753 ny = (ymin + ymax) / 2 - ch / 2;
2754 }
else if (((unrestricted ? ny == ymin : ny <= ymin) || ny == ymax - ch) && diffX < centerSnapZone && diffX < deltaX) {
2756 nx = (xmin + xmax) / 2 - cw / 2;
2761 pos = QPoint(nx, ny);
2766QRectF Workspace::adjustWindowSize(
Window *window, QRectF moveResizeGeom,
Gravity gravity)
2774 const QRectF maxRect = clientArea(
MovementArea, window, window->
rect().center());
2775 const qreal xmin = maxRect.left();
2776 const qreal xmax = maxRect.right();
2777 const qreal ymin = maxRect.top();
2778 const qreal ymax = maxRect.bottom();
2780 const qreal cx(moveResizeGeom.left());
2781 const qreal cy(moveResizeGeom.top());
2782 const qreal rx(moveResizeGeom.right());
2783 const qreal ry(moveResizeGeom.bottom());
2785 qreal newcx(cx), newcy(cy);
2786 qreal newrx(rx), newry(ry);
2790 qreal lx, ly, lrx, lry;
2798#define SNAP_BORDER_TOP \
2799 if ((sOWO ? (newcy < ymin) : true) && (std::abs(ymin - newcy) < deltaY)) { \
2800 deltaY = std::abs(ymin - newcy); \
2804#define SNAP_BORDER_BOTTOM \
2805 if ((sOWO ? (newry > ymax) : true) && (std::abs(ymax - newry) < deltaY)) { \
2806 deltaY = std::abs(ymax - newcy); \
2810#define SNAP_BORDER_LEFT \
2811 if ((sOWO ? (newcx < xmin) : true) && (std::abs(xmin - newcx) < deltaX)) { \
2812 deltaX = std::abs(xmin - newcx); \
2816#define SNAP_BORDER_RIGHT \
2817 if ((sOWO ? (newrx > xmax) : true) && (std::abs(xmax - newrx) < deltaX)) { \
2818 deltaX = std::abs(xmax - newrx); \
2822 case Gravity::BottomRight:
2826 case Gravity::Right:
2829 case Gravity::Bottom:
2832 case Gravity::TopLeft:
2842 case Gravity::TopRight:
2846 case Gravity::BottomLeft:
2861 for (
auto l = m_windows.constBegin(); l != m_windows.constEnd(); ++l) {
2862 if ((*l)->isOnCurrentDesktop() && !(*l)->isMinimized() && !(*l)->isUnmanaged()
2863 && (*l) != window) {
2866 lrx = (*l)->x() + (*l)->width();
2867 lry = (*l)->y() + (*l)->height();
2869#define WITHIN_HEIGHT (((newcy <= lry) && (newcy >= ly)) || ((newry >= ly) && (newry <= lry)) || ((newcy <= ly) && (newry >= lry)))
2871#define WITHIN_WIDTH (((cx <= lrx) && (cx >= lx)) || ((rx >= lx) && (rx <= lrx)) || ((cx <= lx) && (rx >= lrx)))
2873#define SNAP_WINDOW_TOP \
2874 if ((sOWO ? (newcy < lry) : true) \
2876 && (std::abs(lry - newcy) < deltaY)) { \
2877 deltaY = std::abs(lry - newcy); \
2881#define SNAP_WINDOW_BOTTOM \
2882 if ((sOWO ? (newry > ly) : true) \
2884 && (std::abs(ly - newry) < deltaY)) { \
2885 deltaY = std::abs(ly - newry); \
2889#define SNAP_WINDOW_LEFT \
2890 if ((sOWO ? (newcx < lrx) : true) \
2892 && (std::abs(lrx - newcx) < deltaX)) { \
2893 deltaX = std::abs(lrx - newcx); \
2897#define SNAP_WINDOW_RIGHT \
2898 if ((sOWO ? (newrx > lx) : true) \
2900 && (std::abs(lx - newrx) < deltaX)) { \
2901 deltaX = std::abs(lx - newrx); \
2905#define SNAP_WINDOW_C_TOP \
2906 if ((sOWO ? (newcy < ly) : true) \
2907 && (newcx == lrx || newrx == lx) \
2908 && std::abs(ly - newcy) < deltaY) { \
2909 deltaY = std::abs(ly - newcy); \
2913#define SNAP_WINDOW_C_BOTTOM \
2914 if ((sOWO ? (newry > lry) : true) \
2915 && (newcx == lrx || newrx == lx) \
2916 && std::abs(lry - newry) < deltaY) { \
2917 deltaY = std::abs(lry - newry); \
2921#define SNAP_WINDOW_C_LEFT \
2922 if ((sOWO ? (newcx < lx) : true) \
2923 && (newcy == lry || newry == ly) \
2924 && std::abs(lx - newcx) < deltaX) { \
2925 deltaX = std::abs(lx - newcx); \
2929#define SNAP_WINDOW_C_RIGHT \
2930 if ((sOWO ? (newrx > lrx) : true) \
2931 && (newcy == lry || newry == ly) \
2932 && std::abs(lrx - newrx) < deltaX) { \
2933 deltaX = std::abs(lrx - newrx); \
2938 case Gravity::BottomRight:
2944 case Gravity::Right:
2948 case Gravity::Bottom:
2952 case Gravity::TopLeft:
2966 case Gravity::TopRight:
2972 case Gravity::BottomLeft:
2996 moveResizeGeom = QRectF(QPointF(newcx, newcy), QPointF(newrx, newry));
2998 return moveResizeGeom;
3004void Workspace::setMoveResizeWindow(
Window *window)
3006 Q_ASSERT(!window || !m_moveResizeWindow);
3008 m_moveResizeWindow = window;
3009 if (m_moveResizeWindow) {
3019void Workspace::fixPositionAfterCrash(xcb_window_t w,
const xcb_get_geometry_reply_t *geometry)
3021 NETWinInfo i(kwinApp()->x11Connection(), w, kwinApp()->x11RootWindow(), NET::WMFrameExtents, NET::Properties2());
3022 NETStrut frame = i.frameExtents();
3024 if (frame.left != 0 || frame.top != 0) {
3026 const uint32_t left = frame.left;
3027 const uint32_t top = frame.top;
3028 const uint32_t values[] = {Xcb::toXNative(geometry->x - left), Xcb::toXNative(geometry->y - top)};
3029 xcb_configure_window(kwinApp()->x11Connection(), w, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
3035 return m_focusChain.get();
3040 return m_applicationMenu.get();
3045 return m_decorationBridge.get();
3050 return m_outline.get();
3055 return m_placement.get();
3060 return m_rulebook.get();
3065 return m_screenEdges.get();
3070 return m_tileManagers.at(output).get();
3073#if KWIN_BUILD_TABBOX
3076 return m_tabbox.get();
3080#if KWIN_BUILD_ACTIVITIES
3081Activities *Workspace::activities()
const
3083 return m_activities.get();
3089#include "moc_workspace.cpp"
void currentChanged(const QString &id)
void x11ConnectionChanged()
void x11ConnectionAboutToBeDestroyed()
@ OperationModeX11
KWin uses only X11 for managing windows and compositing.
int themeSize() const
The size of the currently used Cursor theme.
const QString & themeName() const
The name of the currently used Cursor theme.
This class is a wrapper for the org.kde.KWin D-Bus interface.
QStringList loadedEffects
CompositingType compositingType
Q_SCRIPTABLE QString supportInformation(const QString &name) const
QStringList activeEffects
Singleton class to handle the various focus chains.
void remove(KWin::Window *window)
Removes window from all focus chains.
void setActiveWindow(KWin::Window *window)
void setSeparateScreenFocus(bool enabled)
const QList< X11Window * > & members() const
bool isPlaceable() const override
int focusStealingPreventionLevel
void rollOverDesktopsChanged(bool enabled)
bool borderlessMaximizedWindows
bool isHideUtilityWindowsForInactive() const
bool isRollOverDesktops() const
bool isSnapOnlyWhenOverlapping() const
bool focusPolicyIsReasonable
bool isNextFocusPrefersMouse() const
bool isSeparateScreenFocus() const
void separateScreenFocusChanged(bool)
void orientationChanged()
This class is used to show the outline of a given geometry.
std::shared_ptr< OutputChangeSet > constChangeSet(Output *output) const
void remove(Window *window)
static RootInfo * create()
Class for controlling screen edges.
static Scripting * create(QObject *parent)
void tabletModeChanged(bool tabletMode)
Manages the number of available virtual desktops, the layout of those and which virtual desktop is th...
void layoutChanged(int columns, int rows)
void setRootInfo(NETRootInfo *info)
void desktopAdded(KWin::VirtualDesktop *desktop)
void setConfig(KSharedConfig::Ptr config)
void currentChanging(KWin::VirtualDesktop *currentDesktop, QPointF offset)
void currentChanged(KWin::VirtualDesktop *previousDesktop, KWin::VirtualDesktop *newDesktop)
void currentChangingCancelled()
void setNavigationWrappingAround(bool enabled)
bool setCurrent(uint current)
void desktopRemoved(KWin::VirtualDesktop *desktop)
void windowRemoved(KWin::Window *)
QList< Window * > windows() const
void windowAdded(KWin::Window *)
virtual QList< Window * > mainWindows() const
bool wantsTabFocus() const
void setOutput(Output *output)
bool isOnCurrentActivity() const
bool isOnAllDesktops() const
virtual bool isUnmanaged() const
void sendToOutput(Output *output)
bool isOnCurrentDesktop() const
void setDesktops(QList< VirtualDesktop * > desktops)
virtual MaximizeMode requestedMaximizeMode() const
QList< KWin::VirtualDesktop * > desktops
virtual bool isRequestedFullScreen() const
QRectF moveResizeGeometry() const
bool isOnDesktop(VirtualDesktop *desktop) const
void setMoveResizeOutput(Output *output)
const WindowRules * rules() const
const QList< Window * > & transients() const
void checkWorkspacePosition(QRectF oldGeometry=QRectF(), const VirtualDesktop *oldDesktop=nullptr)
void setHiddenByShowDesktop(bool hidden)
virtual bool hasStrut() const
virtual bool belongsToDesktop() const
virtual StrutRect strutRect(StrutArea area) const
virtual MaximizeMode maximizeMode() const
virtual bool isPlaceable() const
QPointF checkPosition(QPointF pos, bool init=false) const
void resetUpdateToolWindowsTimer()
Window * activeWindow() const
bool applyOutputConfiguration(const OutputConfiguration &config, const QList< Output * > &outputOrder={})
QRectF clientArea(clientAreaOption, const Output *output, const VirtualDesktop *desktop) const
void windowHidden(Window *)
void constrain(Window *below, Window *above)
X11Window * findClient(std::function< bool(const X11Window *)> func) const
Finds the first Client matching the condition expressed by passed in func.
void activateWindow(Window *window, bool force=false)
void currentDesktopChangingCancelled()
const QList< Window * > & stackingOrder() const
QList< Output * > outputOrder() const
void workspaceInitialized()
void removeX11Window(X11Window *)
Group * findGroup(xcb_window_t leader) const
void windowRemoved(KWin::Window *)
Window * findDesktop(bool topmost, VirtualDesktop *desktop) const
Output * activeOutput() const
void setupWindowShortcutDone(bool)
void currentDesktopChanged(KWin::VirtualDesktop *previousDesktop, KWin::Window *)
void updateStackingOrder(bool propagate_new_windows=false)
void currentDesktopChanging(KWin::VirtualDesktop *currentDesktop, QPointF delta, KWin::Window *)
void raiseWindow(Window *window, bool nogroup=false)
void windowActivated(KWin::Window *)
void checkTransients(xcb_window_t w)
Window * topWindowOnDesktop(VirtualDesktop *desktop, Output *output=nullptr, bool unconstrained=false, bool only_normal=true) const
void windowAdded(KWin::Window *)
void setOutputOrder(const QList< Output * > &order)
bool showingDesktop() const
QList< Output * > outputs() const
void setActiveWindow(Window *window)
const QList< Window * > windows() const
void removeUnmanaged(X11Window *)
void currentActivityChanged()
bool requestFocus(Window *window, bool force=false)
friend class StackingUpdatesBlocker
void setShowingDesktop(bool showing, bool animated=true)
void windowMinimizedChanged(KWin::Window *)
Output * outputAt(const QPointF &pos) const
void removeDeleted(Window *)
void unconstrain(Window *below, Window *above)
Output * findOutput(Output *reference, Direction direction, bool wrapAround=false) const
void addDeleted(Window *)
void deletedRemoved(KWin::Window *)
X11EventFilterContainer(X11EventFilter *filter)
X11EventFilter * filter() const
xcb_window_t inputId() const
static void deleteClient(X11Window *c)
Does 'delete c;'.
xcb_window_t frameId() const
bool isUnmanaged() const override
xcb_window_t window() const
void changeClientLeaderGroup(Group *gr)
xcb_window_t wmClientLeader() const
const Group * group() const override
xcb_window_t wrapperId() const
static Extensions * self()
void show(const QString &message, const QString &iconName, int timeout)
QList< KWayland::Client::Output * > outputs
const QPoint invalidPoint(INT_MIN, INT_MIN)
@ 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 Atoms * atoms
Predicate
Defines Predicates on how to search for a Client.
std::unique_ptr< T, CDeleter > UniqueCPtr
#define SNAP_WINDOW_RIGHT
#define SNAP_WINDOW_BOTTOM
#define SNAP_BORDER_RIGHT
#define SNAP_WINDOW_C_RIGHT
#define SNAP_WINDOW_C_LEFT
#define SNAP_WINDOW_C_TOP
#define SNAP_WINDOW_C_BOTTOM
#define SNAP_BORDER_BOTTOM