diff --git a/app/view/visibilitymanager.cpp b/app/view/visibilitymanager.cpp --- a/app/view/visibilitymanager.cpp +++ b/app/view/visibilitymanager.cpp @@ -1151,7 +1151,17 @@ //active window can be dragged only when it is in the same screen if (actInfo.isValid() && !actInfo.geometry().isNull() && m_latteView->screenGeometry().contains(actInfo.geometry().center())) { QPoint globalPoint{m_latteView->x() + localX, m_latteView->y() + localY}; + wm->requestMoveWindow(actInfo.wid(), globalPoint); + + //! This timer is needed because otherwise the mouse position + //! in the dragged window changes to TopLeft corner + QTimer::singleShot(250, this, [&, actInfo, globalPoint]() { + wm->releaseMouseEventFor(m_latteView->winId()); + }); + + setContainsMouse(false); + updateHiddenState(); } } diff --git a/app/wm/abstractwindowinterface.h b/app/wm/abstractwindowinterface.h --- a/app/wm/abstractwindowinterface.h +++ b/app/wm/abstractwindowinterface.h @@ -89,6 +89,7 @@ virtual void enableBlurBehind(QWindow &view) const = 0; virtual void setEdgeStateFor(QWindow *view, bool active) const = 0; + virtual void releaseMouseEventFor(WindowId wid) const = 0; virtual void requestToggleMaximized(WindowId wid) const = 0; virtual void requestMoveWindow(WindowId wid, QPoint from) const = 0; virtual bool windowCanBeDragged(WindowId wid) const = 0; diff --git a/app/wm/waylandinterface.h b/app/wm/waylandinterface.h --- a/app/wm/waylandinterface.h +++ b/app/wm/waylandinterface.h @@ -77,6 +77,7 @@ void slideWindow(QWindow &view, Slide location) const override; void enableBlurBehind(QWindow &view) const override; + void releaseMouseEventFor(WindowId wid) const override; void requestToggleMaximized(WindowId wid) const override; void requestMoveWindow(WindowId wid, QPoint from) const override; bool windowCanBeDragged(WindowId wid) const; diff --git a/app/wm/waylandinterface.cpp b/app/wm/waylandinterface.cpp --- a/app/wm/waylandinterface.cpp +++ b/app/wm/waylandinterface.cpp @@ -370,6 +370,11 @@ return (winfo.isValid() && !winfo.isPlasmaDesktop() && !winfo.hasSkipTaskbar()); } +void WaylandInterface::releaseMouseEventFor(WindowId wid) const +{ + // this isnt really needed under wayland +} + void WaylandInterface::requestMoveWindow(WindowId wid, QPoint from) const { if (windowCanBeDragged(wid)) { diff --git a/app/wm/xwindowinterface.h b/app/wm/xwindowinterface.h --- a/app/wm/xwindowinterface.h +++ b/app/wm/xwindowinterface.h @@ -61,6 +61,7 @@ void slideWindow(QWindow &view, Slide location) const override; void enableBlurBehind(QWindow &view) const override; + void releaseMouseEventFor(WindowId wid) const override; void requestToggleMaximized(WindowId wid) const override; void requestMoveWindow(WindowId wid, QPoint from) const override; bool windowCanBeDragged(WindowId wid) const override; diff --git a/app/wm/xwindowinterface.cpp b/app/wm/xwindowinterface.cpp --- a/app/wm/xwindowinterface.cpp +++ b/app/wm/xwindowinterface.cpp @@ -333,6 +333,28 @@ return (winfo.isValid() && !winfo.isPlasmaDesktop() && !winfo.hasSkipTaskbar()); } +void XWindowInterface::releaseMouseEventFor(WindowId wid) const +{ + auto connection = QX11Info::connection(); + + xcb_button_release_event_t releaseEvent; + memset(&releaseEvent, 0, sizeof(releaseEvent)); + + releaseEvent.response_type = XCB_BUTTON_RELEASE; + releaseEvent.event = wid.toInt(); + releaseEvent.child = XCB_WINDOW_NONE; + releaseEvent.root = QX11Info::appRootWindow(); + releaseEvent.event_x = -1; + releaseEvent.event_y = -1; + releaseEvent.root_x = -1; + releaseEvent.root_y = -1; + releaseEvent.detail = XCB_BUTTON_INDEX_1; + releaseEvent.state = XCB_BUTTON_MASK_1; + releaseEvent.time = XCB_CURRENT_TIME; + releaseEvent.same_screen = true; + xcb_send_event( connection, false, wid.toInt(), XCB_EVENT_MASK_BUTTON_RELEASE, reinterpret_cast(&releaseEvent)); +} + void XWindowInterface::requestMoveWindow(WindowId wid, QPoint from) const { WindowInfoWrap wInfo = requestInfo(wid);