Handle interaction with window decoration directly in InputRedirection
So far input events were sent through Xwayland which is not needed as we have all information available. Even more it had the pointer surface on the wrong window when interacting with decorations as it was on the window and not on the decoration.
This commit is contained in:
parent
8b3be23032
commit
1edd689293
4 changed files with 129 additions and 0 deletions
40
client.cpp
40
client.cpp
|
@ -45,6 +45,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QMouseEvent>
|
||||
#include <QProcess>
|
||||
#include <QStandardPaths>
|
||||
#include <QScriptEngine>
|
||||
|
@ -2257,6 +2258,45 @@ bool Client::belongsToSameApplication(const AbstractClient *other, bool active_h
|
|||
return Client::belongToSameApplication(this, c2, active_hack);
|
||||
}
|
||||
|
||||
bool Client::processDecorationButtonPress(QMouseEvent *event)
|
||||
{
|
||||
return processDecorationButtonPress(qtToX11Button(event->button()), 0,
|
||||
event->x(), event->y(),
|
||||
event->globalX(), event->globalY());
|
||||
}
|
||||
|
||||
void Client::processDecorationButtonRelease(QMouseEvent *event)
|
||||
{
|
||||
if (m_decoration) {
|
||||
if (!event->isAccepted() && m_decoration->titleBar().contains(event->pos()) && event->button() == Qt::LeftButton) {
|
||||
m_decorationDoubleClickTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
if (event->buttons() == Qt::NoButton) {
|
||||
buttonDown = false;
|
||||
stopDelayedMoveResize();
|
||||
if (moveResizeMode) {
|
||||
finishMoveResize(false);
|
||||
mode = mousePosition();
|
||||
}
|
||||
updateCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::processDecorationMove()
|
||||
{
|
||||
if (buttonDown) {
|
||||
return;
|
||||
}
|
||||
// TODO: handle modifiers
|
||||
Position newmode = mousePosition();
|
||||
if (newmode != mode) {
|
||||
mode = newmode;
|
||||
updateCursor();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "client.moc"
|
||||
|
|
3
client.h
3
client.h
|
@ -231,6 +231,9 @@ public:
|
|||
bool windowEvent(xcb_generic_event_t *e);
|
||||
void syncEvent(xcb_sync_alarm_notify_event_t* e);
|
||||
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
|
||||
bool processDecorationButtonPress(QMouseEvent *event);
|
||||
void processDecorationButtonRelease(QMouseEvent *event);
|
||||
void processDecorationMove();
|
||||
|
||||
bool manage(xcb_window_t w, bool isMapped);
|
||||
void releaseWindow(bool on_shutdown = false);
|
||||
|
|
74
input.cpp
74
input.cpp
|
@ -38,6 +38,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "virtual_terminal.h"
|
||||
#include <KWayland/Server/seat_interface.h>
|
||||
#endif
|
||||
#include <decorations/decoratedclient.h>
|
||||
#include <KDecoration2/Decoration>
|
||||
// Qt
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
|
@ -375,6 +377,10 @@ void InputRedirection::updatePointerWindow()
|
|||
{
|
||||
// TODO: handle pointer grab aka popups
|
||||
Toplevel *t = findToplevel(m_globalPointer.toPoint());
|
||||
updatePointerDecoration(t);
|
||||
if (m_pointerDecoration) {
|
||||
t = nullptr;
|
||||
}
|
||||
auto oldWindow = m_pointerWindow;
|
||||
if (!oldWindow.isNull() && t == m_pointerWindow.data()) {
|
||||
return;
|
||||
|
@ -416,6 +422,38 @@ void InputRedirection::updatePointerWindow()
|
|||
m_pointerWindow = QWeakPointer<Toplevel>(t);
|
||||
}
|
||||
|
||||
void InputRedirection::updatePointerDecoration(Toplevel *t)
|
||||
{
|
||||
const auto oldDeco = m_pointerDecoration;
|
||||
if (Client *c = dynamic_cast<Client*>(t)) {
|
||||
// check whether it's on a Decoration
|
||||
if (c->decoratedClient()) {
|
||||
const QRect clientRect = QRect(c->clientPos(), c->clientSize()).translated(c->pos());
|
||||
if (!clientRect.contains(m_globalPointer.toPoint())) {
|
||||
m_pointerDecoration = c->decoratedClient();
|
||||
} else {
|
||||
m_pointerDecoration.clear();
|
||||
}
|
||||
} else {
|
||||
m_pointerDecoration.clear();
|
||||
}
|
||||
} else {
|
||||
m_pointerDecoration.clear();
|
||||
}
|
||||
|
||||
if (oldDeco && oldDeco != m_pointerDecoration) {
|
||||
// send leave
|
||||
QHoverEvent event(QEvent::HoverLeave, QPointF(), QPointF());
|
||||
QCoreApplication::instance()->sendEvent(oldDeco->decoration(), &event);
|
||||
}
|
||||
if (m_pointerDecoration) {
|
||||
const QPointF p = m_globalPointer - t->pos();
|
||||
QHoverEvent event(QEvent::HoverMove, p, p);
|
||||
QCoreApplication::instance()->sendEvent(m_pointerDecoration->decoration(), &event);
|
||||
m_pointerDecoration->client()->processDecorationMove();
|
||||
}
|
||||
}
|
||||
|
||||
void InputRedirection::updateFocusedPointerPosition()
|
||||
{
|
||||
#if HAVE_WAYLAND
|
||||
|
@ -496,6 +534,23 @@ void InputRedirection::processPointerButton(uint32_t button, InputRedirection::P
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if (m_pointerDecoration) {
|
||||
const QPoint localPos = m_globalPointer.toPoint() - m_pointerDecoration->client()->pos();
|
||||
QMouseEvent event(buttonStateToEvent(state),
|
||||
localPos,
|
||||
m_globalPointer.toPoint(),
|
||||
buttonToQtMouseButton(button), qtButtonStates(), keyboardModifiers());
|
||||
event.setAccepted(false);
|
||||
QCoreApplication::sendEvent(m_pointerDecoration->decoration(), &event);
|
||||
if (!event.isAccepted()) {
|
||||
if (state == PointerButtonPressed) {
|
||||
m_pointerDecoration->client()->processDecorationButtonPress(&event);
|
||||
}
|
||||
}
|
||||
if (state == PointerButtonReleased) {
|
||||
m_pointerDecoration->client()->processDecorationButtonRelease(&event);
|
||||
}
|
||||
}
|
||||
// TODO: check which part of KWin would like to intercept the event
|
||||
#if HAVE_WAYLAND
|
||||
if (auto seat = findSeat()) {
|
||||
|
@ -536,6 +591,25 @@ void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qr
|
|||
}
|
||||
#endif
|
||||
|
||||
if (m_pointerDecoration) {
|
||||
const QPointF localPos = m_globalPointer - m_pointerDecoration->client()->pos();
|
||||
// TODO: add modifiers and buttons
|
||||
QWheelEvent event(localPos, m_globalPointer, QPoint(),
|
||||
(axis == PointerAxisHorizontal) ? QPoint(delta, 0) : QPoint(0, delta),
|
||||
delta,
|
||||
(axis == PointerAxisHorizontal) ? Qt::Horizontal : Qt::Vertical,
|
||||
Qt::NoButton,
|
||||
Qt::NoModifier);
|
||||
event.setAccepted(false);
|
||||
QCoreApplication::sendEvent(m_pointerDecoration->decoration(), &event);
|
||||
if (!event.isAccepted() && axis == PointerAxisVertical) {
|
||||
if (m_pointerDecoration->decoration()->titleBar().contains(localPos.toPoint())) {
|
||||
m_pointerDecoration->client()->performMouseCommand(options->operationTitlebarMouseWheel(delta * -1),
|
||||
m_globalPointer.toPoint());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check which part of KWin would like to intercept the event
|
||||
// TODO: Axis support for effect redirection
|
||||
#if HAVE_WAYLAND
|
||||
|
|
12
input.h
12
input.h
|
@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
#include <QPointer>
|
||||
#include <QEvent>
|
||||
#include <QWeakPointer>
|
||||
#include <config-kwin.h>
|
||||
|
@ -42,6 +43,11 @@ class GlobalShortcutsManager;
|
|||
class Toplevel;
|
||||
class Xkb;
|
||||
|
||||
namespace Decoration
|
||||
{
|
||||
class DecoratedClientImpl;
|
||||
}
|
||||
|
||||
namespace LibInput
|
||||
{
|
||||
class Connection;
|
||||
|
@ -183,6 +189,7 @@ private:
|
|||
void updateFocusedPointerPosition();
|
||||
void updateFocusedTouchPosition();
|
||||
void updateTouchWindow(const QPointF &pos);
|
||||
void updatePointerDecoration(Toplevel *t);
|
||||
bool areButtonsPressed() const;
|
||||
QPointF m_globalPointer;
|
||||
QHash<uint32_t, PointerButtonState> m_pointerButtons;
|
||||
|
@ -193,6 +200,11 @@ private:
|
|||
* @brief The Toplevel which currently receives pointer events
|
||||
*/
|
||||
QWeakPointer<Toplevel> m_pointerWindow;
|
||||
/**
|
||||
* @brief The Decoration which currently receives pointer events.
|
||||
* Decoration belongs to the pointerWindow
|
||||
**/
|
||||
QPointer<Decoration::DecoratedClientImpl> m_pointerDecoration;
|
||||
/**
|
||||
* @brief The Toplevel which currently receives touch events
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue