Pass pointer events through the effect system

InputRedirection forwards pointer events (currently motion, press and
release) through the EffectsHandlerImpl for the case that an effect has
intercepted pointer events.

If the KWin operation mode is not X11 only, the window for intercepting
the mouse events is no longer created.
This commit is contained in:
Martin Gräßlin 2013-06-26 11:40:30 +02:00
parent 940d9fb513
commit 6619faa6ac
4 changed files with 87 additions and 0 deletions

View file

@ -767,6 +767,9 @@ void EffectsHandlerImpl::startMouseInterception(Effect *effect, Qt::CursorShape
if (m_grabbedMouseEffects.size() != 1) {
return;
}
if (kwinApp()->operationMode() != Application::OperationModeX11) {
return;
}
// NOTE: it is intended to not perform an XPointerGrab on X11. See documentation in kwineffects.h
// The mouse grab is implemented by using a full screen input only window
if (!m_mouseInterceptionWindow.isValid()) {
@ -794,6 +797,9 @@ void EffectsHandlerImpl::stopMouseInterception(Effect *effect)
return;
}
m_grabbedMouseEffects.removeAll(effect);
if (kwinApp()->operationMode() != Application::OperationModeX11) {
return;
}
if (m_grabbedMouseEffects.isEmpty()) {
m_mouseInterceptionWindow.unmap();
#ifdef KWIN_BUILD_SCREENEDGES
@ -1291,11 +1297,25 @@ bool EffectsHandlerImpl::checkInputWindowEvent(xcb_motion_notify_event_t *e)
return true; // eat event
}
bool EffectsHandlerImpl::checkInputWindowEvent(QMouseEvent *e)
{
if (m_grabbedMouseEffects.isEmpty()) {
return false;
}
foreach (Effect *effect, m_grabbedMouseEffects) {
effect->windowInputMouseEvent(e);
}
return true;
}
void EffectsHandlerImpl::checkInputWindowStacking()
{
if (m_grabbedMouseEffects.isEmpty()) {
return;
}
if (kwinApp()->operationMode() != Application::OperationModeX11) {
return;
}
m_mouseInterceptionWindow.raise();
// Raise electric border windows above the input windows
// so they can still be triggered. TODO: Do both at once.

View file

@ -156,6 +156,7 @@ public:
void defineCursor(Qt::CursorShape shape) override;
bool checkInputWindowEvent(xcb_button_press_event_t *e);
bool checkInputWindowEvent(xcb_motion_notify_event_t *e);
bool checkInputWindowEvent(QMouseEvent *e);
void checkInputWindowStacking();
void reserveElectricBorder(ElectricBorder border, Effect *effect) override;

View file

@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "input.h"
#include "effects.h"
// TODO: remove xtest
#include <xcb/xtest.h>
// system
@ -47,6 +48,14 @@ void InputRedirection::processPointerMotion(const QPointF &pos, uint32_t time)
emit globalPointerChanged(m_globalPointer);
// TODO: check which part of KWin would like to intercept the event
// TODO: keyboard modifiers
QMouseEvent event(QEvent::MouseMove, m_globalPointer.toPoint(), m_globalPointer.toPoint(),
Qt::NoButton, qtButtonStates(), 0);
// check whether an effect has a mouse grab
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(&event)) {
// an effect grabbed the pointer, we do not forward the event to surfaces
return;
}
// TODO: redirect to proper client
// TODO: don't use xtest
@ -60,6 +69,14 @@ void InputRedirection::processPointerButton(uint32_t button, InputRedirection::P
m_pointerButtons[button] = state;
emit pointerButtonStateChanged(button, state);
// TODO: keyboard modifiers
QMouseEvent event(buttonStateToEvent(state), m_globalPointer.toPoint(), m_globalPointer.toPoint(),
buttonToQtMouseButton(button), qtButtonStates(), 0);
// check whether an effect has a mouse grab
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(&event)) {
// an effect grabbed the pointer, we do not forward the event to surfaces
return;
}
// TODO: check which part of KWin would like to intercept the event
// TODO: redirect to proper client
@ -96,6 +113,7 @@ void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qr
emit pointerAxisChanged(axis, delta);
// TODO: check which part of KWin would like to intercept the event
// TODO: Axis support for effect redirection
// TODO: redirect to proper client
// TODO: don't use xtest
@ -118,4 +136,48 @@ void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qr
}
}
QEvent::Type InputRedirection::buttonStateToEvent(InputRedirection::PointerButtonState state)
{
switch (state) {
case KWin::InputRedirection::PointerButtonReleased:
return QEvent::MouseButtonRelease;
case KWin::InputRedirection::PointerButtonPressed:
return QEvent::MouseButtonPress;
}
return QEvent::None;
}
Qt::MouseButton InputRedirection::buttonToQtMouseButton(uint32_t button)
{
switch (button) {
case BTN_LEFT:
return Qt::LeftButton;
case BTN_MIDDLE:
return Qt::MiddleButton;
case BTN_RIGHT:
return Qt::RightButton;
case BTN_BACK:
return Qt::XButton1;
case BTN_FORWARD:
return Qt::XButton2;
}
return Qt::NoButton;
}
Qt::MouseButtons InputRedirection::qtButtonStates() const
{
Qt::MouseButtons buttons;
for (auto it = m_pointerButtons.constBegin(); it != m_pointerButtons.constEnd(); ++it) {
if (it.value() == KWin::InputRedirection::PointerButtonReleased) {
continue;
}
Qt::MouseButton button = buttonToQtMouseButton(it.key());
if (button != Qt::NoButton) {
buttons |= button;
}
}
return buttons;
}
} // namespace

View file

@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QHash>
#include <QObject>
#include <QPoint>
#include <QEvent>
namespace KWin
{
@ -99,6 +100,9 @@ Q_SIGNALS:
void pointerAxisChanged(PointerAxis axis, qreal delta);
private:
static QEvent::Type buttonStateToEvent(PointerButtonState state);
static Qt::MouseButton buttonToQtMouseButton(uint32_t button);
Qt::MouseButtons qtButtonStates() const;
QPointF m_globalPointer;
QHash<uint32_t, PointerButtonState> m_pointerButtons;