Registered Member
|
Hello,
I'm working on a project developped using Qt 5.3 under KDE and Kwin. We have a widget on which we remove the decoration, but we still want the user to be able to drag the widget around by pressing and moving the mouse on it (meaning without using Alt+click). To achieve that, we have reimplemented events methods of QWidget to process mouse events (like button press, button release or mouse move), and accordingly move the widget around. It used to work well under Kwin 3.0 (KDE 3.3.0-5, Qt3.3), but we've since changed the system to a more recent one (using KDE 4.14.3 and Kwin 4.11.14) and we've noticed that a window without decoration cannot be moved outside of the screen unless with Alt+click. This is a problem for us because the user needs to be able to move that window at the right border of the screen (meaning most of the window should be outside of the screen). We've tried using MWM instead of Kwin and we could not reprocuce the problem so we've assumed Kwin was restricting the window to the screen (probably to make sure the user doesn't lose a window by mistake I suppose). Is there a flag we should add to the window in Qt ? Our project is an entire system and we can even control its configuration, so is there a configuration variable we could change to get the same behavior as before (in kwinrc or kwinrulesrc maybe) ? I've been looking for an issue similar to this one, and so far the only one I could find was this one viewtopic.php?f=305&t=34410 from 2009, and I'm not sure how the solution could be applied in our case. Thank your for your help |
|
Don't. Seriously, it's wrong. This is proper Xlib code, ask if you need xcb code.
If you would insist on doing what you do at the moment (repeat after me: "it is wrong!"), you'll have to either a) hint the "NET::FromTool" flag (KWindowSystem has a convenience function to to this, otherwise you'd have to build anX11 configure request) b) ensure your window is of dock type (Qt "docks" are /not/ - this refers to panels) - most other and notably all "normal" windows are not permitted to move themselves out of screen bounds. I'm not 100% sure but think to recall that this has not been different in KDE3 (I think I asked Lubos back then because I wanted to move a window off-screen, though w/o the user interacting) Again: what you do is wrong and terribly inefficient. Just don't |
Registered Member
|
I'm not sure I understand why you believe it's wrong , aren't QWidget protected events methods meant to be reimplemented in subclasses ?
When I say moving window outside of the screen, I mean being able to drag the window until the cursor hits the boundaries of the screen (at which point part of the window is outside the screen, but some of it is still visible). Currently, frameless windows collide with the boundary of the screen, before the cursor itself collides with it. I'm not trying to move a window completely out of the screen (which I admit seems very wrong), just allow my frameless window to be dragged at the border of the screen without colliding as soon as one of its border hits the border of the screen, like any other decorated window. For information, the user can only drag the window when he clicks in a specific region of the widget/window. I don't know if I make sense, and I'm sorry if I don't Here is a small example that reproduces our problem :
|
|
I know what you want to do. It's not "wrong" codewise, but the approach is.
You instead want to tell the WM "please start moving around this window", what a) tells the WM that a user is acting now, whatever he wants is ok (so no need to perform sanity checks) b) makes the WM aware of the ungoing process (allowing such things as wobbly windows, snapping, quicktiling etc.) c) spares you a hell lot of roundtrips. Currently the server need to sync all clients with every pixel you drag the window, leaving aside the communication overhead. And if you're using the composited mode, KWin won't even actually move the window (yet another roundtrip) until the user is done, but only reposition the texture in the compositors scene (that's for free) d) avoids Qt event translation and compression (on slow systems, moving might otherwise lag behind the mouse) So when you want to start the window being moved, you just signal the code snippet *once*, from that moment on the WM will move the window as if you had pressed Alt+LMB. Client side moving is only required if there is no window manager (or the window is override_redirect, but then neither will appear in Alt+Tab or the taskbar, but instead be on top of everything) |
Registered Member
|
I think I'm starting to understand what you mean.
The thing is, we don't directly discuss with the WM, we only work with Qt and we try to keep it that way. We may have a few files that do xcb related stuff but we want to try to keep it to a minimum. We've been looking for a way to do this through Qt. I'm assuming the QWidget::move method does not bypass the WM, but you're telling me I should instead instruct Qt to notify the WM that we are initiating a move and only when we are done moving, instruct Qt to notify the WM of the move, is that right ? I'm sorry if I'm being annoying but I'm not entirely familiar with the way X11, Qt and the WM work together. If so, as a side question, should we avoid ever moving a QWidget using the method move ? Or is it fine as long as we are not dragging it (and thus asking multiple times and in a short period to move the window) ? |
|
If you want to restrict to Qt, you'll have to move the window by configure events (moving the widget) - and live with all drawbacks.
As long as the window is managed, Qt will use configure requests for this and those are *requests* to the WM; whatever that does in return (in this case constraining the window to the workarea) is undefined: http://www.x.org/releases/X11R7.6/doc/x ... icccm.html
As an alternative, you can explicitly except the window from being managed by passing Qt::BypassWindowManagerHint to the constructor. As mentioned this implies that the window is not part of the regular window stack (but above everything) nor focus chain. It will not be activated by the WM when eg. clicking it etc. Any other solution will require patches to Qt or diving into X11 code (though we could abstract this in KWindowSystem) |
Registered Member
|
We tried using the ByPassWindowManagerHint and it had several side effects that we don't want.
We are going to try out a few things, and I'll come back to give you our results, and hopefully accept your answers Thank you for your help |
|
In case you're using KF5 in addition to Qt, feel free to ask for an abstraction of the feature in KWindowSystem (sth. like "KWindowSystem::initiateMove(window()->winId());")
|
Registered Member
|
We got it working by sending NET_WM_MOVERESIZE events through xcb, the same way you posted it with Xlib, and the way kruler works.
We still have a small issue to fix but it seems to be working the way we want it to. Thank you again for your help |
Registered users: bartoloni, Bing [Bot], Evergrowing, Google [Bot], ourcraft