[wayland] Handle pointer events for internal windows

If there is a visible internal window it gets the pointer events.
The assumption is that the last created internal window is the top
most in stacking order.
icc-effect-5.14.5
Martin Gräßlin 2015-06-06 03:26:24 +02:00
parent 7a64426085
commit 7f0758b85f
3 changed files with 99 additions and 7 deletions

100
input.cpp
View File

@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#if HAVE_WAYLAND
#include "abstract_backend.h"
#include "shell_client.h"
#include "wayland_server.h"
#include "virtual_terminal.h"
#include <KWayland/Server/seat_interface.h>
@ -378,8 +379,13 @@ void InputRedirection::updatePointerWindow()
{
// TODO: handle pointer grab aka popups
Toplevel *t = findToplevel(m_globalPointer.toPoint());
updatePointerDecoration(t);
if (m_pointerDecoration) {
updatePointerInternalWindow();
if (!m_pointerInternalWindow) {
updatePointerDecoration(t);
} else {
m_pointerDecoration.clear();
}
if (m_pointerDecoration || m_pointerInternalWindow) {
t = nullptr;
}
auto oldWindow = m_pointerWindow;
@ -461,6 +467,67 @@ void InputRedirection::updatePointerDecoration(Toplevel *t)
}
}
void InputRedirection::updatePointerInternalWindow()
{
const auto oldInternalWindow = m_pointerInternalWindow;
#if HAVE_WAYLAND
if (waylandServer()) {
bool found = false;
const auto &internalClients = waylandServer()->internalClients();
if (!internalClients.isEmpty()) {
auto it = internalClients.end();
do {
it--;
if (QWindow *w = (*it)->internalWindow()) {
if (!w->isVisible()) {
continue;
}
if (w->geometry().contains(m_globalPointer.toPoint())) {
m_pointerInternalWindow = QPointer<QWindow>(w);
found = true;
break;
}
}
} while (it != internalClients.begin());
if (!found) {
m_pointerInternalWindow.clear();
}
}
}
#endif
if (oldInternalWindow != m_pointerInternalWindow) {
// changed
if (oldInternalWindow) {
disconnect(oldInternalWindow.data(), &QWindow::visibleChanged, this, &InputRedirection::pointerInternalWindowVisibilityChanged);
QEvent event(QEvent::Leave);
QCoreApplication::sendEvent(oldInternalWindow.data(), &event);
}
if (m_pointerInternalWindow) {
connect(oldInternalWindow.data(), &QWindow::visibleChanged, this, &InputRedirection::pointerInternalWindowVisibilityChanged);
QEnterEvent event(m_globalPointer - m_pointerInternalWindow->position(),
m_globalPointer - m_pointerInternalWindow->position(),
m_globalPointer);
QCoreApplication::sendEvent(m_pointerInternalWindow.data(), &event);
return;
}
}
if (m_pointerInternalWindow) {
// send mouse move
QMouseEvent event(QEvent::MouseMove,
m_globalPointer.toPoint() - m_pointerInternalWindow->position(),
m_globalPointer.toPoint(),
Qt::NoButton, qtButtonStates(), keyboardModifiers());
QCoreApplication::sendEvent(m_pointerInternalWindow.data(), &event);
}
}
void InputRedirection::pointerInternalWindowVisibilityChanged(bool visible)
{
if (!visible) {
updatePointerWindow();
}
}
void InputRedirection::installCursorFromDecoration()
{
#if HAVE_WAYLAND
@ -506,6 +573,9 @@ void InputRedirection::updateFocusedTouchPosition()
void InputRedirection::processPointerMotion(const QPointF &pos, uint32_t time)
{
if (!workspace()) {
return;
}
// first update to new mouse position
// const QPointF oldPos = m_globalPointer;
updatePointerPosition(pos);
@ -559,6 +629,15 @@ void InputRedirection::processPointerButton(uint32_t button, InputRedirection::P
}
}
#endif
if (m_pointerInternalWindow) {
// send mouse move
QMouseEvent event(buttonStateToEvent(state),
m_globalPointer.toPoint() - m_pointerInternalWindow->position(),
m_globalPointer.toPoint(),
buttonToQtMouseButton(button), qtButtonStates(), keyboardModifiers());
event.setAccepted(false);
QCoreApplication::sendEvent(m_pointerInternalWindow.data(), &event);
}
if (m_pointerDecoration) {
const QPoint localPos = m_globalPointer.toPoint() - m_pointerDecoration->client()->pos();
QMouseEvent event(buttonStateToEvent(state),
@ -617,8 +696,8 @@ void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qr
}
#endif
if (m_pointerDecoration) {
const QPointF localPos = m_globalPointer - m_pointerDecoration->client()->pos();
auto sendWheelEvent = [this, delta, axis] (const QPoint targetPos, QObject *target) -> bool {
const QPointF localPos = m_globalPointer - targetPos;
// TODO: add modifiers and buttons
QWheelEvent event(localPos, m_globalPointer, QPoint(),
(axis == PointerAxisHorizontal) ? QPoint(delta, 0) : QPoint(0, delta),
@ -627,14 +706,21 @@ void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qr
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())) {
QCoreApplication::sendEvent(target, &event);
return event.isAccepted();
};
if (m_pointerDecoration) {
if (!sendWheelEvent(m_pointerDecoration->client()->pos(), m_pointerDecoration.data())
&& axis == PointerAxisVertical) {
if (m_pointerDecoration->decoration()->titleBar().contains(m_globalPointer.toPoint() - m_pointerDecoration->client()->pos())) {
m_pointerDecoration->client()->performMouseCommand(options->operationTitlebarMouseWheel(delta * -1),
m_globalPointer.toPoint());
}
}
}
if (m_pointerInternalWindow) {
sendWheelEvent(m_pointerInternalWindow->position(), m_pointerInternalWindow.data());
}
// TODO: check which part of KWin would like to intercept the event
// TODO: Axis support for effect redirection

View File

@ -193,6 +193,8 @@ private:
void updateFocusedTouchPosition();
void updateTouchWindow(const QPointF &pos);
void updatePointerDecoration(Toplevel *t);
void updatePointerInternalWindow();
void pointerInternalWindowVisibilityChanged(bool visible);
void installCursorFromDecoration();
bool areButtonsPressed() const;
QPointF m_globalPointer;
@ -209,6 +211,7 @@ private:
* Decoration belongs to the pointerWindow
**/
QPointer<Decoration::DecoratedClientImpl> m_pointerDecoration;
QPointer<QWindow> m_pointerInternalWindow;
/**
* @brief The Toplevel which currently receives touch events
*/

View File

@ -97,6 +97,9 @@ public:
return m_windowId;
}
bool isInternal() const;
QWindow *internalWindow() const {
return m_internalWindow;
}
protected:
void addDamage(const QRegion &damage) override;