diff --git a/geometry.cpp b/geometry.cpp index dbfb41d8c8..be64c69804 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -2535,7 +2535,8 @@ bool Client::startMoveResize() geom_restore = geometry(); // "restore" to current geometry setMaximize(false, false); } - } + } else if (quick_tile_mode != QuickTileNone) // no longer now - we move, resize is handled below + setQuickTileMode(QuickTileNone); // otherwise we mess every second tile, bug #303937 } else if ((maximizeMode() == MaximizeFull && options->electricBorderMaximize()) || (quick_tile_mode != QuickTileNone && isMovable() && mode == PositionCenter)) { // Exit quick tile mode when the user attempts to move a tiled window, cannot use isMove() yet diff --git a/kcmkwin/kwindecoration/decorationmodel.cpp b/kcmkwin/kwindecoration/decorationmodel.cpp index 3d3bb862f8..4915d10098 100644 --- a/kcmkwin/kwindecoration/decorationmodel.cpp +++ b/kcmkwin/kwindecoration/decorationmodel.cpp @@ -37,6 +37,18 @@ along with this program. If not, see . #include #include "kwindecoration.h" +/* WARNING ------------------------------------------------------------------------- +* it is *ABSOLUTELY* mandatory to manage loadPlugin() and destroyPreviousPlugin() +* using disablePreview() +* +* loadPlugin() moves the present factory pointer to "old_fact" which is then deleted +* by the succeeding destroyPreviousPlugin() +* +* So if you loaded a new plugin and that changed the current factory, call disablePreview() +* BEFORE the following destroyPreviousPlugin() destroys the factory for the current m_preview->deco->factory +* (which is invoked on deco deconstruction) +* WARNING ------------------------------------------------------------------------ */ + namespace KWin { @@ -192,10 +204,12 @@ QVariant DecorationModel::data(const QModelIndex& index, int role) const return static_cast< int >(m_decorations[ index.row()].borderSize); case BorderSizesRole: { QList< QVariant > sizes; - if (m_plugins->loadPlugin(m_decorations[ index.row()].libraryName) && - m_plugins->factory() != NULL) { + const bool mustDisablePreview = m_plugins->factory() && m_plugins->factory() == m_preview->factory(); + if (m_plugins->loadPlugin(m_decorations[index.row()].libraryName) && m_plugins->factory()) { foreach (KDecorationDefines::BorderSize size, m_plugins->factory()->borderSizes()) // krazy:exclude=foreach sizes << int(size); + if (mustDisablePreview) // it's nuked with destroyPreviousPlugin() + m_preview->disablePreview(); // so we need to get rid of m_preview->deco first m_plugins->destroyPreviousPlugin(); } return sizes; @@ -312,6 +326,9 @@ void DecorationModel::regeneratePreview(const QModelIndex& index, const QSize& s document.setHtml(html); bool enabled = false; bool loaded; + // m_preview->deco management is not required + // either the deco loads and the following recreateDecoration will sanitize decos (on new factory) + // or the deco does not load and destroyPreviousPlugin() is not called if ((loaded = m_plugins->loadPlugin(data.libraryName)) && m_preview->recreateDecoration(m_plugins)) { enabled = true; m_preview->enablePreview(); diff --git a/kcmkwin/kwindecoration/preview.cpp b/kcmkwin/kwindecoration/preview.cpp index fe802c7345..587df7c5b7 100644 --- a/kcmkwin/kwindecoration/preview.cpp +++ b/kcmkwin/kwindecoration/preview.cpp @@ -103,6 +103,11 @@ void KDecorationPreview::disablePreview() no_preview->show(); } +KDecorationFactory *KDecorationPreview::factory() const +{ + return deco[Active] ? deco[Active]->factory() : 0; +} + void KDecorationPreview::paintEvent(QPaintEvent* e) { Q_UNUSED(e); diff --git a/kcmkwin/kwindecoration/preview.h b/kcmkwin/kwindecoration/preview.h index 20ee869f9b..52645fd767 100644 --- a/kcmkwin/kwindecoration/preview.h +++ b/kcmkwin/kwindecoration/preview.h @@ -50,6 +50,7 @@ public: bool recreateDecoration(KDecorationPlugins* plugin); void enablePreview(); void disablePreview(); + KDecorationFactory *factory() const; void setPreviewMask(const QRegion&, int, bool); QRegion unobscuredRegion(bool, const QRegion&) const; QRect windowGeometry(bool) const; diff --git a/tabgroup.cpp b/tabgroup.cpp index e7b133e8f1..771d789954 100644 --- a/tabgroup.cpp +++ b/tabgroup.cpp @@ -104,6 +104,15 @@ bool TabGroup::add(Client* c, Client *other, bool after, bool becomeVisible) 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()) @@ -114,7 +123,6 @@ bool TabGroup::add(Client* c, Client *other, bool after, bool becomeVisible) c->setTabGroup(this); // Let the client know which group it belongs to updateMinMaxSize(); - updateStates(m_current, All, c); if (!becomeVisible) c->setClientShown(false); @@ -292,6 +300,8 @@ void TabGroup::blockStateUpdates(bool more) { void TabGroup::updateStates(Client* main, States states, Client* only) { + if (main == only) + return; // there's no need to only align "us" to "us" if (m_stateUpdatesBlocked > 0) { m_pendingUpdates |= states; return; @@ -300,10 +310,16 @@ void TabGroup::updateStates(Client* main, States states, Client* only) states |= m_pendingUpdates; m_pendingUpdates = TabGroup::None; - ClientList toBeRemoved; - for (ClientList::const_iterator i = m_clients.constBegin(), end = m_clients.constEnd(); i != end; ++i) { + ClientList toBeRemoved, onlyDummy; + ClientList *list = &m_clients; + if (only) { + onlyDummy << only; + list = &onlyDummy; + } + + for (ClientList::const_iterator i = list->constBegin(), end = list->constEnd(); i != end; ++i) { Client *c = (*i); - if (c != main && (!only || c == only)) { + if (c != main) { if ((states & Minimized) && c->isMinimized() != main->isMinimized()) { if (main->isMinimized()) c->minimize(true);