Bug 356523 - Hide/restore window from system tray cause change it position
Summary: Hide/restore window from system tray cause change it position
Status: RESOLVED FIXED
Alias: None
Product: frameworks-knotifications
Classification: Frameworks and Libraries
Component: general (show other bugs)
Version: 5.5.0
Platform: Arch Linux Linux
: NOR normal
Target Milestone: ---
Assignee: Martin Klapetek
URL:
Keywords:
: 360826 360948 360949 372056 (view as bug list)
Depends on:
Blocks:
 
Reported: 2015-12-11 17:20 UTC by Anthony Fieroni
Modified: 2016-12-18 09:57 UTC (History)
5 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Anthony Fieroni 2015-12-11 17:20:20 UTC
Hide window on who is on position top left, after restore it is shown downside and so on. When it's on bottom left it start "move" on right

Reproducible: Always

Steps to Reproduce:
1. Hide window by click on item in systray
2. Restore it
3. It's position is lower

Actual Results:  
Last window posistion is not saved correctly.

Expected Results:  
Restore on las posistion
Comment 1 Thomas Lübking 2015-12-11 17:24:20 UTC
Systray != Taskbar.

The window is destroyed and a new window is created by the client. It has no former position brand new window.

The client would have to apply the geometry of the old window to the new one - and it looks like it's doing that wrongly, likely messing with the decorated geometry.

Which client in particular?
Comment 2 Anthony Fieroni 2015-12-11 18:23:37 UTC
All apps in systray do it wrong? I don't believe that.
Comment 3 Anthony Fieroni 2015-12-11 19:14:46 UTC
http://tinypic.com/player.php?v=6z08sg%3E&s=9
If not KWin redirect bug to kf, but cannot all clients to have same bugs 'magically'
Comment 4 Thomas Lübking 2015-12-11 19:17:09 UTC
it does completely not matter what you "believe" and you did not specify "all".

the clients destroy and create new windows and demand a new position when closed to the systray, that is fundamentally different from minimize/restore)

i will check whether kwin systematically sets off the position (walking windows bug again?, because when adding the decoration), but the window would then immediately walk downright. not down, then right.

please log the output of "qdbus org.kde.KWin /KWin supportInformation" so we can see your deco config.
Comment 5 Thomas Lübking 2015-12-11 21:05:52 UTC
Both walking window tests pass. It's not kwin.

=> Please provide a complete list of clients where this happens otherwise I won't be able to look what's going on.
Comment 6 Anthony Fieroni 2015-12-12 03:40:12 UTC
Definitly not all, my fault. Kmail, akregator, amarok
Comment 7 Thomas Lübking 2015-12-12 10:20:10 UTC
No problem, we get "systray does not restore position" bugreports twice a year and it's always the client (so I simply close them - usually it's dropbox or skype ;-)

The bug is in

void KStatusNotifierItemPrivate::minimizeRestore(bool show)
   ...
   associatedWidget->move(info.frameGeometry().topLeft()); // avoid placement policies

=> the client is supposed to be placed at the client position, not at the decorated position. The WM needs to add the decoration and keep the decorated client where it is (if this is possible by other constraints)

=> Please move the client to where it is or simply set the Qt::WA_Moved flag (latter should be sufficient, but the Qt5 surface abstraction might have screwed it, didn't recently test)
Comment 8 Martin Klapetek 2015-12-14 17:06:07 UTC
So

-        associatedWidget->move(info.frameGeometry().topLeft()); // avoid placement policies
+        associatedWidget->move(info.geometry().topLeft()); // avoid placement policies

?
Comment 9 Anthony Fieroni 2016-01-04 17:23:46 UTC
Correct it for 5.18, please.
Comment 10 Martin Klapetek 2016-01-04 17:52:43 UTC
5.18 is already released, 5.19 would be the earliest.

@Thomas, is comment #8 all that is needed?
Comment 11 Thomas Lübking 2016-01-04 18:21:18 UTC
i don't recall the code, but if the wininfo isn't required otherwise, you can omit it.
the widget should still have the proper geometry and Qt::WA_Moved will (hopefully still) make Qt ask the WM to not move it elsewhere.

in either case qwidget still has the proper geometry.

sorry for forgetting to keep myself attached :-(
Comment 12 Thomas Lübking 2016-01-05 11:22:37 UTC
Actually™ you should not have to explicitly set the current geometry, QWidget::show() should do that automagically if the widget was ever moved (by the client code or the user) - also works for me (but *not* tested on KNotifications explicitly)
Comment 13 Anthony Fieroni 2016-01-27 07:35:56 UTC
Any results here?
Comment 14 Martin Klapetek 2016-01-27 17:22:51 UTC
> Any results here?

No.

@Thomas
> Actually™ you should not have to explicitly set the current geometry

I did some testing - if I remove this call completely, the placement is
fully random from what I can tell. if I simply replace info.frameGeometry().topLeft()
with info.topLeft(), it still gets restored to a different position. Apparently
this is to some extent due to having QT_DEVICE_PIXEL_RATIO=2 as the
widget geometry is exactly half of what KWindowInfo reports, therefore
simply telling the QWidget to move to KWindowInfo geometry moves
it twice as much.

But not just that, I've tried something like

        associatedWidget->move(info.geometry().topLeft().x() / 2, info.geometry().topLeft().y() / 2);

but it would still restore it by some random pixels off.

What does, however, seems to restore it properly is this:

        associatedWidget->windowHandle()->setX(info.geometry().topLeft().x() /2);
        associatedWidget->windowHandle()->setY(info.geometry().topLeft().y() /2);

...where the "/2" should obviously be replaced by QT_DEVICE_PIXEL_RATIO.

But now tell me if this is a good and/or valid fix.
Comment 15 Thomas Lübking 2016-01-27 17:33:27 UTC
What if you explicity
  associatedWidget->setAttribute(Qt::WA_Moved);

(the individual sets will likely cause this whereas the combined one will figure it's no effective change and shortcut exit)

The QT_DEVICE_PIXEL_RATIO situation is kinda worrysome.
KWindowSystem deals with real pixels (and I doubt we can just change that, we don't know the source of the calculation), so either this is the expected behavior for toplevel widget actions or a bug in Qt (while it makes absolutely sense for internal widgets, global positioning is usually driven by outside values which do not related to the locals environment)
Comment 16 Martin Klapetek 2016-01-27 17:40:47 UTC
>   associatedWidget->setAttribute(Qt::WA_Moved);

Should just this be in or with some of the other lines? This standalone
puts it always to the bottom-left corner of my screen.

> KWindowSystem deals with real pixels

Yeah which means that the widget either needs to be move to real pixels
(ie. apply the device pixel ratio) or the window needs to be moved externally
by something else.
Comment 17 Thomas Lübking 2016-01-27 17:49:09 UTC
This alone should do (and not even be required), but I guess there there's more to it in the SNI case, like the widget being destroyed and recreated (so you've not moved this widget at all, but just told the WM to believe so)

In the latter case you could either carry over the last position (and move it in QWidget geometries, sth. like ie.

oldPosition = oldWidget->pos();
....
QWidget *newWidget = new QWidget;
newWidget->move(oldPosition);
newWidget->show();


---

"Something else™" cannot move the widget as eg. the WM doesn't know that this window has been there before (or that it should restore that former geometry)
Comment 18 Anthony Fieroni 2016-01-27 19:17:48 UTC
How this works correctly before 5.15?
Comment 19 Martin Klapetek 2016-01-27 19:28:12 UTC
That's very likely some unrelated change, this code hasn't been altered for ages.
Comment 20 Thomas Lübking 2016-01-27 20:13:27 UTC
Either the window was undecorated or the call to the wininfo was made before it was decorated by the WM (in either case frameGeometry() and geometry() are equal)

Why there's this complex code, also preserving the current desktop, is frankly beyond me - QWidget::hide() withdraws the X drawable, but doesn't destroy it - so properties like the VD and the geometry should be preserved; QWidget::hide() / QWidget::show() should™ really just work.

The only thing I could imagine is that the client code in addition nukes the widget (destroying the drawable) and adds a new associate (w/o caring about former properties) - however then also the X properties (KWinInfo geometry) should be nonsense...

My uninformed suggestion was to explicitly store the position QWidget::pos() like the virtual desktop and restore to that QPoint *shrug*
Comment 21 David Edmundson 2016-03-28 23:55:50 UTC
*** Bug 360826 has been marked as a duplicate of this bug. ***
Comment 22 David Edmundson 2016-03-28 23:55:56 UTC
*** Bug 360948 has been marked as a duplicate of this bug. ***
Comment 23 David Edmundson 2016-03-28 23:56:03 UTC
*** Bug 360949 has been marked as a duplicate of this bug. ***
Comment 24 Anthony Fieroni 2016-12-03 06:50:47 UTC
Git commit 6198841710fb128987c308bd3ef3ff8cbd294ce0 by Anthony Fieroni.
Committed on 03/12/2016 at 06:50.
Pushed by anthonyfieroni into branch 'master'.

[KStatusNotifierItem] Save / restore widget position during hide / restore it window

REVIEW: 127216

Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>

M  +24   -5    src/kstatusnotifieritem.cpp
M  +1    -0    src/kstatusnotifieritemprivate_p.h

https://commits.kde.org/knotifications/6198841710fb128987c308bd3ef3ff8cbd294ce0
Comment 25 Andrea Scarpino 2016-12-18 09:57:11 UTC
*** Bug 372056 has been marked as a duplicate of this bug. ***