diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -395,7 +395,6 @@ client_machine.cpp cursor.cpp debug_console.cpp - tabgroup.cpp focuschain.cpp globalshortcuts.cpp input.cpp diff --git a/abstract_client.h b/abstract_client.h --- a/abstract_client.h +++ b/abstract_client.h @@ -23,7 +23,6 @@ #include "toplevel.h" #include "options.h" #include "rules.h" -#include "tabgroup.h" #include "cursor.h" #include @@ -75,12 +74,6 @@ */ Q_PROPERTY(bool fullScreenable READ isFullScreenable) - /** - * Whether this Client is the currently visible Client in its Client Group (Window Tabs). - * For change connect to the visibleChanged signal on the Client's Group. - */ - Q_PROPERTY(bool isCurrentTab READ isCurrentTab) - /** * Whether this Client is active or not. Use Workspace::activateClient() to activate a Client. * @see Workspace::activateClient @@ -318,11 +311,6 @@ */ Q_PROPERTY(bool unresponsive READ unresponsive NOTIFY unresponsiveChanged) - /** - * The "Window Tabs" Group this Client belongs to. - */ - Q_PROPERTY(KWin::TabGroup* tabGroup READ tabGroup NOTIFY tabGroupChanged SCRIPTABLE false) - /** * The color scheme set on this client * Absolute file path, or name of palette in the user's config directory following KColorSchemes format. @@ -494,36 +482,9 @@ return m_minimized; } virtual void setFullScreen(bool set, bool user = true) = 0; - // Tabbing functions - Q_INVOKABLE inline bool tabBefore(AbstractClient *other, bool activate) { return tabTo(other, false, activate); } - Q_INVOKABLE inline bool tabBehind(AbstractClient *other, bool activate) { return tabTo(other, true, activate); } - /** - * Syncs the *dynamic* @p property @p fromThisClient or the currentTab() to - * all members of the tabGroup() (if there is one) - * - * eg. if you call: - * @code - * client->setProperty("kwin_tiling_floats", true); - * client->syncTabGroupFor("kwin_tiling_floats", true) - * @endcode - * all clients in this tabGroup will have property("kwin_tiling_floats").toBool() == true - * - * WARNING: non dynamic properties are ignored - you're not supposed to alter/update such explicitly - */ - Q_INVOKABLE void syncTabGroupFor(QString property, bool fromThisClient = false); - TabGroup *tabGroup() const; - /** - * Set tab group - this is to be invoked by TabGroup::add/remove(client) and NO ONE ELSE - */ - void setTabGroup(TabGroup* group); + virtual void setClientShown(bool shown); - Q_INVOKABLE bool untab(const QRect &toGeometry = QRect(), bool clientRemoved = false); - /** - * When a click is done in the decoration and it calls the group - * to change the visible client it starts to move-resize the new - * client, this function stops it. - */ - bool isCurrentTab() const; + virtual QRect geometryRestore() const = 0; /** * The currently applied maximize mode @@ -917,11 +878,6 @@ void hasApplicationMenuChanged(bool); void applicationMenuActiveChanged(bool); void unresponsiveChanged(bool); - /** - * Emitted whenever the Client's TabGroup changed. That is whenever the Client is moved to - * another group, but not when a Client gets added or removed to the Client's ClientGroup. - */ - void tabGroupChanged(); protected: AbstractClient(); @@ -1053,13 +1009,6 @@ */ void addRepaintDuringGeometryUpdates(); - /** - * Convenient method to update the TabGroup states if there is one present. - * Marked as virtual as TabGroup does not yet handle AbstractClient, but only - * subclasses of AbstractClient. Given that the default implementation does nothing. - */ - virtual void updateTabGroupStates(TabGroup::States states); - /** * @returns whether the Client is currently in move resize mode */ @@ -1303,7 +1252,6 @@ QKeySequence _shortcut; WindowRules m_rules; - TabGroup* tab_group = nullptr; static bool s_haveResizeEffect; }; @@ -1371,11 +1319,6 @@ m_pendingGeometryUpdate = update; } -inline TabGroup* AbstractClient::tabGroup() const -{ - return tab_group; -} - } Q_DECLARE_METATYPE(KWin::AbstractClient*) diff --git a/abstract_client.cpp b/abstract_client.cpp --- a/abstract_client.cpp +++ b/abstract_client.cpp @@ -32,7 +32,6 @@ #include "tabbox.h" #endif #include "screenedge.h" -#include "tabgroup.h" #include "useractions.h" #include "workspace.h" @@ -125,96 +124,11 @@ return false; } -void AbstractClient::setTabGroup(TabGroup* group) -{ - tab_group = group; - emit tabGroupChanged(); -} - void AbstractClient::setClientShown(bool shown) { Q_UNUSED(shown) } -bool AbstractClient::untab(const QRect &toGeometry, bool clientRemoved) -{ - TabGroup *group = tab_group; - if (group && group->remove(this)) { // remove sets the tabgroup to "0", therefore the pointer is cached - if (group->isEmpty()) { - delete group; - } - if (clientRemoved) - return true; // there's been a broadcast signal that this client is now removed - don't touch it - setClientShown(!(isMinimized() || isShade())); - bool keepSize = toGeometry.size() == size(); - bool changedSize = false; - if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) { - changedSize = true; - setQuickTileMode(QuickTileFlag::None); // if we leave a quicktiled group, assume that the user wants to untile - } - if (toGeometry.isValid()) { - if (maximizeMode() != MaximizeRestore) { - changedSize = true; - maximize(MaximizeRestore); // explicitly calling for a geometry -> unmaximize - } - if (keepSize && changedSize) { - setGeometryRestore(geometry()); // checkWorkspacePosition() invokes it - QPoint cpoint = Cursor::pos(); - QPoint point = cpoint; - point.setX((point.x() - toGeometry.x()) * geometryRestore().width() / toGeometry.width()); - point.setY((point.y() - toGeometry.y()) * geometryRestore().height() / toGeometry.height()); - auto geometry_restore = geometryRestore(); - geometry_restore.moveTo(cpoint-point); - setGeometryRestore(geometry_restore); - } else { - setGeometryRestore(toGeometry); // checkWorkspacePosition() invokes it - } - setGeometry(geometryRestore()); - checkWorkspacePosition(); - } - return true; - } - return false; -} - -bool AbstractClient::tabTo(AbstractClient *other, bool behind, bool activate) -{ - Q_ASSERT(other && other != this); - - if (tab_group && tab_group == other->tabGroup()) { // special case: move inside group - tab_group->move(this, other, behind); - return true; - } - - GeometryUpdatesBlocker blocker(this); - const bool wasBlocking = signalsBlocked(); - blockSignals(true); // prevent client emitting "retabbed to nowhere" cause it's about to be entabbed the next moment - untab(); - blockSignals(wasBlocking); - - TabGroup *newGroup = other->tabGroup() ? other->tabGroup() : new TabGroup(other); - - if (!newGroup->add(this, other, behind, activate)) { - if (newGroup->count() < 2) { // adding "c" to "to" failed for whatever reason - newGroup->remove(other); - delete newGroup; - } - return false; - } - return true; -} - -void AbstractClient::syncTabGroupFor(QString property, bool fromThisClient) -{ - if (tab_group) - tab_group->sync(property.toLatin1().data(), fromThisClient ? this : tab_group->current()); -} - -bool AbstractClient::isCurrentTab() const -{ - return !tab_group || tab_group->current() == this; -} - MaximizeMode AbstractClient::requestedMaximizeMode() const { return maximizeMode(); @@ -1195,14 +1109,6 @@ if (!isDesktop()) // No point in changing the opacity of the desktop setOpacity(qMax(opacity() - 0.1, 0.1)); break; - case Options::MousePreviousTab: - if (tabGroup()) - tabGroup()->activatePrev(); - break; - case Options::MouseNextTab: - if (tabGroup()) - tabGroup()->activateNext(); - break; case Options::MouseClose: closeWindow(); break; @@ -1405,10 +1311,6 @@ m_geometryBeforeUpdateBlocking = geom; } -void AbstractClient::updateTabGroupStates(TabGroup::States) -{ -} - void AbstractClient::doMove(int, int) { } diff --git a/activation.cpp b/activation.cpp --- a/activation.cpp +++ b/activation.cpp @@ -389,8 +389,6 @@ } flags &= ~ActivityFocus; } - if (c->tabGroup() && c->tabGroup()->current() != c) - c->tabGroup()->setCurrent(c); if (!c->isShown(true)) { // shouldn't happen, call activateClient() if needed qCWarning(KWIN_CORE) << "takeActivity: not shown" ; return; @@ -467,15 +465,6 @@ AbstractClient* get_focus = NULL; - // precedence on keeping the current tabgroup active. to the user that's the same window - if (c && c->tabGroup() && c->isShown(false)) { - if (c == c->tabGroup()->current()) - c->tabGroup()->activateNext(); - get_focus = c->tabGroup()->current(); - if (get_focus == c) // single tab case - should not happen - get_focus = NULL; - } - const int desktop = VirtualDesktopManager::self()->current(); if (!get_focus && showingDesktop()) diff --git a/atoms.h b/atoms.h --- a/atoms.h +++ b/atoms.h @@ -69,7 +69,6 @@ Xcb::Atom net_wm_sync_request_counter; Xcb::Atom net_wm_sync_request; Xcb::Atom kde_net_wm_shadow; - Xcb::Atom kde_net_wm_tab_group; Xcb::Atom kde_first_in_window_list; Xcb::Atom kde_color_sheme; Xcb::Atom kde_skip_close_animation; diff --git a/atoms.cpp b/atoms.cpp --- a/atoms.cpp +++ b/atoms.cpp @@ -60,7 +60,6 @@ , net_wm_sync_request_counter(QByteArrayLiteral("_NET_WM_SYNC_REQUEST_COUNTER")) , net_wm_sync_request(QByteArrayLiteral("_NET_WM_SYNC_REQUEST")) , kde_net_wm_shadow(QByteArrayLiteral("_KDE_NET_WM_SHADOW")) - , kde_net_wm_tab_group(QByteArrayLiteral("_KDE_NET_WM_TAB_GROUP")) , kde_first_in_window_list(QByteArrayLiteral("_KDE_FIRST_IN_WINDOWLIST")) , kde_color_sheme(QByteArrayLiteral("_KDE_NET_WM_COLOR_SCHEME")) , kde_skip_close_animation(QByteArrayLiteral("_KDE_NET_WM_SKIP_CLOSE_ANIMATION")) diff --git a/client.h b/client.h --- a/client.h +++ b/client.h @@ -25,7 +25,6 @@ // kwin #include "options.h" #include "rules.h" -#include "tabgroup.h" #include "abstract_client.h" #include "xcbutils.h" // Qt @@ -346,8 +345,6 @@ bool buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root); bool motionNotifyEvent(xcb_window_t w, int state, int x, int y, int x_root, int y_root); - Client* findAutogroupCandidate() const; - protected: void debug(QDebug& stream) const override; void addDamage(const QRegion &damage) override; @@ -362,7 +359,6 @@ void doSetSkipSwitcher() override; bool belongsToDesktop() const override; void setGeometryRestore(const QRect &geo) override; - void updateTabGroupStates(TabGroup::States states) override; void doMove(int x, int y) override; bool doStartMoveResize() override; void doPerformMoveResize() override; @@ -596,8 +592,7 @@ inline bool Client::isShown(bool shaded_is_shown) const { - return !isMinimized() && (!isShade() || shaded_is_shown) && !hidden && - (!tabGroup() || tabGroup()->current() == this); + return !isMinimized() && (!isShade() || shaded_is_shown) && !hidden; } inline bool Client::isHiddenInternal() const diff --git a/client.cpp b/client.cpp --- a/client.cpp +++ b/client.cpp @@ -172,17 +172,6 @@ } }); - connect(this, &Client::tabGroupChanged, this, - [this] { - auto group = tabGroup(); - if (group) { - unsigned long data[] = {qHash(group)}; //->id(); - m_client.changeProperty(atoms->kde_net_wm_tab_group, XCB_ATOM_CARDINAL, 32, 1, data); - } - else - m_client.deleteProperty(atoms->kde_net_wm_tab_group); - }); - // SELI TODO: Initialize xsizehints?? } @@ -260,8 +249,7 @@ // Only when the window is being unmapped, not when closing down KWin (NETWM sections 5.5,5.7) info->setDesktop(0); info->setState(0, info->state()); // Reset all state flags - } else - untab(); + } xcb_connection_t *c = connection(); m_client.deleteProperty(atoms->kde_net_wm_user_creation_time); m_client.deleteProperty(atoms->net_frame_extents); @@ -619,7 +607,7 @@ bool Client::userCanSetNoBorder() const { - return !isFullScreen() && !isShade() && !tabGroup(); + return !isFullScreen() && !isShade(); } void Client::setNoBorder(bool set) @@ -779,9 +767,6 @@ updateVisibility(); updateAllowedActions(); workspace()->updateMinimizedOfTransients(this); - // Update states of all other windows in this group - if (tabGroup()) - tabGroup()->updateStates(this, TabGroup::Minimized); } QRect Client::iconGeometry() const @@ -831,10 +816,6 @@ decoration->borders(border_left, border_right, border_top, border_bottom); #endif - // Update states of all other windows in this group - if (tabGroup()) - tabGroup()->updateStates(this, TabGroup::Shaded); - if (was_shade == isShade()) { // Decoration may want to update after e.g. hover-shade changes emit shadeChanged(); @@ -917,9 +898,7 @@ void Client::shadeUnhover() { - if (!tabGroup() || tabGroup()->current() == this || - tabGroup()->current()->shadeMode() == ShadeNormal) - setShade(ShadeNormal); + setShade(ShadeNormal); cancelShadeHoverTimer(); } @@ -939,17 +918,16 @@ { if (deleting) return; - if (hidden && isCurrentTab()) { + if (hidden) { info->setState(NET::Hidden, NET::Hidden); setSkipTaskbar(true); // Also hide from taskbar if (compositing() && options->hiddenPreviews() == HiddenPreviewsAlways) internalKeep(); else internalHide(); return; } - if (isCurrentTab()) - setSkipTaskbar(originalSkipTaskbar()); // Reset from 'hidden' + setSkipTaskbar(originalSkipTaskbar()); // Reset from 'hidden' if (isMinimized()) { info->setState(NET::Hidden, NET::Hidden); if (compositing() && options->hiddenPreviews() == HiddenPreviewsAlways) @@ -1275,10 +1253,6 @@ Q_UNUSED(desktop) Q_UNUSED(was_desk) updateVisibility(); - - // Update states of all other windows in this group - if (tabGroup()) - tabGroup()->updateStates(this, TabGroup::Desktop); } /** @@ -1382,10 +1356,6 @@ FocusChain::self()->update(this, FocusChain::MakeFirst); updateVisibility(); updateWindowRules(Rules::Activity); - - // Update states of all other windows in this group - if (tabGroup()) - tabGroup()->updateStates(this, TabGroup::Activity); } /** @@ -1611,8 +1581,7 @@ } else { unmap(); // Don't move tabs to the end of the list when another tab get's activated - if (isCurrentTab()) - FocusChain::self()->update(this, FocusChain::MakeLast); + FocusChain::self()->update(this, FocusChain::MakeLast); addWorkspaceRepaint(visibleRect()); } } @@ -2111,13 +2080,6 @@ return Client::belongToSameApplication(this, c2, checks); } -void Client::updateTabGroupStates(TabGroup::States states) -{ - if (auto t = tabGroup()) { - t->updateStates(this, states); - } -} - QSize Client::resizeIncrements() const { return m_geometryHints.resizeIncrements(); diff --git a/deleted.h b/deleted.h --- a/deleted.h +++ b/deleted.h @@ -87,9 +87,6 @@ return m_fullscreen; } - bool isCurrentTab() const { - return m_wasCurrentTab; - } bool keepAbove() const { return m_keepAbove; } @@ -220,7 +217,6 @@ bool m_modal; QList m_mainClients; bool m_wasClient; - bool m_wasCurrentTab; Decoration::Renderer *m_decorationRenderer; double m_opacity; NET::WindowType m_type = NET::Unknown; diff --git a/deleted.cpp b/deleted.cpp --- a/deleted.cpp +++ b/deleted.cpp @@ -43,7 +43,6 @@ , m_minimized(false) , m_modal(false) , m_wasClient(false) - , m_wasCurrentTab(true) , m_decorationRenderer(nullptr) , m_fullscreen(false) , m_keepAbove(false) @@ -131,7 +130,6 @@ connect(c, &AbstractClient::windowClosed, this, &Deleted::mainClientClosed); } m_fullscreen = client->isFullScreen(); - m_wasCurrentTab = client->isCurrentTab(); m_keepAbove = client->keepAbove(); m_keepBelow = client->keepBelow(); m_caption = client->caption(); diff --git a/effects.cpp b/effects.cpp --- a/effects.cpp +++ b/effects.cpp @@ -563,8 +563,7 @@ Client *c = static_cast(t); disconnect(c, &Toplevel::windowShown, this, &EffectsHandlerImpl::slotClientShown); setupClientConnections(c); - if (!c->tabGroup()) // the "window" has already been there - emit windowAdded(c->effectWindow()); + emit windowAdded(c->effectWindow()); } void EffectsHandlerImpl::slotShellClientShown(Toplevel *t) @@ -1858,14 +1857,19 @@ CLIENT_HELPER_WITH_DELETED(bool, isMinimized, isMinimized, false) CLIENT_HELPER_WITH_DELETED(bool, isModal, isModal, false) CLIENT_HELPER_WITH_DELETED(bool, isFullScreen, isFullScreen, false) -CLIENT_HELPER_WITH_DELETED(bool, isCurrentTab, isCurrentTab, false) CLIENT_HELPER_WITH_DELETED(bool, keepAbove, keepAbove, false) CLIENT_HELPER_WITH_DELETED(bool, keepBelow, keepBelow, false) CLIENT_HELPER_WITH_DELETED(QString, caption, caption, QString()); CLIENT_HELPER_WITH_DELETED(QVector, desktops, x11DesktopIds, QVector()); #undef CLIENT_HELPER_WITH_DELETED +// legacy from tab groups, can be removed when no effects use this any more. +bool EffectWindowImpl::isCurrentTab() const +{ + return true; +} + QString EffectWindowImpl::windowClass() const { return toplevel->resourceName() + QLatin1Char(' ') + toplevel->resourceClass(); diff --git a/effects/desktopgrid/desktopgrid.cpp b/effects/desktopgrid/desktopgrid.cpp --- a/effects/desktopgrid/desktopgrid.cpp +++ b/effects/desktopgrid/desktopgrid.cpp @@ -1436,10 +1436,6 @@ return false; } - if (!w->isCurrentTab()) { - return false; - } - if (!w->isOnCurrentActivity()) { return false; } diff --git a/effects/flipswitch/flipswitch.cpp b/effects/flipswitch/flipswitch.cpp --- a/effects/flipswitch/flipswitch.cpp +++ b/effects/flipswitch/flipswitch.cpp @@ -370,8 +370,6 @@ w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); if (w->isMinimized()) w->enablePainting(EffectWindow::PAINT_DISABLED_BY_MINIMIZE); - if (!w->isCurrentTab()) - w->enablePainting(EffectWindow::PAINT_DISABLED_BY_TAB_GROUP); } else { if ((m_start || m_stop) && !w->isDesktop() && w->isOnCurrentDesktop()) data.setTranslucent(); diff --git a/effects/highlightwindow/highlightwindow.cpp b/effects/highlightwindow/highlightwindow.cpp --- a/effects/highlightwindow/highlightwindow.cpp +++ b/effects/highlightwindow/highlightwindow.cpp @@ -51,7 +51,7 @@ static bool isInitiallyHidden(EffectWindow* w) { // Is the window initially hidden until it is highlighted? - return w->isMinimized() || !w->isCurrentTab() || !w->isOnCurrentDesktop(); + return w->isMinimized() || !w->isOnCurrentDesktop(); } void HighlightWindowEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) @@ -97,8 +97,6 @@ if (opacity != m_windowOpacity.end() && *opacity > 0.01) { if (w->isMinimized()) w->enablePainting(EffectWindow::PAINT_DISABLED_BY_MINIMIZE); - if (!w->isCurrentTab()) - w->enablePainting(EffectWindow::PAINT_DISABLED_BY_TAB_GROUP); if (!w->isOnCurrentDesktop()) w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); } diff --git a/effects/presentwindows/presentwindows.cpp b/effects/presentwindows/presentwindows.cpp --- a/effects/presentwindows/presentwindows.cpp +++ b/effects/presentwindows/presentwindows.cpp @@ -290,8 +290,6 @@ } w->enablePainting(EffectWindow::PAINT_DISABLED_BY_MINIMIZE); // Display always w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); - if (winData->visible) - w->enablePainting(EffectWindow::PAINT_DISABLED_BY_TAB_GROUP); // Calculate window's opacity // TODO: Minimized windows or windows not on the current desktop are only 75% visible? @@ -1621,7 +1619,7 @@ DataHash::iterator winData = m_windowData.find(w); if (winData != m_windowData.end()) winData->visible = (w->isOnDesktop(desktop) || w->isOnAllDesktops()) && - !w->isMinimized() && (w->isCurrentTab() || winData->visible); + !w->isMinimized(); } if (m_closeView) m_closeView->hide(); @@ -1682,8 +1680,6 @@ return false; if (!w->acceptsFocus()) return false; - if (!w->isCurrentTab()) - return false; if (w->isSkipSwitcher()) return false; if (m_closeView && w == effects->findWindow(m_closeView->winId())) diff --git a/effects/slideback/slideback.cpp b/effects/slideback/slideback.cpp --- a/effects/slideback/slideback.cpp +++ b/effects/slideback/slideback.cpp @@ -299,7 +299,7 @@ bool SlideBackEffect::isWindowUsable(EffectWindow* w) { return w && (w->isNormalWindow() || w->isDialog()) && !w->keepAbove() && !w->isDeleted() && !w->isMinimized() - && w->isCurrentTab() && w->isPaintingEnabled(); + && w->isPaintingEnabled(); } bool SlideBackEffect::intersects(EffectWindow* windowUnder, const QRect &windowOverGeometry) diff --git a/geometry.cpp b/geometry.cpp --- a/geometry.cpp +++ b/geometry.cpp @@ -548,8 +548,6 @@ continue; // is minimized if (!(*l)->isShown(false)) continue; - if ((*l)->tabGroup() && (*l) != (*l)->tabGroup()->current()) - continue; // is not active tab if (!((*l)->isOnDesktop(c->desktop()) || c->isOnDesktop((*l)->desktop()))) continue; // wrong virtual desktop if (!(*l)->isOnCurrentActivity()) @@ -1360,8 +1358,8 @@ // basesize, minsize, maxsize, paspect and resizeinc have all values defined, // even if they're not set in flags - see getWmNormalHints() - QSize min_size = tabGroup() ? tabGroup()->minSize() : minSize(); - QSize max_size = tabGroup() ? tabGroup()->maxSize() : maxSize(); + QSize min_size = minSize(); + QSize max_size = maxSize(); if (isDecorated()) { QSize decominsize(0, 0); QSize border_size(borderLeft() + borderRight(), borderTop() + borderBottom()); @@ -1531,10 +1529,6 @@ // align to eventual new contraints maximize(max_mode); } - // Update min/max size of this group - if (tabGroup()) - tabGroup()->updateMinMaxSize(); - if (isManaged()) { // update to match restrictions QSize new_size = adjustedSize(); @@ -1900,8 +1894,8 @@ mode == PositionLeft || mode == PositionBottomLeft) && rules()->checkPosition(invalidPoint) != invalidPoint) return false; - QSize min = tabGroup() ? tabGroup()->minSize() : minSize(); - QSize max = tabGroup() ? tabGroup()->maxSize() : maxSize(); + QSize min = minSize(); + QSize max = maxSize(); return min.width() < max.width() || min.height() < max.height(); } @@ -1996,22 +1990,15 @@ screens()->setCurrent(this); workspace()->updateStackingOrder(); - // need to regenerate decoration pixmaps when either + // need to regenerate decoration pixmaps when // - size is changed - // - maximize mode is changed to MaximizeRestore, when size unchanged - // which can happen when untabbing maximized windows if (resized) { if (oldClientSize != QSize(w,h)) discardWindowPixmap(); } emit geometryShapeChanged(this, geometryBeforeUpdateBlocking()); addRepaintDuringGeometryUpdates(); updateGeometryBeforeUpdateBlocking(); - - // Update states of all other windows in this group - if (tabGroup()) - tabGroup()->updateStates(this, TabGroup::Geometry); - // TODO: this signal is emitted too often emit geometryChanged(); } @@ -2069,10 +2056,6 @@ emit geometryShapeChanged(this, geometryBeforeUpdateBlocking()); addRepaintDuringGeometryUpdates(); updateGeometryBeforeUpdateBlocking(); - - // Update states of all other windows in this group - if (tabGroup()) - tabGroup()->updateStates(this, TabGroup::Geometry); // TODO: this signal is emitted too often emit geometryChanged(); } @@ -2107,9 +2090,6 @@ // client itself is not damaged addRepaintDuringGeometryUpdates(); updateGeometryBeforeUpdateBlocking(); - - // Update states of all other windows in this group - updateTabGroupStates(TabGroup::Geometry); emit geometryChanged(); } @@ -2159,34 +2139,6 @@ } -// Update states of all other windows in this group -class TabSynchronizer -{ -public: - TabSynchronizer(AbstractClient *client, TabGroup::States syncStates) : - m_client(client) , m_states(syncStates) - { - if (client->tabGroup()) - client->tabGroup()->blockStateUpdates(true); - } - ~TabSynchronizer() - { - syncNow(); - } - void syncNow() - { - if (m_client && m_client->tabGroup()) { - m_client->tabGroup()->blockStateUpdates(false); - m_client->tabGroup()->updateStates(dynamic_cast(m_client), m_states); - } - m_client = 0; - } -private: - AbstractClient *m_client; - TabGroup::States m_states; -}; - - static bool changeMaximizeRecursion = false; void Client::changeMaximize(bool horizontal, bool vertical, bool adjust) { @@ -2236,8 +2188,6 @@ return; GeometryUpdatesBlocker blocker(this); - // QT synchronizing required because we eventually change from QT to Maximized - TabSynchronizer syncer(this, TabGroup::Maximized|TabGroup::QuickTile); // maximing one way and unmaximizing the other way shouldn't happen, // so restore first and then maximize the other way @@ -2437,8 +2387,6 @@ break; } - syncer.syncNow(); // important because of window rule updates! - updateAllowedActions(); updateWindowRules(Rules::MaximizeVert|Rules::MaximizeHoriz|Rules::Position|Rules::Size); emit quickTileModeChanged(); @@ -2474,7 +2422,6 @@ if (set) { m_fullscreenMode = FullScreenNormal; - untab(); workspace()->raiseClient(this); } else { m_fullscreenMode = FullScreenNone; @@ -3230,7 +3177,6 @@ GeometryUpdatesBlocker blocker(this); if (mode == QuickTileMode(QuickTileFlag::Maximize)) { - TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry|TabGroup::Maximized); m_quickTileMode = int(QuickTileFlag::None); if (maximizeMode() == MaximizeFull) { setMaximize(false, false); @@ -3261,8 +3207,6 @@ // restore from maximized so that it is possible to tile maximized windows with one hit or by dragging if (maximizeMode() != MaximizeRestore) { - TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry|TabGroup::Maximized); - if (mode != QuickTileMode(QuickTileFlag::None)) { // decorations may turn off some borders when tiled const ForceGeometry_t geom_mode = isDecorated() ? ForceGeometrySet : NormalGeometrySet; @@ -3284,8 +3228,6 @@ } if (mode != QuickTileMode(QuickTileFlag::None)) { - TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry); - QPoint whichScreen = keyboard ? geometry().center() : Cursor::pos(); // If trying to tile to the side that the window is already tiled to move the window to the next @@ -3350,8 +3292,6 @@ } if (mode == QuickTileMode(QuickTileFlag::None)) { - TabSynchronizer syncer(this, TabGroup::QuickTile|TabGroup::Geometry); - m_quickTileMode = int(QuickTileFlag::None); // Untiling, so just restore geometry, and we're done. if (!geometryRestore().isValid()) // invalid if we started maximized and wait for placement diff --git a/input.cpp b/input.cpp --- a/input.cpp +++ b/input.cpp @@ -2140,7 +2140,7 @@ continue; } if (AbstractClient *c = dynamic_cast(t)) { - if (!c->isOnCurrentActivity() || !c->isOnCurrentDesktop() || c->isMinimized() || !c->isCurrentTab() || c->isHiddenInternal()) { + if (!c->isOnCurrentActivity() || !c->isOnCurrentDesktop() || c->isMinimized() || c->isHiddenInternal()) { continue; } } diff --git a/kwinbindings.cpp b/kwinbindings.cpp --- a/kwinbindings.cpp +++ b/kwinbindings.cpp @@ -46,10 +46,6 @@ initShortcut(QStringLiteral(name), i18n(name), key, target, &fnSlot); -DEF(I18N_NOOP("Walk Through Window Tabs"), 0, slotActivateNextTab); -DEF(I18N_NOOP("Walk Through Window Tabs (Reverse)"), 0, slotActivatePrevTab); -DEF(I18N_NOOP("Remove Window From Group"), 0, slotUntab); - DEF(I18N_NOOP("Window Operations Menu"), Qt::ALT + Qt::Key_F3, slotWindowOperations); DEF2("Window Close", I18N_NOOP("Close Window"), diff --git a/layers.cpp b/layers.cpp --- a/layers.cpp +++ b/layers.cpp @@ -856,16 +856,10 @@ void Client::doSetKeepAbove() { - // Update states of all other windows in this group - if (tabGroup()) - tabGroup()->updateStates(this, TabGroup::Layer); } void Client::doSetKeepBelow() { - // Update states of all other windows in this group - if (tabGroup()) - tabGroup()->updateStates(this, TabGroup::Layer); } bool Client::belongsToDesktop() const diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -2098,7 +2098,7 @@ PAINT_DISABLED_BY_DESKTOP = 1 << 2, /** Window will not be painted because it is minimized */ PAINT_DISABLED_BY_MINIMIZE = 1 << 3, - /** Window will not be painted because it is not the active window in a client group */ + /** Deprecated, tab groups have been removed: Window will not be painted because it is not the active window in a client group */ PAINT_DISABLED_BY_TAB_GROUP = 1 << 4, /** Window will not be painted because it's not on the current activity */ PAINT_DISABLED_BY_ACTIVITY = 1 << 5 @@ -2333,6 +2333,7 @@ virtual void unminimize() = 0; Q_SCRIPTABLE virtual void closeWindow() = 0; + /// deprecated virtual bool isCurrentTab() const = 0; /** diff --git a/manage.cpp b/manage.cpp --- a/manage.cpp +++ b/manage.cpp @@ -340,51 +340,6 @@ // Create client group if the window will have a decoration bool dontKeepInArea = false; - setTabGroup(NULL); - if (!noBorder() && false) { - const bool autogrouping = rules()->checkAutogrouping(options->isAutogroupSimilarWindows()); - const bool autogroupInFg = rules()->checkAutogroupInForeground(options->isAutogroupInForeground()); - // Automatically add to previous groups on session restore - if (session && session->tabGroupClient && !workspace()->hasClient(session->tabGroupClient)) - session->tabGroupClient = NULL; - if (session && session->tabGroupClient && session->tabGroupClient != this) { - tabBehind(session->tabGroupClient, autogroupInFg); - } else if (isMapped && autogrouping) { - // If the window is already mapped (Restarted KWin) add any windows that already have the - // same geometry to the same client group. (May incorrectly handle maximized windows) - foreach (Client *other, workspace()->clientList()) { - if (other->maximizeMode() != MaximizeFull && - geom == QRect(other->pos(), other->clientSize()) && - desk == other->desktop() && activities() == other->activities()) { - - tabBehind(other, autogroupInFg); - break; - - } - } - } - if (!(tabGroup() || isMapped || session)) { - // Attempt to automatically group similar windows - Client* similar = findAutogroupCandidate(); - if (similar && !similar->noBorder()) { - if (autogroupInFg) { - similar->setDesktop(desk); // can happen when grouping by id. ... - similar->setMinimized(false); // ... or anyway - still group, but "here" and visible - } - if (!similar->isMinimized()) { // do not attempt to tab in background of a hidden group - geom = QRect(similar->pos() + similar->clientPos(), similar->clientSize()); - updateDecoration(false); - if (tabBehind(similar, autogroupInFg)) { - // Don't move entire group - geom = QRect(similar->pos() + similar->clientPos(), similar->clientSize()); - placementDone = true; - dontKeepInArea = true; - } - } - } - } - } - readColorScheme(colorSchemeCookie); readApplicationMenuServiceName(applicationMenuServiceNameCookie); @@ -745,52 +700,4 @@ return b; } -Client* Client::findAutogroupCandidate() const -{ - // Attempt to find a similar window to the input. If we find multiple possibilities that are in - // different groups then ignore all of them. This function is for automatic window grouping. - Client *found = NULL; - - // See if the window has a group ID to match with - QString wGId = rules()->checkAutogroupById(QString()); - if (!wGId.isEmpty()) { - foreach (Client *c, workspace()->clientList()) { - if (activities() != c->activities()) - continue; // don't cross activities - if (wGId == c->rules()->checkAutogroupById(QString())) { - if (found && found->tabGroup() != c->tabGroup()) { // We've found two, ignore both - found = NULL; - break; // Continue to the next test - } - found = c; - } - } - if (found) - return found; - } - - // If this is a transient window don't take a guess - if (isTransient()) - return NULL; - - // If we don't have an ID take a guess - if (rules()->checkAutogrouping(options->isAutogroupSimilarWindows())) { - QByteArray wRole = truncatedWindowRole(windowRole()); - foreach (Client *c, workspace()->clientList()) { - if (desktop() != c->desktop() || activities() != c->activities()) - continue; - QByteArray wRoleB = truncatedWindowRole(c->windowRole()); - if (resourceClass() == c->resourceClass() && // Same resource class - wRole == wRoleB && // Same window role - c->isNormalWindow()) { // Normal window TODO: Can modal windows be "normal"? - if (found && found->tabGroup() != c->tabGroup()) // We've found two, ignore both - return NULL; - found = c; - } - } - } - - return found; -} - } // namespace diff --git a/options.h b/options.h --- a/options.h +++ b/options.h @@ -362,11 +362,6 @@ NoOp, SetupWindowShortcutOp, ApplicationRulesOp, - RemoveTabFromGroupOp, // Remove from group - CloseTabGroupOp, // Close the group - ActivateNextTabOp, // Move left in the group - ActivatePreviousTabOp, // Move right in the group - TabDragOp, }; WindowOperation operationTitlebarDblClick() const { diff --git a/placement.cpp b/placement.cpp --- a/placement.cpp +++ b/placement.cpp @@ -178,8 +178,6 @@ return true; if (client == regarding) return true; - if (!client->isCurrentTab()) - return true; if (!client->isShown(false)) return true; if (!client->isOnDesktop(desktop)) diff --git a/scene.h b/scene.h --- a/scene.h +++ b/scene.h @@ -319,8 +319,6 @@ PAINT_DISABLED_BY_DESKTOP = 1 << 2, // Window will not be painted because it is minimized PAINT_DISABLED_BY_MINIMIZE = 1 << 3, - // Window will not be painted because it is not the active window in a client group - PAINT_DISABLED_BY_TAB_GROUP = 1 << 4, // Window will not be painted because it's not on the current activity PAINT_DISABLED_BY_ACTIVITY = 1 << 5 }; diff --git a/scene.cpp b/scene.cpp --- a/scene.cpp +++ b/scene.cpp @@ -819,8 +819,6 @@ if (AbstractClient *c = dynamic_cast(toplevel)) { if (c->isMinimized()) disable_painting |= PAINT_DISABLED_BY_MINIMIZE; - if (c->tabGroup() && c != c->tabGroup()->current()) - disable_painting |= PAINT_DISABLED_BY_TAB_GROUP; if (c->isHiddenInternal()) { disable_painting |= PAINT_DISABLED; } diff --git a/scripting/scripting_model.cpp b/scripting/scripting_model.cpp --- a/scripting/scripting_model.cpp +++ b/scripting/scripting_model.cpp @@ -142,11 +142,6 @@ return true; } } - if (exclusions & ClientModel::NonSelectedWindowTabExclusion) { - if (!client->isCurrentTab()) { - return true; - } - } if (exclusions & ClientModel::NotAcceptingFocusExclusion) { if (!client->wantsInput()) { return true; diff --git a/shell_client.cpp b/shell_client.cpp --- a/shell_client.cpp +++ b/shell_client.cpp @@ -1033,7 +1033,6 @@ m_fullScreen = set; if (set) { - untab(); workspace()->raiseClient(this); } RequestGeometryBlocker requestBlocker(this); @@ -1116,10 +1115,10 @@ bool ShellClient::userCanSetNoBorder() const { if (m_serverDecoration && m_serverDecoration->mode() == ServerSideDecorationManagerInterface::Mode::Server) { - return !isFullScreen() && !isShade() && !tabGroup(); + return !isFullScreen() && !isShade(); } if (m_xdgDecoration && m_xdgDecoration->requestedMode() != XdgDecorationInterface::Mode::ClientSide) { - return !isFullScreen() && !isShade() && !tabGroup(); + return !isFullScreen() && !isShade(); } return false; } diff --git a/sm.h b/sm.h --- a/sm.h +++ b/sm.h @@ -66,9 +66,7 @@ bool active; // means 'was active in the saved session' int stackingOrder; float opacity; - int tabGroup; // Unique identifier for the client group that this window is in - Client* tabGroupClient; // The first client created that has an identical identifier QStringList activities; }; diff --git a/sm.cpp b/sm.cpp --- a/sm.cpp +++ b/sm.cpp @@ -202,8 +202,6 @@ cg.writeEntry(QLatin1String("windowType") + n, windowTypeToTxt(c->windowType())); cg.writeEntry(QLatin1String("shortcut") + n, c->shortcut().toString()); cg.writeEntry(QLatin1String("stackingOrder") + n, unconstrained_stacking_order.indexOf(c)); - // KConfig doesn't support long so we need to live with less precision on 64-bit systems - cg.writeEntry(QLatin1String("tabGroup") + n, static_cast(reinterpret_cast(c->tabGroup()))); cg.writeEntry(QLatin1String("activities") + n, c->activities()); } @@ -287,8 +285,6 @@ info->shortcut = cg.readEntry(QLatin1String("shortcut") + n, QString()); info->active = (active_client == i); info->stackingOrder = cg.readEntry(QLatin1String("stackingOrder") + n, -1); - info->tabGroup = cg.readEntry(QLatin1String("tabGroup") + n, 0); - info->tabGroupClient = NULL; info->activities = cg.readEntry(QLatin1String("activities") + n, QStringList()); } } @@ -363,15 +359,6 @@ } } } - - // Set tabGroupClient for other clients in the same group - if (realInfo && realInfo->tabGroup) { - foreach (SessionInfo * info, session) { - if (!info->tabGroupClient && info->tabGroup == realInfo->tabGroup) - info->tabGroupClient = c; - } - } - return realInfo; } diff --git a/tabgroup.h b/tabgroup.h deleted file mode 100644 --- a/tabgroup.h +++ /dev/null @@ -1,209 +0,0 @@ -/******************************************************************************* -KWin - the KDE window manager -This file is part of the KDE project. - -Copyright (C) 2011/2012 The KWin team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*******************************************************************************/ - -#ifndef KWIN_TABGROUP_H -#define KWIN_TABGROUP_H - -#include - -#include "utils.h" - -namespace KWin -{ - -class AbstractClient; - -/** - * This class represents a group of clients for use in window tabbing. All - * clients in the group share the same geometry and state information; I.e if - * one client changes then all others should also be changed. - * - * A group contains at least one client and DOES NOT contain multiple - * copies of the same client. A client MUST NOT be in two groups at the same - * time. All decorated clients SHOULD be in a group, even if it's a group of - * one client. - * - * rohanp: Had to convert this object to a QObject to make it easier for adding - * scripting interface to TabGroup. - * - * If a group contains multiple clients then only one will ever be mapped at - * any given time. - */ -class TabGroup -{ -public: - /** - * Creates a new group containing \p c. - */ - explicit TabGroup(AbstractClient* c); - ~TabGroup(); - - enum State { - None = 0, Minimized = 1<<0, Maximized = 1<<1, Shaded = 1<<2, - Geometry = 1<<3, Desktop = 1<<4, Activity = 1<<5, - Layer = 1<<6, QuickTile = 1<<7, All = 0xffffffff - }; - Q_DECLARE_FLAGS(States, State) - - /** - * Activate next tab (flips) - */ - void activateNext(); - - /** - * Activate previous tab (flips) - */ - void activatePrev(); - - /** - * Allows to alter several attributes in random order and trigger a general update at the end - * (must still be explicitly called) - * this is to prevent side effects, mostly for geometry adjustments during maximization and QuickTiling - */ - void blockStateUpdates(bool); - - /** - * Close all clients in this group. - */ - void closeAll(); - - /** - * Whether client \p c is member of this group - */ - bool contains(AbstractClient* c) const; - - /** - * The amount of clients in this group - */ - int count() const; - - /** - * Returns whether or not this group contains the active client. - */ - bool isActive() const; - - /** - * Returns whether this group is empty (used by workspace to remove it) - */ - bool isEmpty() const; - - /** - * Returns the list of all the clients contained in this group in their current order. - */ - const QVector &clients() const; - - /** - * Returns the currently visible client. - */ - AbstractClient* current() const; - /** - * Makes \p c the visible client in the group - force is only used when the window becomes ready for painting. - * Any other usage just causes pointless action - */ - void setCurrent(AbstractClient* c, bool force = false); - - /** - * Alignes the dynamic Qt @param property of all clients to the one of @param c - */ - void sync(const char *property, AbstractClient *c); - - /** - * Returns combined minimum size of all clients in the group. - */ - QSize minSize() const; - /** - * Returns combined maximum size of all clients in the group. - */ - QSize maxSize() const; - - /** - * Ensures that all the clients in the group have identical geometries and states using - * \p main as the primary client to copy the settings off. If \p only is set then only - * that client is updated to match \p main. - */ - void updateStates(AbstractClient* main, States states, AbstractClient* only = NULL); - - /** - * updates geometry restrictions of this group, basically called from Client::getWmNormalHints(), otherwise rather private - */ - void updateMinMaxSize(); - -Q_SIGNALS: - void minSizeChanged(); - void maxSizeChanged(); - -private: - friend class AbstractClient; - friend class Client; -// friend bool Client::tabTo(Client*, bool, bool); - bool add(KWin::AbstractClient *c, AbstractClient *other, bool behind, bool activateC); - void move(KWin::AbstractClient* c, KWin::AbstractClient* before, bool behind); - -// friend bool Client::untab(const QRect&); - bool remove(KWin::AbstractClient *c); - - QVector m_clients; - AbstractClient *m_current; - QSize m_minSize; - QSize m_maxSize; - int m_stateUpdatesBlocked; - States m_pendingUpdates; -}; - -inline bool TabGroup::contains(AbstractClient* c) const -{ - return c && m_clients.contains(c); -} - -inline int TabGroup::count() const -{ - return m_clients.count(); -} - -inline const QVector &TabGroup::clients() const -{ - return m_clients; -} - -inline bool TabGroup::isEmpty() const -{ - return m_clients.isEmpty(); -} - -inline AbstractClient* TabGroup::current() const -{ - return m_current; -} - -inline QSize TabGroup::minSize() const -{ - return m_minSize; -} - -inline QSize TabGroup::maxSize() const -{ - return m_maxSize; -} - -} - -Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::TabGroup::States) - -#endif diff --git a/tabgroup.cpp b/tabgroup.cpp deleted file mode 100644 --- a/tabgroup.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/******************************************************************************* -KWin - the KDE window manager -This file is part of the KDE project. - -Copyright (C) 2011/2012 The KWin team - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*******************************************************************************/ - -#include "tabgroup.h" - -#include "client.h" -#include "effects.h" -#include "workspace.h" - -namespace KWin -{ - -TabGroup::TabGroup(AbstractClient *c) - : m_clients() - , m_current(c) - , m_minSize(c->minSize()) - , m_maxSize(c->maxSize()) - , m_stateUpdatesBlocked(0) - , m_pendingUpdates(TabGroup::None) -{ - QIcon icon(c->icon()); - m_clients << c; - c->setTabGroup(this); - c->setClientShown(true); -} - -TabGroup::~TabGroup() -{ -} - - -void TabGroup::activateNext() -{ - int index = m_clients.indexOf(m_current); - setCurrent(m_clients.at((index < m_clients.count() - 1) ? index + 1 : 0)); -} - -void TabGroup::activatePrev() -{ - int index = m_clients.indexOf(m_current); - setCurrent(m_clients.at((index > 0) ? index - 1 : m_clients.count() - 1)); -} - -bool TabGroup::add(AbstractClient* c, AbstractClient *other, bool after, bool becomeVisible) -{ - Q_ASSERT(!c->tabGroup()); - - if (contains(c) || !contains(other)) - return false; - - // Tabbed windows MUST have a decoration - c->setNoBorder(false); - if (c->noBorder()) - return false; - - // If it's not possible to have the same states then ungroup them, TODO: Check all states - // We do this here as the ungroup code in updateStates() cannot be called until add() completes - - bool cannotTab = false; - ShadeMode oldShadeMode = c->shadeMode(); - QRect oldGeom = c->geometry(); - int oldDesktop = c->desktop(); - - c->setShade(m_current->shadeMode()); - cannotTab = c->shadeMode() != m_current->shadeMode(); - if (!cannotTab) { - c->setDesktop(m_current->desktop()); - cannotTab = c->desktop() != m_current->desktop(); - } - if (!cannotTab) { - c->setGeometry(m_current->geometry()); - cannotTab = c->geometry() != m_current->geometry(); - } - - if (cannotTab) { - c->setShade(oldShadeMode); - c->setDesktop(oldDesktop); - c->setGeometry(oldGeom); - // trigger decoration repaint on the group to make sure that hover animations are properly reset. - m_current->triggerDecorationRepaint(); - return false; // cannot tab - } - - // Actually add to new group ---------------------------------------- - - // Notify effects of merge - if (effects) - static_cast(effects)->slotTabAdded(c->effectWindow(), other->effectWindow()); - - // next: aling the client states BEFORE adding it to the group - // otherwise the caused indirect state changes would be taken as the dominating ones and break - // the main client - // example: QuickTiling is aligned to None, this restores the former QuickTiled size and alignes - // all other windows in the group - including the actual main client! - to this size and thus - // breaks the actually required alignment to the main windows geometry (because that now has the - // restored geometry of the formerly Q'tiled window) - bug #303937 - updateStates(m_current, All, c); - - int index = other ? m_clients.indexOf(other) : m_clients.size(); - index += after; - if (index > m_clients.size()) - index = m_clients.size(); - - m_clients.insert(index, c); - - c->setTabGroup(this); // Let the client know which group it belongs to - - updateMinMaxSize(); - - if (!becomeVisible) - c->setClientShown(false); - else { - c->setClientShown(true); - if (!effects || c->readyForPainting()) { - setCurrent(c); - if (options->focusPolicyIsReasonable()) - workspace()->requestFocus( c ); - } - else { - if (options->focusPolicyIsReasonable()) - workspace()->requestFocus( m_current ); - m_current = c; // setCurrent will be called by Toplevel::setReadyForPainting() - } - } - - m_current->triggerDecorationRepaint(); - return true; -} - -bool TabGroup::remove(AbstractClient* c) -{ - if (!c) - return false; - - int index = m_clients.indexOf(c); - if (index < 0) - return false; - - c->setTabGroup(NULL); - - m_clients.removeAt(index); - updateMinMaxSize(); - - if (m_clients.count() == 1) { // split - remove(m_clients.at(0)); - } - if (m_clients.isEmpty()) { // remaining singleton "tab" - c->setClientShown(true); - return true; // group is gonna be deleted after this anyway - } - - if (c == m_current) { - m_current = index < m_clients.count() ? m_clients.at(index) : m_clients.last(); - m_current->setClientShown(true); - - if (effects) // "c -> m_current" because c was m_current - static_cast(effects)->slotCurrentTabAboutToChange(c->effectWindow(), m_current->effectWindow()); - } - - // Notify effects of removal - if (effects) - static_cast(effects)->slotTabRemoved(c->effectWindow(), m_current->effectWindow()); - - m_current->triggerDecorationRepaint(); - return true; -} - -void TabGroup::closeAll() -{ - // NOTICE - in theory it's OK to use the list because closing sends an event to the client and - // due to the async X11 nature, the client would be released and thus removed from m_clients - // after this function exits. - // However later Wayland support or similar might not share this bahaviour - and we really had - // enough trouble with a polluted client list around the tabbing code .... - auto list(m_clients); - for (auto i = list.constBegin(), end = list.constEnd(); i != end; ++i) - if (*i != m_current) - (*i)->closeWindow(); - - m_current->closeWindow(); -} - -void TabGroup::move(AbstractClient *c, AbstractClient *other, bool after) -{ - if (c == other) - return; - - int from = m_clients.indexOf(c); - if (from < 0) - return; - - int to = other ? m_clients.indexOf(other) : m_clients.size() - 1; - if (to < 0) - return; - to += after; - if (to >= m_clients.size()) - to = m_clients.size() - 1; - - if (from == to) - return; - - m_clients.move(from, to); - m_current->triggerDecorationRepaint(); -} - -bool TabGroup::isActive() const -{ - return contains(Workspace::self()->activeClient()); -} - -void TabGroup::setCurrent(AbstractClient* c, bool force) -{ - if ((c == m_current && !force) || !contains(c)) - return; - - // Notify effects of switch - if (effects) - static_cast(effects)->slotCurrentTabAboutToChange(m_current->effectWindow(), c->effectWindow()); - - m_current = c; - c->setClientShown(true); // reduce flicker? - for (auto i = m_clients.constBegin(), end = m_clients.constEnd(); i != end; ++i) - (*i)->setClientShown((*i) == m_current); -} - -void TabGroup::sync(const char *property, AbstractClient *c) -{ - if (c->metaObject()->indexOfProperty(property) > -1) { - qCWarning(KWIN_CORE, "caught attempt to sync non dynamic property: %s", property); - return; - } - QVariant v = c->property(property); - for (auto i = m_clients.begin(), end = m_clients.end(); i != end; ++i) { - if (*i != m_current) - (*i)->setProperty(property, v); - } -} - -void TabGroup::updateMinMaxSize() -{ - // Determine entire group's minimum and maximum sizes - // TODO this used to be signalled out but i didn't find a receiver - or got an idea what this would be good for - // find purpose & solution or kick it -// QSize oldMin = m_minSize; -// QSize oldMax = m_maxSize; - m_minSize = QSize(0, 0); - m_maxSize = QSize(INT_MAX, INT_MAX); - - for (auto i = m_clients.constBegin(); i != m_clients.constEnd(); ++i) { - m_minSize = m_minSize.expandedTo((*i)->minSize()); - m_maxSize = m_maxSize.boundedTo((*i)->maxSize()); - } - - // TODO: this actually resolves a conflict that should be caught when adding? - m_maxSize = m_maxSize.expandedTo(m_minSize); - - // calculate this _once_ to get a common size. - // TODO this leaves another unresolved conflict about the base increment (luckily not used too often) - const QSize size = m_current->clientSize().expandedTo(m_minSize).boundedTo(m_maxSize); - if (size != m_current->clientSize()) { - const QRect r(m_current->pos(), m_current->sizeForClientSize(size)); - for (auto i = m_clients.constBegin(), end = m_clients.constEnd(); i != end; ++i) - (*i)->setGeometry(r); - } -} - - -void TabGroup::blockStateUpdates(bool more) { - more ? ++m_stateUpdatesBlocked : --m_stateUpdatesBlocked; - if (m_stateUpdatesBlocked < 0) { - m_stateUpdatesBlocked = 0; - qCWarning(KWIN_CORE, "TabGroup: Something is messed up with TabGroup::blockStateUpdates() invocation\nReleased more than blocked!"); - } -} - -void TabGroup::updateStates(AbstractClient* main, States states, AbstractClient* only) -{ - if (main == only) - return; // there's no need to only align "us" to "us" - if (m_stateUpdatesBlocked > 0) { - m_pendingUpdates |= states; - return; - } - - states |= m_pendingUpdates; - m_pendingUpdates = TabGroup::None; - - QVector toBeRemoved, onlyDummy; - auto *list = &m_clients; - if (only) { - onlyDummy << only; - list = &onlyDummy; - } - - for (auto i = list->constBegin(), end = list->constEnd(); i != end; ++i) { - auto *c = (*i); - if (c != main) { - if ((states & Minimized) && c->isMinimized() != main->isMinimized()) { - if (main->isMinimized()) - c->minimize(true); - else - c->unminimize(true); - } - - // the order QuickTile -> Maximized -> Geometry is somewhat important because one will change the other - // don't change w/o good reason and care - if ((states & QuickTile) && c->quickTileMode() != main->quickTileMode()) - c->setQuickTileMode(main->quickTileMode()); - if ((states & Maximized) && c->maximizeMode() != main->maximizeMode()) - c->maximize(main->maximizeMode()); - // the order Shaded -> Geometry is somewhat important because one will change the other - if ((states & Shaded)) - c->setShade(main->shadeMode()); - if ((states & Geometry) && c->geometry() != main->geometry()) - c->setGeometry(main->geometry()); - if (states & Desktop) { - if (c->isOnAllDesktops() != main->isOnAllDesktops()) - c->setOnAllDesktops(main->isOnAllDesktops()); - if (c->desktop() != main->desktop()) - c->setDesktop(main->desktop()); - } - if ((states & Activity) && c->activities() != main->activities()) { - c->setOnActivities(main->activities()); - } - if (states & Layer) { - if (c->keepAbove() != main->keepAbove()) - c->setKeepAbove(main->keepAbove()); - if (c->keepBelow() != main->keepBelow()) - c->setKeepBelow(main->keepBelow()); - } - - // If it's not possible to have the same states then ungroup them, TODO: Check all states - if (((states & Geometry) && c->geometry() != main->geometry()) || - ((states & Desktop) && c->desktop() != main->desktop())) - toBeRemoved << c; - } - } - - for (auto i = toBeRemoved.constBegin(), end = toBeRemoved.constEnd(); i != end; ++i) - remove(*i); -} - -} diff --git a/toplevel.cpp b/toplevel.cpp --- a/toplevel.cpp +++ b/toplevel.cpp @@ -501,10 +501,6 @@ if (compositing()) { addRepaintFull(); emit windowShown(this); - if (auto *cl = dynamic_cast(this)) { - if (cl->tabGroup() && cl->tabGroup()->current() == cl) - cl->tabGroup()->setCurrent(cl, true); - } } } } diff --git a/useractions.h b/useractions.h --- a/useractions.h +++ b/useractions.h @@ -120,26 +120,6 @@ * Adjust the items according to the respective Client. */ void menuAboutToShow(); - /** - * Adjusts the add to tab group menu to the current value of the Client. - */ - void rebuildTabGroupPopup(); - /** - * Adjusts the switch to tab menu to the current values of the Client. - */ - void rebuildTabListPopup(); - /** - * Adds the Client as tab to the Client identified by the @p action. - * - * @param action The invoked action containing the Client to which the active Client should be tabbed. - */ - void entabPopupClient(QAction *action); - /** - * Activates the selected tabbed Client. - * - * @param action The invoked action containing the tabbed Client which should be activated. - */ - void selectPopupClientTab(QAction *action); /** * Adjusts the desktop popup to the current values and the location of * the Client. @@ -210,10 +190,6 @@ * Oh, and an 'all' option too of course */ void initActivityPopup(); - /** - * Creates the Window Tabbing related menus. - */ - void initTabbingPopups(); /** * Shows a helper Dialog to inform the user how to get back in case he triggered * an action which hides the window decoration (e.g. NoBorder or Fullscreen). @@ -241,14 +217,6 @@ * The activities sub menu. */ QMenu* m_activityMenu; - /** - * Menu to add the group to other group. - */ - QMenu* m_addTabsMenu; - /** - * Menu to change tab. - */ - QMenu* m_switchToTabMenu; /** * Menu for further entries added by scripts. */ @@ -264,14 +232,6 @@ QAction* m_minimizeOperation; QAction* m_closeOperation; QAction* m_shortcutOperation; - /** - * Remove client from group. - */ - QAction* m_removeFromTabGroup; - /** - * Close all clients in the group. - */ - QAction* m_closeTabGroup; /** * The Client for which the menu is shown. */ diff --git a/useractions.cpp b/useractions.cpp --- a/useractions.cpp +++ b/useractions.cpp @@ -81,8 +81,6 @@ , m_desktopMenu(NULL) , m_screenMenu(NULL) , m_activityMenu(NULL) - , m_addTabsMenu(NULL) - , m_switchToTabMenu(NULL) , m_scriptsMenu(NULL) , m_resizeOperation(NULL) , m_moveOperation(NULL) @@ -94,8 +92,6 @@ , m_noBorderOperation(NULL) , m_minimizeOperation(NULL) , m_closeOperation(NULL) - , m_removeFromTabGroup(NULL) - , m_closeTabGroup(NULL) { } @@ -376,22 +372,6 @@ m_menu->addSeparator(); - // Actions for window tabbing - if (false) { - m_removeFromTabGroup = m_menu->addAction(i18n("&Untab")); - setShortcut(m_removeFromTabGroup, QStringLiteral("Untab")); - m_removeFromTabGroup->setData(Options::RemoveTabFromGroupOp); - - m_closeTabGroup = m_menu->addAction(i18n("Close Entire &Group")); - m_closeTabGroup->setIcon(QIcon::fromTheme(QStringLiteral("window-close"))); - setShortcut(m_closeTabGroup, QStringLiteral("Close TabGroup")); - m_closeTabGroup->setData(Options::CloseTabGroupOp); - - m_menu->addSeparator(); - } - - m_menu->addSeparator(); - action = m_menu->addMenu(advancedMenu); action->setText(i18n("&More Actions")); @@ -411,8 +391,6 @@ m_multipleDesktopsMenu = nullptr; m_screenMenu = NULL; m_activityMenu = NULL; - m_switchToTabMenu = NULL; - m_addTabsMenu = NULL; m_scriptsMenu = NULL; } @@ -453,17 +431,9 @@ m_closeOperation->setEnabled(m_client->isCloseable()); m_shortcutOperation->setEnabled(m_client->rules()->checkShortcut(QString()).isNull()); - if (false) { - initTabbingPopups(); - m_addTabsMenu->setPalette(m_client->palette()); - } else { - delete m_addTabsMenu; - m_addTabsMenu = 0; - } - // drop the existing scripts menu delete m_scriptsMenu; - m_scriptsMenu = NULL; + m_scriptsMenu = nullptr; // ask scripts whether they want to add entries for the given Client QList scriptActions = Scripting::self()->actionsForUserActionMenu(m_client.data(), m_scriptsMenu); if (!scriptActions.isEmpty()) { @@ -500,118 +470,14 @@ #endif } -void UserActionsMenu::selectPopupClientTab(QAction* action) -{ - if (!m_client || !m_client->tabGroup() || !action->data().isValid()) { - return; - } - - if (AbstractClient *other = action->data().value()) { - m_client->tabGroup()->setCurrent(other); - return; - } - - // failed conversion, try "1" & "2", being prev and next - int direction = action->data().toInt(); - if (direction == 1) { - m_client->tabGroup()->activatePrev(); - } else if (direction == 2) { - m_client->tabGroup()->activateNext(); - } -} - static QString shortCaption(const QString &s) { if (s.length() < 64) return s; QString ss = s; return ss.replace(32,s.length()-64, QStringLiteral("...")); } -void UserActionsMenu::rebuildTabListPopup() -{ - Q_ASSERT(m_switchToTabMenu); - - m_switchToTabMenu->clear(); - // whatever happens "0x1" and "0x2" are no heap positions ;-) - m_switchToTabMenu->addAction(i18nc("Switch to tab -> Previous", "Previous"))->setData(1); - m_switchToTabMenu->addAction(i18nc("Switch to tab -> Next", "Next"))->setData(2); - - m_switchToTabMenu->addSeparator(); - - if (!m_client) { - return; - } - for (auto i = m_client->tabGroup()->clients().constBegin(), - end = m_client->tabGroup()->clients().constEnd(); i != end; ++i) { - if ((*i)->noBorder() || *i == m_client->tabGroup()->current()) - continue; // cannot tab there anyway - m_switchToTabMenu->addAction(shortCaption((*i)->caption()))->setData(QVariant::fromValue(*i)); - } -} - -void UserActionsMenu::entabPopupClient(QAction* action) -{ - if (m_client.isNull() || !action->data().isValid()) { - return; - } - AbstractClient *other = action->data().value(); - if (!Workspace::self()->allClientList().contains(other)) { // might have been lost betwenn pop-up and selection - return; - } - - m_client->tabBehind(other, true); - if (options->focusPolicyIsReasonable()) { - Workspace::self()->requestFocus(m_client); - } -} - -void UserActionsMenu::rebuildTabGroupPopup() -{ - Q_ASSERT(m_addTabsMenu); - - m_addTabsMenu->clear(); - const auto &clientList = Workspace::self()->allClientList(); - for (auto i = clientList.constBegin(), end = clientList.constEnd(); i != end; ++i) { - if (*i == m_client.data() || (*i)->noBorder()) - continue; - m_addTabsMenu->addAction(shortCaption((*i)->caption()))->setData(QVariant::fromValue(*i)); - } - if (m_addTabsMenu->actions().isEmpty()) - m_addTabsMenu->addAction(i18nc("There's no window available to be attached as tab to this one", "None available"))->setEnabled(false); -} - -void UserActionsMenu::initTabbingPopups() -{ - bool needTabManagers = false; - Q_ASSERT(m_client); - if (!m_client) - return; - if (m_client->tabGroup() && m_client->tabGroup()->count() > 1) { - needTabManagers = true; - if (!m_switchToTabMenu) { - m_switchToTabMenu = new QMenu(i18n("Switch to Tab"), m_menu); - connect(m_switchToTabMenu, &QMenu::triggered, this, &UserActionsMenu::selectPopupClientTab); - connect(m_switchToTabMenu, &QMenu::aboutToShow, this, &UserActionsMenu::rebuildTabListPopup); - m_menu->insertMenu(m_removeFromTabGroup, m_switchToTabMenu); - } - } else { - delete m_switchToTabMenu; - m_switchToTabMenu = 0; - } - - if (!m_addTabsMenu) { - m_addTabsMenu = new QMenu(i18n("&Attach as tab to"), m_menu); - connect(m_addTabsMenu, &QMenu::triggered, this, &UserActionsMenu::entabPopupClient); - connect(m_addTabsMenu, &QMenu::aboutToShow, this, &UserActionsMenu::rebuildTabGroupPopup); - m_menu->insertMenu(m_removeFromTabGroup, m_addTabsMenu); - } - - m_addTabsMenu->menuAction()->setEnabled(!m_client->isFullScreen()); - m_removeFromTabGroup->setVisible(needTabManagers); - m_closeTabGroup->setVisible(needTabManagers); -} - void UserActionsMenu::initDesktopPopup() { if (kwinApp()->operationMode() == Application::OperationModeWaylandOnly || @@ -1291,24 +1157,8 @@ case Options::LowerOp: lowerClient(c); break; - case Options::TabDragOp: // Handled by decoration itself case Options::NoOp: break; - case Options::RemoveTabFromGroupOp: - if (c->untab(c->geometry().translated(cascadeOffset(c))) && options->focusPolicyIsReasonable()) - takeActivity(c, ActivityFocus | ActivityRaise); - break; - case Options::ActivateNextTabOp: - if (c->tabGroup()) - c->tabGroup()->activateNext(); - break; - case Options::ActivatePreviousTabOp: - if (c->tabGroup()) - c->tabGroup()->activatePrev(); - break; - case Options::CloseTabGroupOp: - c->tabGroup()->closeAll(); - break; } } @@ -1330,9 +1180,6 @@ else if (button == Qt::RightButton) com = active ? options->commandActiveTitlebar3() : options->commandInactiveTitlebar3(); - // TODO: Complete the list - if (com == Options::MouseDragTab) - return Options::TabDragOp; if (com == Options::MouseOperationsMenu) return Options::OperationsOp; return Options::NoOp; @@ -1668,24 +1515,6 @@ } } -void Workspace::slotActivateNextTab() -{ - if (active_client && active_client->tabGroup()) - active_client->tabGroup()->activateNext(); -} - -void Workspace::slotActivatePrevTab() -{ - if (active_client && active_client->tabGroup()) - active_client->tabGroup()->activatePrev(); -} - -void Workspace::slotUntab() -{ - if (active_client) - active_client->untab(active_client->geometry().translated(cascadeOffset(active_client))); -} - /** * Kill Window feature, similar to xkill. */ @@ -1783,8 +1612,6 @@ } } if (switchTo) { - if (switchTo->tabGroup()) - switchTo = switchTo->tabGroup()->current(); activateClient(switchTo); } diff --git a/workspace.h b/workspace.h --- a/workspace.h +++ b/workspace.h @@ -455,10 +455,6 @@ void updateClientArea(); - void slotActivateNextTab(); // Slot to move left the active Client. - void slotActivatePrevTab(); // Slot to move right the active Client. - void slotUntab(); // Slot to remove the active client from its group. - private Q_SLOTS: void desktopResized(); void selectWmInputEventMask(); diff --git a/workspace.cpp b/workspace.cpp --- a/workspace.cpp +++ b/workspace.cpp @@ -677,8 +677,6 @@ m_userActionsMenu->close(); } - c->untab(QRect(), true); - if (client_keys_client == c) setupWindowShortcutDone(false); if (!c->shortcut().isEmpty()) { @@ -759,8 +757,7 @@ // TODO: What if Client's transiency/group changes? should this be called too? (I'm paranoid, am I not?) if (!options->isHideUtilityWindowsForInactive()) { for (ClientList::ConstIterator it = clients.constBegin(); it != clients.constEnd(); ++it) - if (!(*it)->tabGroup() || (*it)->tabGroup()->current() == *it) - (*it)->hideClient(false); + (*it)->hideClient(false); return; } const Group* group = nullptr;