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
211
workspace.cpp
211
workspace.cpp
|
@ -58,19 +58,19 @@ public:
|
|||
|
||||
void changeNumberOfDesktops(Q_UINT32 n) { workspace->setNumberOfDesktops( n ); }
|
||||
void changeCurrentDesktop(Q_UINT32 d) { workspace->setCurrentDesktop( d ); }
|
||||
void changeActiveWindow(Window w) {
|
||||
void changeActiveWindow(Window w) {
|
||||
::Client* c = workspace->findClient( (WId) w );
|
||||
if ( c )
|
||||
workspace->activateClient( c );
|
||||
}
|
||||
void closeWindow(Window w) {
|
||||
void closeWindow(Window w) {
|
||||
::Client* c = workspace->findClient( (WId) w );
|
||||
if ( c ) {
|
||||
c->closeWindow();
|
||||
}
|
||||
}
|
||||
void moveResize(Window, int, int, unsigned long) { }
|
||||
|
||||
|
||||
private:
|
||||
Workspace* workspace;
|
||||
};
|
||||
|
@ -169,7 +169,7 @@ Client* Workspace::clientFactory( Workspace *ws, WId w )
|
|||
c->setPassiveFocus( TRUE );
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
case NET::Dock: {
|
||||
Client * c = new NoBorderClient( ws, w);
|
||||
c->setSticky( TRUE );
|
||||
|
@ -177,7 +177,7 @@ Client* Workspace::clientFactory( Workspace *ws, WId w )
|
|||
c->setPassiveFocus( TRUE );
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
case NET::Menu: {
|
||||
Client * c = new NoBorderClient( ws, w);
|
||||
c->setSticky( TRUE );
|
||||
|
@ -185,12 +185,12 @@ Client* Workspace::clientFactory( Workspace *ws, WId w )
|
|||
c->setPassiveFocus( TRUE );
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
case NET::Toolbar: {
|
||||
Client * c = new NoBorderClient( ws, w);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -280,8 +280,8 @@ Workspace::Workspace( bool restore )
|
|||
void Workspace::init()
|
||||
{
|
||||
supportWindow = new QWidget;
|
||||
|
||||
unsigned long protocols =
|
||||
|
||||
unsigned long protocols =
|
||||
NET::Supported |
|
||||
NET::SupportingWMCheck |
|
||||
NET::ClientList |
|
||||
|
@ -304,7 +304,7 @@ void Workspace::init()
|
|||
;
|
||||
|
||||
rootInfo = new RootInfo( this, qt_xdisplay(), supportWindow->winId(), "KWin", protocols, qt_xscreen() );
|
||||
|
||||
|
||||
KConfig* config = KGlobal::config();
|
||||
config->setGroup("Desktops");
|
||||
if (!config->hasKey("NumberOfDesktops"))
|
||||
|
@ -381,7 +381,7 @@ Workspace::~Workspace()
|
|||
if ( root == qt_xrootwin() )
|
||||
XDeleteProperty(qt_xdisplay(), qt_xrootwin(), atoms->kwin_running);
|
||||
KGlobal::config()->sync();
|
||||
|
||||
|
||||
delete rootInfo;
|
||||
delete supportWindow;
|
||||
}
|
||||
|
@ -439,7 +439,7 @@ bool Workspace::workspaceEvent( XEvent * e )
|
|||
}
|
||||
case ReparentNotify:
|
||||
c = findClient( e->xreparent.window );
|
||||
if ( c )
|
||||
if ( c )
|
||||
(void) c->windowEvent( e );
|
||||
|
||||
//do not confuse Qt with these events. After all, _we_ are the
|
||||
|
@ -923,7 +923,7 @@ void Workspace::setActiveClient( Client* c )
|
|||
if ( c->wantsTabFocus() )
|
||||
focus_chain.append( c );
|
||||
}
|
||||
|
||||
|
||||
rootInfo->setActiveWindow( active_client? active_client->window() : 0 );
|
||||
}
|
||||
|
||||
|
@ -1708,9 +1708,9 @@ void Workspace::setNumberOfDesktops( int n )
|
|||
bool Workspace::netCheck( XEvent* e )
|
||||
{
|
||||
unsigned int dirty = rootInfo->event( e );
|
||||
|
||||
|
||||
dirty = 0; // shut up, compiler
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -1750,7 +1750,7 @@ bool Workspace::addDockwin( WId w )
|
|||
{
|
||||
if ( dockwins.contains( w ) )
|
||||
return TRUE;
|
||||
|
||||
|
||||
NETWinInfo ni( qt_xdisplay(), w, root, NET::WMKDEDockWinFor );
|
||||
WId dockFor = ni.kdeDockWinFor();
|
||||
if ( !dockFor )
|
||||
|
@ -1802,7 +1802,7 @@ void Workspace::propagateDockwins()
|
|||
for ( DockWindowList::ConstIterator it = dockwins.begin(); it != dockwins.end(); ++it ) {
|
||||
cl[i++] = (*it).dockWin;
|
||||
}
|
||||
|
||||
|
||||
rootInfo->setKDEDockingWindows( (Window*) cl, i );
|
||||
delete [] cl;
|
||||
}
|
||||
|
@ -1925,6 +1925,8 @@ void Workspace::slotMouseEmulation()
|
|||
GrabModeAsync, GrabModeAsync,
|
||||
kwin_time) == GrabSuccess ) {
|
||||
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
|
||||
*/
|
||||
|
@ -2187,6 +2288,7 @@ bool Workspace::keyPressMouseEmulation( XKeyEvent key )
|
|||
|
||||
bool is_control = km & ControlMask;
|
||||
bool is_alt = km & Mod1Mask;
|
||||
bool is_shift = km & ShiftMask;
|
||||
int delta = is_control?1:is_alt?32:8;
|
||||
QPoint pos = QCursor::pos();
|
||||
|
||||
|
@ -2207,46 +2309,47 @@ bool Workspace::keyPressMouseEmulation( XKeyEvent key )
|
|||
case XK_KP_Down:
|
||||
pos.ry() += delta;
|
||||
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_space:
|
||||
case XK_KP_Enter:
|
||||
case XK_KP_Space:
|
||||
{
|
||||
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 );
|
||||
|
||||
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 );
|
||||
if ( !mouse_emulation_state ) {
|
||||
// nothing was pressed, fake a LMB click
|
||||
mouse_emulation_window = getMouseEmulationWindow();
|
||||
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuPress, Button1, mouse_emulation_state );
|
||||
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
|
||||
} else { // release all
|
||||
if ( mouse_emulation_state & Button1Mask )
|
||||
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button1, mouse_emulation_state );
|
||||
if ( mouse_emulation_state & Button2Mask )
|
||||
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button2, mouse_emulation_state );
|
||||
if ( mouse_emulation_state & Button3Mask )
|
||||
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuRelease, Button3, mouse_emulation_state );
|
||||
}
|
||||
}
|
||||
// fall through
|
||||
|
@ -2259,6 +2362,8 @@ bool Workspace::keyPressMouseEmulation( XKeyEvent key )
|
|||
}
|
||||
|
||||
QCursor::setPos( pos );
|
||||
if ( mouse_emulation_state )
|
||||
mouse_emulation_state = sendFakedMouseEvent( pos, mouse_emulation_window, EmuMove, 0, mouse_emulation_state );
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
@ -2363,7 +2468,7 @@ void Workspace::updateClientArea()
|
|||
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) {
|
||||
a = a.intersect( (*it)->adjustedClientArea( all ) );
|
||||
}
|
||||
|
||||
|
||||
if ( area != a ) {
|
||||
area = a;
|
||||
NETRect r;
|
||||
|
|
13
workspace.h
13
workspace.h
|
@ -181,11 +181,11 @@ public:
|
|||
*/
|
||||
virtual void updateClientArea();
|
||||
|
||||
|
||||
|
||||
// dcop interface
|
||||
void cascadeDesktop();
|
||||
void unclutterDesktop();
|
||||
|
||||
|
||||
|
||||
public slots:
|
||||
void setCurrentDesktop( int new_desktop );
|
||||
|
@ -258,6 +258,11 @@ private:
|
|||
int col;
|
||||
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
|
||||
|
||||
// ------------------
|
||||
|
||||
|
@ -286,6 +291,8 @@ private:
|
|||
bool control_grab;
|
||||
bool tab_grab;
|
||||
bool mouse_emulation;
|
||||
unsigned int mouse_emulation_state;
|
||||
WId mouse_emulation_window;
|
||||
bool focus_change;
|
||||
|
||||
TabBox* tab_box;
|
||||
|
@ -297,7 +304,7 @@ private:
|
|||
WId root;
|
||||
|
||||
PluginMgr mgr;
|
||||
|
||||
|
||||
RootInfo *rootInfo;
|
||||
QWidget* supportWindow;
|
||||
|
||||
|
|
Loading…
Reference in a new issue