Process mouse events

Button Press/Release do no longer fall through to motion notify as
there is no shared mouse event in xcb. Also the methods in Effects and
TabBox are adjusted to process only button press/release or motion
notify.

ScreenEdges are no longer checked for button press/release. They don't
interact on button press/release so there is no need to check it.
This commit is contained in:
Martin Gräßlin 2013-07-26 08:46:31 +02:00
parent d81c45a810
commit 485f0a3e06
5 changed files with 71 additions and 55 deletions

View file

@ -1184,43 +1184,31 @@ void EffectsHandlerImpl::defineCursor(Qt::CursorShape shape)
m_mouseInterceptionWindow.defineCursor(Cursor::x11Cursor(shape));
}
bool EffectsHandlerImpl::checkInputWindowEvent(XEvent* e)
bool EffectsHandlerImpl::checkInputWindowEvent(xcb_button_press_event_t *e)
{
if (e->type != ButtonPress && e->type != ButtonRelease && e->type != MotionNotify)
return false;
if (m_grabbedMouseEffects.isEmpty() || m_mouseInterceptionWindow != e->xany.window) {
if (m_grabbedMouseEffects.isEmpty() || m_mouseInterceptionWindow != e->event) {
return false;
}
foreach (Effect *effect, m_grabbedMouseEffects) {
switch(e->type) {
case ButtonPress: {
XButtonEvent* e2 = &e->xbutton;
Qt::MouseButton button = x11ToQtMouseButton(e2->button);
Qt::MouseButtons buttons = x11ToQtMouseButtons(e2->state) | button;
QMouseEvent ev(QEvent::MouseButtonPress,
QPoint(e2->x, e2->y), QPoint(e2->x_root, e2->y_root),
button, buttons, x11ToQtKeyboardModifiers(e2->state));
effect->windowInputMouseEvent(&ev);
break; // --->
}
case ButtonRelease: {
XButtonEvent* e2 = &e->xbutton;
Qt::MouseButton button = x11ToQtMouseButton(e2->button);
Qt::MouseButtons buttons = x11ToQtMouseButtons(e2->state) & ~button;
QMouseEvent ev(QEvent::MouseButtonRelease,
QPoint(e2->x, e2->y), QPoint(e2->x_root, e2->y_root),
button, buttons, x11ToQtKeyboardModifiers(e2->state));
effect->windowInputMouseEvent(&ev);
break; // --->
}
case MotionNotify: {
XMotionEvent* e2 = &e->xmotion;
QMouseEvent ev(QEvent::MouseMove, QPoint(e2->x, e2->y), QPoint(e2->x_root, e2->y_root),
Qt::NoButton, x11ToQtMouseButtons(e2->state), x11ToQtKeyboardModifiers(e2->state));
effect->windowInputMouseEvent(&ev);
break; // --->
}
}
for (Effect *effect : m_grabbedMouseEffects) {
Qt::MouseButton button = x11ToQtMouseButton(e->detail);
Qt::MouseButtons buttons = x11ToQtMouseButtons(e->state) & ~button;
QMouseEvent ev(((e->response_type & ~0x80) == XCB_BUTTON_PRESS) ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease,
QPoint(e->event_x, e->event_y), QPoint(e->root_x, e->root_y),
button, buttons, x11ToQtKeyboardModifiers(e->state));
effect->windowInputMouseEvent(&ev);
}
return true; // eat event
}
bool EffectsHandlerImpl::checkInputWindowEvent(xcb_motion_notify_event_t *e)
{
if (m_grabbedMouseEffects.isEmpty() || m_mouseInterceptionWindow != e->event) {
return false;
}
for (Effect *effect : m_grabbedMouseEffects) {
QMouseEvent ev(QEvent::MouseMove, QPoint(e->event_x, e->event_y), QPoint(e->root_x, e->root_y),
Qt::NoButton, x11ToQtMouseButtons(e->state), x11ToQtKeyboardModifiers(e->state));
effect->windowInputMouseEvent(&ev);
}
return true; // eat event
}

View file

@ -151,7 +151,8 @@ public:
virtual WindowQuadType newWindowQuadType();
virtual void defineCursor(Qt::CursorShape shape);
virtual bool checkInputWindowEvent(XEvent* e);
bool checkInputWindowEvent(xcb_button_press_event_t *e);
bool checkInputWindowEvent(xcb_motion_notify_event_t *e);
virtual void checkInputWindowStacking();
virtual void reserveElectricBorder(ElectricBorder border, Effect *effect);

View file

@ -99,31 +99,44 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
}
#endif
#if KWIN_QT5_PORTING
// events that should be handled before Clients can get them
switch(e->type) {
case ButtonPress:
case ButtonRelease:
switch (eventType) {
case XCB_BUTTON_PRESS:
case XCB_BUTTON_RELEASE: {
was_user_interaction = true;
// fallthrough
case MotionNotify:
auto *mouseEvent = reinterpret_cast<xcb_button_press_event_t*>(e);
#ifdef KWIN_BUILD_TABBOX
if (TabBox::TabBox::self()->isGrabbed()) {
return TabBox::TabBox::self()->handleMouseEvent(mouseEvent);
}
#endif
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(mouseEvent)) {
return true;
}
break;
}
case XCB_MOTION_NOTIFY: {
auto *mouseEvent = reinterpret_cast<xcb_motion_notify_event_t*>(e);
const QPoint rootPos(mouseEvent->root_x, mouseEvent->root_y);
#ifdef KWIN_BUILD_TABBOX
if (TabBox::TabBox::self()->isGrabbed()) {
#ifdef KWIN_BUILD_SCREENEDGES
ScreenEdges::self()->check(QPoint(e->xbutton.x_root, e->xbutton.y_root), QDateTime::fromMSecsSinceEpoch(xTime()), true);
ScreenEdges::self()->check(rootPos, QDateTime::fromMSecsSinceEpoch(xTime()), true);
#endif
return TabBox::TabBox::self()->handleMouseEvent(e);
return TabBox::TabBox::self()->handleMouseEvent(mouseEvent);
}
#endif
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(e)) {
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(mouseEvent)) {
return true;
}
#ifdef KWIN_BUILD_SCREENEDGES
if (QWidget::mouseGrabber()) {
ScreenEdges::self()->check(QPoint(e->xbutton.x_root, e->xbutton.y_root), QDateTime::fromMSecsSinceEpoch(xTime()), true);
ScreenEdges::self()->check(rootPos, QDateTime::fromMSecsSinceEpoch(xTime()), true);
}
#endif
break;
}
#if KWIN_QT5_PORTING
case KeyPress: {
was_user_interaction = true;
int keyQt;
@ -353,8 +366,8 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
Cursor::self()->notifyCursorChanged(reinterpret_cast<XFixesCursorNotifyEvent*>(e)->cursor_serial);
}
break;
}
#endif
}
return false;
}

View file

@ -813,28 +813,27 @@ void TabBox::delayedShow()
m_delayedShowTimer.start(m_delayShowTime);
}
bool TabBox::handleMouseEvent(XEvent* e)
bool TabBox::handleMouseEvent(xcb_button_press_event_t *e)
{
XAllowEvents(display(), AsyncPointer, xTime());
xcb_allow_events(connection(), XCB_ALLOW_ASYNC_POINTER, xTime());
if (!m_isShown && isDisplayed()) {
// tabbox has been replaced, check effects
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(e))
return true;
}
if (e->type == ButtonPress) {
if (e->response_type & ~0x80 == XCB_BUTTON_PRESS) {
// press outside Tabbox?
QPoint pos(e->xbutton.x_root, e->xbutton.y_root);
QPoint pos(e->root_x, e->root_y);
if ((!m_isShown && isDisplayed())
|| (!m_tabBox->containsPos(pos) &&
(e->xbutton.button == Button1 || e->xbutton.button == Button2 || e->xbutton.button == Button3))) {
(e->detail == XCB_BUTTON_INDEX_1 || e->detail == XCB_BUTTON_INDEX_2 || e->detail == XCB_BUTTON_INDEX_3))) {
close(); // click outside closes tab
return true;
}
if (e->xbutton.button == Button5 || e->xbutton.button == Button4) {
if (e->detail == XCB_BUTTON_INDEX_5 || e->detail == XCB_BUTTON_INDEX_4) {
// mouse wheel event
const QModelIndex index = m_tabBox->nextPrev(e->xbutton.button == Button5);
const QModelIndex index = m_tabBox->nextPrev(e->detail == XCB_BUTTON_INDEX_5);
if (index.isValid()) {
setCurrentIndex(index);
}
@ -844,6 +843,17 @@ bool TabBox::handleMouseEvent(XEvent* e)
return false;
}
bool TabBox::handleMouseEvent(xcb_motion_notify_event_t *e)
{
xcb_allow_events(connection(), XCB_ALLOW_ASYNC_POINTER, xTime());
if (!m_isShown && isDisplayed()) {
// tabbox has been replaced, check effects
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(e))
return true;
}
return false;
}
void TabBox::grabbedKeyEvent(QKeyEvent* event)
{
emit tabBoxKeyEvent(event);

View file

@ -33,6 +33,9 @@ class KActionCollection;
class KConfigGroup;
class QKeyEvent;
struct xcb_button_press_event_t;
struct xcb_motion_notify_event_t;
namespace KWin
{
@ -156,7 +159,8 @@ public:
return m_displayRefcount > 0;
};
bool handleMouseEvent(XEvent* e);
bool handleMouseEvent(xcb_button_press_event_t *e);
bool handleMouseEvent(xcb_motion_notify_event_t *e);
void grabbedKeyEvent(QKeyEvent* event);
bool isGrabbed() const {