From 2390024f69f82ba074a2292e22cb2b431ca6ec39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Wed, 28 Jan 2015 23:41:43 +0100 Subject: [PATCH 1/7] use xcb_time_current_time as setinputfocus default BUG: 343430 REVIEW: 122298 FIXED-IN: 5.2.1 --- xcbutils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcbutils.h b/xcbutils.h index 9a03134cf6..465cb0e770 100644 --- a/xcbutils.h +++ b/xcbutils.h @@ -1089,7 +1089,7 @@ public: void clear(); void setBackgroundPixmap(xcb_pixmap_t pixmap); void defineCursor(xcb_cursor_t cursor); - void focus(uint8_t revertTo = XCB_INPUT_FOCUS_POINTER_ROOT, xcb_timestamp_t time = xTime()); + void focus(uint8_t revertTo = XCB_INPUT_FOCUS_POINTER_ROOT, xcb_timestamp_t time = XCB_TIME_CURRENT_TIME); void selectInput(uint32_t events); void kill(); operator xcb_window_t() const; From e3768b43559fa179f497d5130c0108dd72acf266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Thu, 29 Jan 2015 00:14:47 +0100 Subject: [PATCH 2/7] updateFocusMousePosition() before some actions in particular artificial geometry updates that should not update the focus and are prone to a static cursor BUG: 343319 REVIEW: 122299 FIXED-IN: 5.2.1 --- geometry.cpp | 5 +++++ placement.cpp | 28 ++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/geometry.cpp b/geometry.cpp index 3bf8da29aa..198d12a30b 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -3126,6 +3126,11 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard) if (!isResizable() && maximizeMode() != MaximizeFull) return; + // this might move the window away from the cursor pos what will cause a leave event + // since this is not due to a cursor move and we didn't receive motion events in the active + // window, we need to udpate the focus mouse position here + workspace()->updateFocusMousePosition(Cursor::pos()); + GeometryUpdatesBlocker blocker(this); if (mode == QuickTileMaximize) { diff --git a/placement.cpp b/placement.cpp index c193657cf4..2f936f6d65 100644 --- a/placement.cpp +++ b/placement.cpp @@ -663,6 +663,11 @@ const char* Placement::policyToString(Policy policy) void Client::packTo(int left, int top) { + // this might move the window away from the cursor pos what will cause a leave event + // since this is not due to a cursor move and we didn't receive motion events in the active + // window, we need to udpate the focus mouse position here + workspace()->updateFocusMousePosition(Cursor::pos()); + const int oldScreen = screen(); move(left, top); if (screen() != oldScreen) { @@ -725,6 +730,11 @@ void Client::growHorizontal() geom.setRight(newright); } geom.setSize(adjustedSize(geom.size(), SizemodeFixedW)); + geom.setSize(adjustedSize(geom.size(), SizemodeFixedH)); + // this might move an inactive window under the cursor pos what will cause an enter event + // since this is not due to a cursor move and we didn't receive motion events in the active + // window, we need to udpate the focus mouse position here + workspace()->updateFocusMousePosition(Cursor::pos()); setGeometry(geom); } @@ -743,8 +753,13 @@ void Client::shrinkHorizontal() if (geom.width() <= 1) return; geom.setSize(adjustedSize(geom.size(), SizemodeFixedW)); - if (geom.width() > 20) + if (geom.width() > 20) { + // this might move the window away from the cursor pos what will cause a leave event + // since this is not due to a cursor move and we didn't receive motion events in the active + // window, we need to udpate the focus mouse position here + workspace()->updateFocusMousePosition(Cursor::pos()); setGeometry(geom); + } } void Workspace::slotWindowGrowVertical() @@ -768,6 +783,10 @@ void Client::growVertical() geom.setBottom(newbottom); } geom.setSize(adjustedSize(geom.size(), SizemodeFixedH)); + // this might move an inactive window under the cursor pos what will cause an enter event + // since this is not due to a cursor move and we didn't receive motion events in the active + // window, we need to udpate the focus mouse position here + workspace()->updateFocusMousePosition(Cursor::pos()); setGeometry(geom); } @@ -787,8 +806,13 @@ void Client::shrinkVertical() if (geom.height() <= 1) return; geom.setSize(adjustedSize(geom.size(), SizemodeFixedH)); - if (geom.height() > 20) + if (geom.height() > 20) { + // this might move the window away from the cursor pos what will cause a leave event + // since this is not due to a cursor move and we didn't receive motion events in the active + // window, we need to udpate the focus mouse position here + workspace()->updateFocusMousePosition(Cursor::pos()); setGeometry(geom); + } } From 49fa157f0f5c3d9d1743d3016d361a219675b775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Thu, 29 Jan 2015 00:51:14 +0100 Subject: [PATCH 3/7] do not wrap text in deco button drag source The text cannot be aligned to the icon (makes it move around when dragging the icon) nor can we just allocate two line (makes single lines detached from the icon) BUG: 343411 REVIEW: 122301 FIXED-IN: 5.2.1 --- kcmkwin/kwindecoration/qml/Buttons.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kcmkwin/kwindecoration/qml/Buttons.qml b/kcmkwin/kwindecoration/qml/Buttons.qml index a8e1c96181..7c6997c330 100644 --- a/kcmkwin/kwindecoration/qml/Buttons.qml +++ b/kcmkwin/kwindecoration/qml/Buttons.qml @@ -169,7 +169,7 @@ Item { anchors.left: parent.left anchors.right: parent.right elide: Text.ElideRight - wrapMode: Text.Wrap + wrapMode: Text.NoWrap } MouseArea { id: dragArea From 4f7edb8d74675936e9b970c33e9576f571f84f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Tue, 3 Feb 2015 16:35:19 +0100 Subject: [PATCH 4/7] Rules: make WindowRole matching case sensitive required by KWindowInfo forwarding BUG: 343709 FIXED-IN: 5.2.1 REVIEW: 122407 --- rules.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules.cpp b/rules.cpp index d07a70f314..97abd30f18 100644 --- a/rules.cpp +++ b/rules.cpp @@ -141,7 +141,7 @@ void Rules::readFromCfg(const KConfigGroup& cfg) description = cfg.readEntry("description"); READ_MATCH_STRING(wmclass, .toLower().toLatin1()); wmclasscomplete = cfg.readEntry("wmclasscomplete" , false); - READ_MATCH_STRING(windowrole, .toLower().toLatin1()); + READ_MATCH_STRING(windowrole, .toLatin1()); READ_MATCH_STRING(title,); READ_MATCH_STRING(clientmachine, .toLower().toLatin1()); types = NET::WindowTypeMask(cfg.readEntry("types", NET::AllTypesMask)); From fa1368cb9ec740f5f6fe52dbc620997adbfa7a22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Tue, 3 Feb 2015 22:59:07 +0100 Subject: [PATCH 5/7] correctly handle virtual desktop on packing copy approach from smart placement REVIEW: 122417 --- placement.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/placement.cpp b/placement.cpp index 2f936f6d65..b8543607b4 100644 --- a/placement.cpp +++ b/placement.cpp @@ -879,8 +879,9 @@ int Workspace::packPositionLeft(const Client* cl, int oldx, bool left_edge) cons } if (oldx <= newx) return oldx; + const int desktop = cl->desktop() == 0 || cl->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : cl->desktop(); for (ClientList::ConstIterator it = clients.constBegin(), end = clients.constEnd(); it != end; ++it) { - if (isIrrelevant(*it, cl, cl->desktop())) + if (isIrrelevant(*it, cl, desktop)) continue; int x = left_edge ? (*it)->geometry().right() + 1 : (*it)->geometry().left() - 1; if (x > newx && x < oldx @@ -906,8 +907,9 @@ int Workspace::packPositionRight(const Client* cl, int oldx, bool right_edge) co } if (oldx >= newx) return oldx; + const int desktop = cl->desktop() == 0 || cl->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : cl->desktop(); for (ClientList::ConstIterator it = clients.constBegin(), end = clients.constEnd(); it != end; ++it) { - if (isIrrelevant(*it, cl, cl->desktop())) + if (isIrrelevant(*it, cl, desktop)) continue; int x = right_edge ? (*it)->geometry().left() - 1 : (*it)->geometry().right() + 1; if (x < newx && x > oldx @@ -933,8 +935,9 @@ int Workspace::packPositionUp(const Client* cl, int oldy, bool top_edge) const } if (oldy <= newy) return oldy; + const int desktop = cl->desktop() == 0 || cl->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : cl->desktop(); for (ClientList::ConstIterator it = clients.constBegin(), end = clients.constEnd(); it != end; ++it) { - if (isIrrelevant(*it, cl, cl->desktop())) + if (isIrrelevant(*it, cl, desktop)) continue; int y = top_edge ? (*it)->geometry().bottom() + 1 : (*it)->geometry().top() - 1; if (y > newy && y < oldy @@ -960,8 +963,9 @@ int Workspace::packPositionDown(const Client* cl, int oldy, bool bottom_edge) co } if (oldy >= newy) return oldy; + const int desktop = cl->desktop() == 0 || cl->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : cl->desktop(); for (ClientList::ConstIterator it = clients.constBegin(), end = clients.constEnd(); it != end; ++it) { - if (isIrrelevant(*it, cl, cl->desktop())) + if (isIrrelevant(*it, cl, desktop)) continue; int y = bottom_edge ? (*it)->geometry().top() - 1 : (*it)->geometry().bottom() + 1; if (y < newy && y > oldy From 92aa2fb553184c708b8b696fd3ea4b58ec73ce7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Wed, 4 Feb 2015 00:50:17 +0100 Subject: [PATCH 6/7] save geom_restore before calling for border update otherwise the stored geometry would be correct for maximized borders, thus the unmaximized borders make the window to small on unmaximizing BUG: 343691 FIXED-IN: 5.2.1 REVIEW: 122416 --- geometry.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/geometry.cpp b/geometry.cpp index 198d12a30b..3850110e04 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -2202,22 +2202,6 @@ void Client::changeMaximize(bool vertical, bool horizontal, bool adjust) changeMaximize(false, false, false); // restore } - // call into decoration update borders - if (m_decoration && m_decoration->client() && !(options->borderlessMaximizedWindows() && max_mode == KWin::MaximizeFull)) { - changeMaximizeRecursion = true; - const auto c = m_decoration->client().data(); - if ((max_mode & MaximizeVertical) != (old_mode & MaximizeVertical)) { - emit c->maximizedVerticallyChanged(max_mode & MaximizeVertical); - } - if ((max_mode & MaximizeHorizontal) != (old_mode & MaximizeHorizontal)) { - emit c->maximizedHorizontallyChanged(max_mode & MaximizeHorizontal); - } - if ((max_mode == MaximizeFull) != (old_mode == MaximizeFull)) { - emit c->maximizedChanged(max_mode & MaximizeFull); - } - changeMaximizeRecursion = false; - } - // save sizes for restoring, if maximalizing QSize sz; if (isShade()) @@ -2236,6 +2220,22 @@ void Client::changeMaximize(bool vertical, bool horizontal, bool adjust) } } + // call into decoration update borders + if (m_decoration && m_decoration->client() && !(options->borderlessMaximizedWindows() && max_mode == KWin::MaximizeFull)) { + changeMaximizeRecursion = true; + const auto c = m_decoration->client().data(); + if ((max_mode & MaximizeVertical) != (old_mode & MaximizeVertical)) { + emit c->maximizedVerticallyChanged(max_mode & MaximizeVertical); + } + if ((max_mode & MaximizeHorizontal) != (old_mode & MaximizeHorizontal)) { + emit c->maximizedHorizontallyChanged(max_mode & MaximizeHorizontal); + } + if ((max_mode == MaximizeFull) != (old_mode == MaximizeFull)) { + emit c->maximizedChanged(max_mode & MaximizeFull); + } + changeMaximizeRecursion = false; + } + if (options->borderlessMaximizedWindows()) { // triggers a maximize change. // The next setNoBorder interation will exit since there's no change but the first recursion pullutes the restore geometry From ff700a8db58b66dc3a28ceb39fe4b5e3edaa7e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Thu, 29 Jan 2015 00:14:47 +0100 Subject: [PATCH 7/7] fix e3768b43559fa179f497d5130c0108dd72acf266 accidentally picked the patch from the wrong branch just about comments --- events.cpp | 2 +- geometry.cpp | 7 ++----- placement.cpp | 25 +++++-------------------- workspace.h | 8 ++++++++ 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/events.cpp b/events.cpp index 05aaddca6f..8ce51e763f 100644 --- a/events.cpp +++ b/events.cpp @@ -1599,7 +1599,7 @@ bool Unmanaged::windowEvent(xcb_generic_event_t *e) release(ReleaseReason::Destroyed); break; case XCB_UNMAP_NOTIFY:{ - workspace()->updateFocusMousePosition(Cursor::pos()); + workspace()->updateFocusMousePosition(Cursor::pos()); // may cause leave event // unmap notify might have been emitted due to a destroy notify // but unmap notify gets emitted before the destroy notify, nevertheless at this diff --git a/geometry.cpp b/geometry.cpp index 3850110e04..94daf199f8 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -2405,7 +2405,7 @@ void Client::setFullScreen(bool set, bool user) setShade(ShadeNone); bool was_fs = isFullScreen(); if (was_fs) - workspace()->updateFocusMousePosition(Cursor::pos()); + workspace()->updateFocusMousePosition(Cursor::pos()); // may cause leave event else geom_fs_restore = geometry(); fullscreen_mode = set ? FullScreenNormal : FullScreenNone; @@ -3126,10 +3126,7 @@ void Client::setQuickTileMode(QuickTileMode mode, bool keyboard) if (!isResizable() && maximizeMode() != MaximizeFull) return; - // this might move the window away from the cursor pos what will cause a leave event - // since this is not due to a cursor move and we didn't receive motion events in the active - // window, we need to udpate the focus mouse position here - workspace()->updateFocusMousePosition(Cursor::pos()); + workspace()->updateFocusMousePosition(Cursor::pos()); // may cause leave event GeometryUpdatesBlocker blocker(this); diff --git a/placement.cpp b/placement.cpp index b8543607b4..906b282b62 100644 --- a/placement.cpp +++ b/placement.cpp @@ -663,10 +663,7 @@ const char* Placement::policyToString(Policy policy) void Client::packTo(int left, int top) { - // this might move the window away from the cursor pos what will cause a leave event - // since this is not due to a cursor move and we didn't receive motion events in the active - // window, we need to udpate the focus mouse position here - workspace()->updateFocusMousePosition(Cursor::pos()); + workspace()->updateFocusMousePosition(Cursor::pos()); // may cause leave event; const int oldScreen = screen(); move(left, top); @@ -731,10 +728,7 @@ void Client::growHorizontal() } geom.setSize(adjustedSize(geom.size(), SizemodeFixedW)); geom.setSize(adjustedSize(geom.size(), SizemodeFixedH)); - // this might move an inactive window under the cursor pos what will cause an enter event - // since this is not due to a cursor move and we didn't receive motion events in the active - // window, we need to udpate the focus mouse position here - workspace()->updateFocusMousePosition(Cursor::pos()); + workspace()->updateFocusMousePosition(Cursor::pos()); // may cause leave event; setGeometry(geom); } @@ -754,10 +748,7 @@ void Client::shrinkHorizontal() return; geom.setSize(adjustedSize(geom.size(), SizemodeFixedW)); if (geom.width() > 20) { - // this might move the window away from the cursor pos what will cause a leave event - // since this is not due to a cursor move and we didn't receive motion events in the active - // window, we need to udpate the focus mouse position here - workspace()->updateFocusMousePosition(Cursor::pos()); + workspace()->updateFocusMousePosition(Cursor::pos()); // may cause leave event; setGeometry(geom); } } @@ -783,10 +774,7 @@ void Client::growVertical() geom.setBottom(newbottom); } geom.setSize(adjustedSize(geom.size(), SizemodeFixedH)); - // this might move an inactive window under the cursor pos what will cause an enter event - // since this is not due to a cursor move and we didn't receive motion events in the active - // window, we need to udpate the focus mouse position here - workspace()->updateFocusMousePosition(Cursor::pos()); + workspace()->updateFocusMousePosition(Cursor::pos()); // may cause leave event; setGeometry(geom); } @@ -807,10 +795,7 @@ void Client::shrinkVertical() return; geom.setSize(adjustedSize(geom.size(), SizemodeFixedH)); if (geom.height() > 20) { - // this might move the window away from the cursor pos what will cause a leave event - // since this is not due to a cursor move and we didn't receive motion events in the active - // window, we need to udpate the focus mouse position here - workspace()->updateFocusMousePosition(Cursor::pos()); + workspace()->updateFocusMousePosition(Cursor::pos()); // may cause leave event; setGeometry(geom); } } diff --git a/workspace.h b/workspace.h index 249cf36bb0..bccc1c1fe3 100644 --- a/workspace.h +++ b/workspace.h @@ -314,6 +314,14 @@ public: void cancelDelayFocus(); void requestDelayFocus(Client*); + + /** + * updates the mouse position to track whether a focus follow mouse focus change was caused by + * an actual mouse move + * is esp. called on enter/motion events of inactive windows + * since an active window doesn't receive mouse events, it must also be invoked if a (potentially) + * active window might be moved/resize away from the cursor (causing a leave event) + */ void updateFocusMousePosition(const QPoint& pos); QPoint focusMousePosition() const;