improved mouse emulation
svn path=/trunk/kdebase/kwin/; revision=53892
This commit is contained in:
parent
601d183852
commit
c0e1ae2879
2 changed files with 168 additions and 56 deletions
175
workspace.cpp
175
workspace.cpp
|
@ -1925,6 +1925,8 @@ void Workspace::slotMouseEmulation()
|
||||||
GrabModeAsync, GrabModeAsync,
|
GrabModeAsync, GrabModeAsync,
|
||||||
kwin_time) == GrabSuccess ) {
|
kwin_time) == GrabSuccess ) {
|
||||||
mouse_emulation = TRUE;
|
mouse_emulation = TRUE;
|
||||||
|
mouse_emulation_state = 0;
|
||||||
|
mouse_emulation_window = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2175,6 +2177,105 @@ QPoint Workspace::adjustClientPosition( Client* c, QPoint pos )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the child window under the mouse and activates the
|
||||||
|
respective client if necessary.
|
||||||
|
|
||||||
|
Auxiliary function for the mouse emulation system.
|
||||||
|
*/
|
||||||
|
WId Workspace::getMouseEmulationWindow()
|
||||||
|
{
|
||||||
|
Window root;
|
||||||
|
Window child = qt_xrootwin();
|
||||||
|
int root_x, root_y, lx, ly;
|
||||||
|
uint state;
|
||||||
|
Window w;
|
||||||
|
Client * c = 0;
|
||||||
|
do {
|
||||||
|
w = child;
|
||||||
|
if (!c)
|
||||||
|
c = findClientWidthId( w );
|
||||||
|
XQueryPointer( qt_xdisplay(), w, &root, &child,
|
||||||
|
&root_x, &root_y, &lx, &ly, &state );
|
||||||
|
} while ( child != None && child != w );
|
||||||
|
|
||||||
|
if ( c && !c->isActive() )
|
||||||
|
activateClient( c );
|
||||||
|
return (WId) w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sends a faked mouse event to the specified window. Returns the new button state.
|
||||||
|
*/
|
||||||
|
unsigned int Workspace::sendFakedMouseEvent( QPoint pos, WId w, MouseEmulation type, int button, unsigned int state )
|
||||||
|
{
|
||||||
|
if ( !w )
|
||||||
|
return state;
|
||||||
|
QWidget* widget = QWidget::find( w );
|
||||||
|
if ( (!widget || widget->inherits("QToolButton") ) && !findClient( w ) ) {
|
||||||
|
int x, y;
|
||||||
|
Window xw;
|
||||||
|
XTranslateCoordinates( qt_xdisplay(), qt_xrootwin(), w, pos.x(), pos.y(), &x, &y, &xw );
|
||||||
|
if ( type == EmuMove ) { // motion notify events
|
||||||
|
XMotionEvent e;
|
||||||
|
e.type = MotionNotify;
|
||||||
|
e.window = w;
|
||||||
|
e.root = qt_xrootwin();
|
||||||
|
e.subwindow = w;
|
||||||
|
e.time = kwin_time;
|
||||||
|
e.x = x;
|
||||||
|
e.y = y;
|
||||||
|
e.x_root = pos.x();
|
||||||
|
e.y_root = pos.y();
|
||||||
|
e.state = state;
|
||||||
|
e.is_hint = NotifyNormal;
|
||||||
|
XSendEvent( qt_xdisplay(), w, TRUE, ButtonMotionMask, (XEvent*)&e );
|
||||||
|
} else {
|
||||||
|
XButtonEvent e;
|
||||||
|
e.type = type == EmuRelease ? ButtonRelease : ButtonPress;
|
||||||
|
e.window = w;
|
||||||
|
e.root = qt_xrootwin();
|
||||||
|
e.subwindow = w;
|
||||||
|
e.time = kwin_time;
|
||||||
|
e.x = x;
|
||||||
|
e.y = y;
|
||||||
|
e.x_root = pos.x();
|
||||||
|
e.y_root = pos.y();
|
||||||
|
e.state = state;
|
||||||
|
e.button = button;
|
||||||
|
XSendEvent( qt_xdisplay(), w, TRUE, ButtonPressMask, (XEvent*)&e );
|
||||||
|
|
||||||
|
if ( type == EmuPress ) {
|
||||||
|
switch ( button ) {
|
||||||
|
case 2:
|
||||||
|
state |= Button2Mask;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state |= Button3Mask;
|
||||||
|
break;
|
||||||
|
default: // 1
|
||||||
|
state |= Button1Mask;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch ( button ) {
|
||||||
|
case 2:
|
||||||
|
state &= ~Button2Mask;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state &= ~Button3Mask;
|
||||||
|
break;
|
||||||
|
default: // 1
|
||||||
|
state &= ~Button1Mask;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Handles keypress event during mouse emulation
|
Handles keypress event during mouse emulation
|
||||||
*/
|
*/
|
||||||
|
@ -2187,6 +2288,7 @@ bool Workspace::keyPressMouseEmulation( XKeyEvent key )
|
||||||
|
|
||||||
bool is_control = km & ControlMask;
|
bool is_control = km & ControlMask;
|
||||||
bool is_alt = km & Mod1Mask;
|
bool is_alt = km & Mod1Mask;
|
||||||
|
bool is_shift = km & ShiftMask;
|
||||||
int delta = is_control?1:is_alt?32:8;
|
int delta = is_control?1:is_alt?32:8;
|
||||||
QPoint pos = QCursor::pos();
|
QPoint pos = QCursor::pos();
|
||||||
|
|
||||||
|
@ -2207,46 +2309,47 @@ bool Workspace::keyPressMouseEmulation( XKeyEvent key )
|
||||||
case XK_KP_Down:
|
case XK_KP_Down:
|
||||||
pos.ry() += delta;
|
pos.ry() += delta;
|
||||||
break;
|
break;
|
||||||
|
case XK_F1:
|
||||||
|
if ( !mouse_emulation_state )
|
||||||
|
mouse_emulation_window = getMouseEmulationWindow();
|
||||||
|
if ( (mouse_emulation_state & Button1Mask) == 0 )
|
||||||
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
|
||||||
|
if ( !is_shift )
|
||||||
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
|
||||||
|
break;
|
||||||
|
case XK_F2:
|
||||||
|
if ( !mouse_emulation_state )
|
||||||
|
mouse_emulation_window = getMouseEmulationWindow();
|
||||||
|
if ( (mouse_emulation_state & Button2Mask) == 0 )
|
||||||
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button2, mouse_emulation_state );
|
||||||
|
if ( !is_shift )
|
||||||
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
|
||||||
|
break;
|
||||||
|
case XK_F3:
|
||||||
|
if ( !mouse_emulation_state )
|
||||||
|
mouse_emulation_window = getMouseEmulationWindow();
|
||||||
|
if ( (mouse_emulation_state & Button3Mask) == 0 )
|
||||||
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button3, mouse_emulation_state );
|
||||||
|
if ( !is_shift )
|
||||||
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
|
||||||
|
break;
|
||||||
case XK_Return:
|
case XK_Return:
|
||||||
case XK_space:
|
case XK_space:
|
||||||
case XK_KP_Enter:
|
case XK_KP_Enter:
|
||||||
case XK_KP_Space:
|
case XK_KP_Space:
|
||||||
{
|
{
|
||||||
Window root;
|
if ( !mouse_emulation_state ) {
|
||||||
Window child = qt_xrootwin();
|
// nothing was pressed, fake a LMB click
|
||||||
int root_x, root_y, lx, ly;
|
mouse_emulation_window = getMouseEmulationWindow();
|
||||||
uint state;
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
|
||||||
Window w;
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
|
||||||
Client * c = 0;
|
} else { // release all
|
||||||
do {
|
if ( mouse_emulation_state & Button1Mask )
|
||||||
w = child;
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
|
||||||
if (!c)
|
if ( mouse_emulation_state & Button2Mask )
|
||||||
c = findClientWidthId( w );
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
|
||||||
XQueryPointer( qt_xdisplay(), w, &root, &child,
|
if ( mouse_emulation_state & Button3Mask )
|
||||||
&root_x, &root_y, &lx, &ly, &state );
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
|
||||||
} while ( child != None && child != w );
|
|
||||||
|
|
||||||
if ( c && !c->isActive() )
|
|
||||||
activateClient( c );
|
|
||||||
|
|
||||||
QWidget* widget = QWidget::find( w );
|
|
||||||
if ( (!widget || widget->inherits("QToolButton") ) && !findClient( w ) ) {
|
|
||||||
XButtonEvent e;
|
|
||||||
e.type = ButtonPress;
|
|
||||||
e.window = w;
|
|
||||||
e.root = qt_xrootwin();
|
|
||||||
e.subwindow = w;
|
|
||||||
e.time = kwin_time;
|
|
||||||
e.x = lx;
|
|
||||||
e.y = ly;
|
|
||||||
e.x_root = root_x;
|
|
||||||
e.y_root = root_y;
|
|
||||||
e.state = key.state;
|
|
||||||
e.button = Button1;
|
|
||||||
XSendEvent( qt_xdisplay(), w, TRUE, ButtonPressMask, (XEvent*)&e );
|
|
||||||
e.type = ButtonRelease;
|
|
||||||
e.state = key.state & Button1Mask;
|
|
||||||
XSendEvent( qt_xdisplay(), w, TRUE, ButtonReleaseMask, (XEvent*)&e );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
|
@ -2259,6 +2362,8 @@ bool Workspace::keyPressMouseEmulation( XKeyEvent key )
|
||||||
}
|
}
|
||||||
|
|
||||||
QCursor::setPos( pos );
|
QCursor::setPos( pos );
|
||||||
|
if ( mouse_emulation_state )
|
||||||
|
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuMove, 0, mouse_emulation_state );
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,6 +259,11 @@ private:
|
||||||
int row;
|
int row;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// mouse emulation
|
||||||
|
WId getMouseEmulationWindow();
|
||||||
|
enum MouseEmulation { EmuPress, EmuRelease, EmuMove };
|
||||||
|
unsigned int sendFakedMouseEvent( QPoint pos, WId win, MouseEmulation type, int button, unsigned int state ); // returns the new state
|
||||||
|
|
||||||
// ------------------
|
// ------------------
|
||||||
|
|
||||||
DockWindowList dockwins;
|
DockWindowList dockwins;
|
||||||
|
@ -286,6 +291,8 @@ private:
|
||||||
bool control_grab;
|
bool control_grab;
|
||||||
bool tab_grab;
|
bool tab_grab;
|
||||||
bool mouse_emulation;
|
bool mouse_emulation;
|
||||||
|
unsigned int mouse_emulation_state;
|
||||||
|
WId mouse_emulation_window;
|
||||||
bool focus_change;
|
bool focus_change;
|
||||||
|
|
||||||
TabBox* tab_box;
|
TabBox* tab_box;
|
||||||
|
|
Loading…
Reference in a new issue