Closed ivnvitx closed 4 years ago
Yes, this also how GTK does it client side. If you have lots of widgets in the decorations, dragging can become a huge problem unless you allow the user to drag from the widget.
Is this possible @Zren ?
First I'll need to get rid of the mousePressEvent
code that triggers mouseReleaseEvent
which is easy enough.
I don't think we can tell KDecoration to ignore the "press button", letting it fall through to the titlebar "move" unfortunately. There doesn't seem to be a "move" function anywhere in KDecoration either. So KWin is probably handling it.
There's a mouseMoveEvent
, which I think is only triggered when a mouse button is pressed.
virtual void hoverEnterEvent(QHoverEvent *event);
virtual void hoverLeaveEvent(QHoverEvent *event);
virtual void hoverMoveEvent(QHoverEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void wheelEvent(QWheelEvent *event);
We can use that with mousePressEvent
to get the distrance dragged, and if it goes over the threshold to somehow trigger the "move window" event.
https://doc.qt.io/qt-5/qstylehints.html#startDragDistance-prop
Breeze has a "SizeGrip" in the bottom right which manually sends a MoveResize
event to the xorg server. It sends direction=4
or _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
clientMessageEvent.response_type = XCB_CLIENT_MESSAGE;
clientMessageEvent.type = m_moveResizeAtom;
clientMessageEvent.format = 32;
clientMessageEvent.window = c->windowId();
clientMessageEvent.data.data32[0] = rootPosition.x();
clientMessageEvent.data.data32[1] = rootPosition.y();
clientMessageEvent.data.data32[2] = 4; // bottom right
clientMessageEvent.data.data32[3] = Qt::LeftButton;
clientMessageEvent.data.data32[4] = 0;
xcb_send_event( connection, false, QX11Info::appRootWindow(),
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
reinterpret_cast<const char*>(&clientMessageEvent) );
We can probably try _NET_WM_MOVERESIZE_MOVE
to send a Move only event. We can also look at what event the taskmanager widget sends when you right click a window > More Actions > Move.
#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
DecorationButton::mouseMoveEvent
doesn't seem to be triggered, event when isPressed() == true
. DecorationButton::hoverMoveEvent
is sent when it's true
and false
, so that's weird. I didn't check Decoration::mouseMoveEvent
. I'll probably need to use Decoration::mouseMoveEvent
in the long term so that:
Click the very edge of a AppMenu button then dragging. It should trigger the move event.
DecorationButton::hoverMoveEvent
may not detect this as each button has it's own pressedPoint
atm. I'll need to store pressedPoint
in the Decoration
object.
I've gotten it working, however I'm not able to reset the "pressed" state of the button, so there a visual and functional bug. The first button press to open a menu item will be gobbled up to set "pressed = false" of the previously dragged button.
Try the buttonmove
branch.
https://github.com/Zren/material-decoration/compare/master...buttonmove
I've found a workaround for button->setPressed(false)
by toggling button->setEnabled
twice.
Just tried this and it works just fine. Should we also apply this to other buttons like Close/Min/Max... ?
One issue could be improved is that the grabbing window should become the active one.
I deliberately limited the effect to just the appmenu with m_menuButtons->geometry().contains(event->pos())
to limit edge cases.
https://github.com/Zren/material-decoration/blob/master/src/Decoration.cc#L177
You can remove the if check if you want to try applying the affect to all buttons.
@Zren what about scroll and right-click events. I could see right-click-anywhere to maximize being useful here. As an added bonus, you can configure the same behavior in gtk CSD system-wide, so you could even get consistent wm behavior between CSD and SSD.
I personally think scroll up/down anywhere to maximize/restore is more natural though, so there is value in that as well, esp for people who don't care about gtk CSD.
The default Application Menu accepts Left and Right click to activate. I can definitely pass through Middle Button and wheel events though.
Tbh, I don't really care about enforcing a standard atm, I'll just pass through RightClick events too.
@Zren I have also a small question regarding this topic.
On Ubuntu, it is possible to call the menu item by pressing left mouse button (mouse-down event), select the entry by moving the cursor, and then select it by releasing the button (mouse-up action). The same behavior also applies in some KDE apps - for example context menus in Dolphin or on desktop behave this way, so it is possible to select some submenu entry within only one whole click event.
However, this trick doesn't work with material-decoration menu - if you press mouse button over one of the menu buttons, and then move cursor down (while keeping mouse button pressed), whole window is getting moved. Maybe it is possible somehow to make continuous selection work with material-decoration ? For example, open the menu on 'mouse-down' event instead of 'click' or 'mouse-up' can help in theory (just a thought).
Thanks.
How did unity differentiate a "mousedown+drag" to open a menu from a "mousedown+drag" to move a window?
I guess it works the way that when initial click was over empty space - "move window" action gets triggered on cursor move, and when it was over the menu button - then, the menu dropdown behavior I described above.
So basically menu bar should somehow consume mouse events to make it all work. Maybe event consuming will be handled by system itself, if the menu dropdown is opened immediately after 'mouse-down' event, instead of being opened only on releasing the mouse button (as it is in the current version)?
So you want it to never move the window when you press a menu item?
So you want an option that will:
initDragMove(event->pos());
in Decoration::mousePressEvent
AppMenuButton::pressed
signal to the AppMenuButton::clicked
signal.
Yes, sounds about right! But need to check somehow if these changes allow the behavior I was talking about. Just wanted to test it, but the last 2 links point to the Plasma sources?
Basically, somehow making the menu buttons behave as if they were not there when I click and drag, and so just move the window around. I do not know if this is possible, as there may be issues with the window manager or something (I really do not know much about this), but it would certainly take it to the next level, to the point where I could see this system become the standard. It is just too space-efficient. I love it.
Thanks for the work you are doing here. I hope it brings many people in to work it all out.