More keyboard commands such as "Window move" and "Window resize".
"Mouse emulation" (defaults to F12 currently) provides mouse emulation with [Ctrl|Alt]-ArrowKeys. Unfortunatly, dragging isn't (technically) possible with X, but at least normal clicks work with Space or Return. svn path=/trunk/kdebase/kwin/; revision=35919
This commit is contained in:
parent
6d59623f8f
commit
935c0a4478
5 changed files with 339 additions and 20 deletions
110
client.cpp
110
client.cpp
|
@ -20,6 +20,8 @@
|
|||
extern Atom qt_wm_state;
|
||||
extern Time kwin_time;
|
||||
|
||||
static bool resizeHorizontalDirectionFixed = FALSE;
|
||||
static bool resizeVerticalDirectionFixed = FALSE;
|
||||
|
||||
static QRect* visible_bound = 0;
|
||||
|
||||
|
@ -82,7 +84,7 @@ static void sendClientMessage(Window w, Atom a, long x){
|
|||
|
||||
There's not much to know about this class, it's completley handled by
|
||||
the abstract class Client. You get access to the window wrapper with
|
||||
Client:.windowWrapper(). The big advantage of WindowWrapper is,
|
||||
Client::windowWrapper(). The big advantage of WindowWrapper is,
|
||||
that you can use just like a normal QWidget, although it encapsulates
|
||||
an X window that belongs to another application.
|
||||
|
||||
|
@ -823,6 +825,7 @@ void Client::mouseReleaseEvent( QMouseEvent * e)
|
|||
setGeometry( geom );
|
||||
moveResizeMode = FALSE;
|
||||
releaseMouse();
|
||||
releaseKeyboard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1402,12 +1405,12 @@ void Client::setShade( bool s )
|
|||
*/
|
||||
void Client::setActive( bool act)
|
||||
{
|
||||
if ( act )
|
||||
workspace()->setActiveClient( this );
|
||||
|
||||
if ( active == act )
|
||||
return;
|
||||
|
||||
active = act;
|
||||
if ( active )
|
||||
workspace()->setActiveClient( this );
|
||||
activeChange( active );
|
||||
}
|
||||
|
||||
|
@ -1541,6 +1544,9 @@ void Client::contextHelp()
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
Performs a mouse command on this client (see options.h)
|
||||
*/
|
||||
bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPos)
|
||||
{
|
||||
bool replay = FALSE;
|
||||
|
@ -1581,6 +1587,7 @@ bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPo
|
|||
moveOffset = mapFromGlobal( globalPos );
|
||||
invertedMoveOffset = rect().bottomRight() - moveOffset;
|
||||
grabMouse( arrowCursor );
|
||||
grabKeyboard();
|
||||
if ( options->moveMode != Options::Opaque )
|
||||
XGrabServer( qt_xdisplay() );
|
||||
break;
|
||||
|
@ -1602,6 +1609,9 @@ bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPo
|
|||
invertedMoveOffset = rect().bottomRight() - moveOffset;
|
||||
setMouseCursor( mode );
|
||||
grabMouse( cursor() );
|
||||
grabKeyboard();
|
||||
resizeHorizontalDirectionFixed = FALSE;
|
||||
resizeVerticalDirectionFixed = FALSE;
|
||||
if ( options->resizeMode != Options::Opaque )
|
||||
XGrabServer( qt_xdisplay() );
|
||||
break;
|
||||
|
@ -1615,6 +1625,98 @@ bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPo
|
|||
}
|
||||
|
||||
|
||||
void Client::keyPressEvent( QKeyEvent * e )
|
||||
{
|
||||
if ( !isMove() && !isResize() )
|
||||
return;
|
||||
bool is_control = e->state() & ControlButton;
|
||||
int delta = is_control?1:8;
|
||||
QPoint pos = QCursor::pos();
|
||||
switch ( e->key() ) {
|
||||
case Key_Left:
|
||||
pos.rx() -= delta;
|
||||
if ( pos.x() <= workspace()->geometry().left() ) {
|
||||
moveOffset.rx() += delta;
|
||||
invertedMoveOffset.rx() += delta;
|
||||
}
|
||||
if ( isResize() && !resizeHorizontalDirectionFixed ) {
|
||||
resizeHorizontalDirectionFixed = TRUE;
|
||||
if ( mode == BottomRight )
|
||||
mode = BottomLeft;
|
||||
else if ( mode == TopRight )
|
||||
mode = TopLeft;
|
||||
setMouseCursor( mode );
|
||||
grabMouse( cursor() );
|
||||
}
|
||||
break;
|
||||
case Key_Right:
|
||||
pos.rx() += delta;
|
||||
if ( pos.x() >= workspace()->geometry().right() ) {
|
||||
moveOffset.rx() -= delta;
|
||||
invertedMoveOffset.rx() -= delta;
|
||||
}
|
||||
if ( isResize() && !resizeHorizontalDirectionFixed ) {
|
||||
resizeHorizontalDirectionFixed = TRUE;
|
||||
if ( mode == BottomLeft )
|
||||
mode = BottomRight;
|
||||
else if ( mode == TopLeft )
|
||||
mode = TopRight;
|
||||
setMouseCursor( mode );
|
||||
grabMouse( cursor() );
|
||||
}
|
||||
break;
|
||||
case Key_Up:
|
||||
pos.ry() -= delta;
|
||||
if ( pos.y() <= workspace()->geometry().top() ) {
|
||||
moveOffset.ry() += delta;
|
||||
invertedMoveOffset.ry() += delta;
|
||||
}
|
||||
if ( isResize() && !resizeVerticalDirectionFixed ) {
|
||||
resizeVerticalDirectionFixed = TRUE;
|
||||
if ( mode == BottomLeft )
|
||||
mode = TopLeft;
|
||||
else if ( mode == BottomRight )
|
||||
mode = TopRight;
|
||||
setMouseCursor( mode );
|
||||
grabMouse( cursor() );
|
||||
}
|
||||
break;
|
||||
case Key_Down:
|
||||
pos.ry() += delta;
|
||||
if ( pos.y() >= workspace()->geometry().bottom() ) {
|
||||
moveOffset.ry() -= delta;
|
||||
invertedMoveOffset.ry() -= delta;
|
||||
}
|
||||
if ( isResize() && !resizeVerticalDirectionFixed ) {
|
||||
resizeVerticalDirectionFixed = TRUE;
|
||||
if ( mode == TopLeft )
|
||||
mode = BottomLeft;
|
||||
else if ( mode == TopRight )
|
||||
mode = BottomRight;
|
||||
setMouseCursor( mode );
|
||||
grabMouse( cursor() );
|
||||
}
|
||||
break;
|
||||
case Key_Space:
|
||||
case Key_Return:
|
||||
case Key_Enter:
|
||||
clearbound();
|
||||
if ( ( isMove() && options->moveMode != Options::Opaque )
|
||||
|| ( isResize() && options->resizeMode != Options::Opaque ) )
|
||||
XUngrabServer( qt_xdisplay() );
|
||||
setGeometry( geom );
|
||||
moveResizeMode = FALSE;
|
||||
releaseMouse();
|
||||
releaseKeyboard();
|
||||
buttonDown = FALSE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
QCursor::setPos( pos );
|
||||
}
|
||||
|
||||
|
||||
NoBorderClient::NoBorderClient( Workspace *ws, WId w, QWidget *parent, const char *name )
|
||||
: Client( ws, w, parent, name )
|
||||
{
|
||||
|
|
1
client.h
1
client.h
|
@ -147,6 +147,7 @@ protected:
|
|||
void mousePressEvent( QMouseEvent * );
|
||||
void mouseReleaseEvent( QMouseEvent * );
|
||||
void mouseMoveEvent( QMouseEvent * );
|
||||
void keyPressEvent( QKeyEvent * );
|
||||
void resizeEvent( QResizeEvent * );
|
||||
virtual void windowWrapperShowEvent( QShowEvent* ){}
|
||||
virtual void windowWrapperHideEvent( QHideEvent* ){}
|
||||
|
|
|
@ -15,3 +15,7 @@
|
|||
keys->insertItem(i18n("Window maximize horizontal"),"Window maximize horizontal", "");
|
||||
keys->insertItem(i18n("Window iconify"),"Window iconify", "");
|
||||
keys->insertItem(i18n("Window shade"),"Window shade", "");
|
||||
keys->insertItem(i18n("Window move"),"Window move", "");
|
||||
keys->insertItem(i18n("Window resize"),"Window resize", "");
|
||||
|
||||
keys->insertItem(i18n("Mouse emulation"),"Mouse emulation", "F12");
|
||||
|
|
227
workspace.cpp
227
workspace.cpp
|
@ -18,6 +18,7 @@
|
|||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/keysymdef.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
|
||||
extern Time kwin_time;
|
||||
|
@ -120,6 +121,7 @@ Workspace::Workspace()
|
|||
|
||||
control_grab = FALSE;
|
||||
tab_grab = FALSE;
|
||||
mouse_emulation = FALSE;
|
||||
tab_box = new TabBox( this );
|
||||
}
|
||||
|
||||
|
@ -235,6 +237,11 @@ Workspace::~Workspace()
|
|||
*/
|
||||
bool Workspace::workspaceEvent( XEvent * e )
|
||||
{
|
||||
if ( mouse_emulation && e->type == ButtonPress || e->type == ButtonRelease ) {
|
||||
mouse_emulation = FALSE;
|
||||
XUngrabKeyboard( qt_xdisplay(), kwin_time );
|
||||
}
|
||||
|
||||
Client * c = findClient( e->xany.window );
|
||||
if ( c )
|
||||
return c->windowEvent( e );
|
||||
|
@ -349,9 +356,20 @@ bool Workspace::workspaceEvent( XEvent * e )
|
|||
}
|
||||
break;
|
||||
case KeyPress:
|
||||
if ( QWidget::keyboardGrabber() ) {
|
||||
freeKeyboard( FALSE );
|
||||
break;
|
||||
}
|
||||
if ( mouse_emulation )
|
||||
return keyPressMouseEmulation( e->xkey );
|
||||
return keyPress(e->xkey);
|
||||
break;
|
||||
case KeyRelease:
|
||||
if ( QWidget::keyboardGrabber() ) {
|
||||
freeKeyboard( FALSE );
|
||||
break;
|
||||
}
|
||||
if ( mouse_emulation )
|
||||
return FALSE;
|
||||
return keyRelease(e->xkey);
|
||||
break;
|
||||
case FocusIn:
|
||||
|
@ -832,6 +850,8 @@ void Workspace::requestFocus( Client* c)
|
|||
if ( !popup || !popup->isVisible() )
|
||||
popup_client = c;
|
||||
|
||||
active_client = c;
|
||||
|
||||
if ( c->isVisible() && !c->isShade() ) {
|
||||
c->takeFocus();
|
||||
should_get_focus = c;
|
||||
|
@ -916,6 +936,12 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op )
|
|||
return;
|
||||
|
||||
switch ( op ) {
|
||||
case Options::MoveOp:
|
||||
c->performMouseCommand( Options::MouseMove, QCursor::pos() );
|
||||
break;
|
||||
case Options::ResizeOp:
|
||||
c->performMouseCommand( Options::MouseResize, QCursor::pos() );
|
||||
break;
|
||||
case Options::CloseOp:
|
||||
c->closeWindow();
|
||||
break;
|
||||
|
@ -935,8 +961,7 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op )
|
|||
|
||||
void Workspace::clientPopupActivated( int id )
|
||||
{
|
||||
if ( popup_client )
|
||||
performWindowOperation( popup_client, (Options::WindowOperation) id );
|
||||
performWindowOperation( popup_client, (Options::WindowOperation) id );
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1499,6 +1524,11 @@ void Workspace::propagateClients( bool onlyStacking )
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
Check whether \a w is a dock window. If so, add it to the respective
|
||||
datastructures and propagate it to the world.
|
||||
*/
|
||||
bool Workspace::addDockwin( WId w )
|
||||
{
|
||||
WId dockFor = 0;
|
||||
|
@ -1512,6 +1542,10 @@ bool Workspace::addDockwin( WId w )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*!
|
||||
Check whether \a w is a dock window. If so, remove it from the
|
||||
respective datastructures and propagate this to the world.
|
||||
*/
|
||||
bool Workspace::removeDockwin( WId w )
|
||||
{
|
||||
if ( !dockwins.contains( w ) )
|
||||
|
@ -1521,6 +1555,12 @@ bool Workspace::removeDockwin( WId w )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns whether iconify means actually withdraw for client \a. This
|
||||
is TRUE for clients that have a docking window. In that case the
|
||||
docking window will serve as icon replacement.
|
||||
*/
|
||||
bool Workspace::iconifyMeansWithdraw( Client* c)
|
||||
{
|
||||
for ( DockWindowList::ConstIterator it = dockwins.begin(); it != dockwins.end(); ++it ) {
|
||||
|
@ -1547,6 +1587,9 @@ void Workspace::propagateDockwins()
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
Create the global accel object \c keys.
|
||||
*/
|
||||
void Workspace::createKeybindings(){
|
||||
keys = new KGlobalAccel();
|
||||
|
||||
|
@ -1568,7 +1611,10 @@ void Workspace::createKeybindings(){
|
|||
keys->connectItem( "Window maximize vertical", this, SLOT( slotWindowMaximizeVertical() ) );
|
||||
keys->connectItem( "Window iconify", this, SLOT( slotWindowIconify() ) );
|
||||
keys->connectItem( "Window shade", this, SLOT( slotWindowShade() ) );
|
||||
keys->connectItem( "Window move", this, SLOT( slotWindowMove() ) );
|
||||
keys->connectItem( "Window resize", this, SLOT( slotWindowResize() ) );
|
||||
|
||||
keys->connectItem( "Mouse emulation", this, SLOT( slotMouseEmulation() ) );
|
||||
keys->readSettings();
|
||||
}
|
||||
|
||||
|
@ -1598,33 +1644,70 @@ void Workspace::slotSwitchDesktop8(){
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
Maximizes the popup client
|
||||
*/
|
||||
void Workspace::slotWindowMaximize()
|
||||
{
|
||||
if ( popup_client )
|
||||
popup_client->maximize( Client::MaximizeFull );
|
||||
}
|
||||
|
||||
/*!
|
||||
Maximizes the popup client vertically
|
||||
*/
|
||||
void Workspace::slotWindowMaximizeVertical()
|
||||
{
|
||||
if ( popup_client )
|
||||
popup_client->maximize( Client::MaximizeVertical );
|
||||
}
|
||||
|
||||
/*!
|
||||
Maximizes the popup client horiozontally
|
||||
*/
|
||||
void Workspace::slotWindowMaximizeHorizontal()
|
||||
{
|
||||
if ( popup_client )
|
||||
popup_client->maximize( Client::MaximizeHorizontal );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Iconifies the popup client
|
||||
*/
|
||||
void Workspace::slotWindowIconify()
|
||||
{
|
||||
if ( popup_client )
|
||||
popup_client->iconify();
|
||||
performWindowOperation( popup_client, Options::IconifyOp );
|
||||
}
|
||||
|
||||
/*!
|
||||
Shades/unshades the popup client respectively
|
||||
*/
|
||||
void Workspace::slotWindowShade()
|
||||
{
|
||||
if ( popup_client )
|
||||
popup_client->setShade( !popup_client->isShade() );
|
||||
performWindowOperation( popup_client, Options::ShadeOp );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Invokes keyboard mouse emulation
|
||||
*/
|
||||
void Workspace::slotMouseEmulation()
|
||||
{
|
||||
if ( XGrabKeyboard(qt_xdisplay(),
|
||||
root, FALSE,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
kwin_time) == GrabSuccess ) {
|
||||
mouse_emulation = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Adjusts the desktop popup to the current values and the location of
|
||||
the popup client.
|
||||
*/
|
||||
void Workspace::desktopPopupAboutToShow()
|
||||
{
|
||||
if ( !desk_popup )
|
||||
|
@ -1641,6 +1724,12 @@ void Workspace::desktopPopupAboutToShow()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
The client popup menu will become visible soon.
|
||||
|
||||
Adjust the items according to the respective popup client.
|
||||
*/
|
||||
void Workspace::clientPopupAboutToShow()
|
||||
{
|
||||
if ( !popup_client || !popup )
|
||||
|
@ -1649,6 +1738,10 @@ void Workspace::clientPopupAboutToShow()
|
|||
popup->setItemChecked( Options::ShadeOp, popup_client->isShade() );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Sends the activeClient() to desktop \a desk
|
||||
*/
|
||||
void Workspace::sendToDesktop( int desk )
|
||||
{
|
||||
if ( !popup_client )
|
||||
|
@ -1677,6 +1770,10 @@ void Workspace::sendToDesktop( int desk )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Shows the window operations popup menu for the activeClient()
|
||||
*/
|
||||
void Workspace::slotWindowOperations()
|
||||
{
|
||||
if ( !active_client )
|
||||
|
@ -1685,14 +1782,34 @@ void Workspace::slotWindowOperations()
|
|||
p->popup( active_client->mapToGlobal( active_client->windowWrapper()->geometry().topLeft() ) );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Closes the popup client
|
||||
*/
|
||||
void Workspace::slotWindowClose()
|
||||
{
|
||||
if ( popup_client )
|
||||
popup_client->closeWindow();
|
||||
performWindowOperation( popup_client, Options::CloseOp );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/*!
|
||||
Starts keyboard move mode for the popup client
|
||||
*/
|
||||
void Workspace::slotWindowMove()
|
||||
{
|
||||
performWindowOperation( popup_client, Options::MoveOp );
|
||||
}
|
||||
|
||||
/*!
|
||||
Starts keyboard resize mode for the popup client
|
||||
*/
|
||||
void Workspace::slotWindowResize()
|
||||
{
|
||||
performWindowOperation( popup_client, Options::ResizeOp );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Client \a c is moved around to position \a pos. This gives the
|
||||
workspace the opportunity to interveniate and to implement
|
||||
snap-to-windows functionality.
|
||||
|
@ -1793,3 +1910,93 @@ QPoint Workspace::adjustClientPosition( Client* c, QPoint pos )
|
|||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Handles keypress event during mouse emulation
|
||||
*/
|
||||
bool Workspace::keyPressMouseEmulation( XKeyEvent key )
|
||||
{
|
||||
if ( root != qt_xrootwin() )
|
||||
return FALSE;
|
||||
int kc = XKeycodeToKeysym(qt_xdisplay(), key.keycode, 0);
|
||||
int km = key.state & (ControlMask | Mod1Mask | ShiftMask);
|
||||
|
||||
bool is_control = km & ControlMask;
|
||||
bool is_alt = km & Mod1Mask;
|
||||
int delta = is_control?1:is_alt?32:8;
|
||||
QPoint pos = QCursor::pos();
|
||||
|
||||
switch ( kc ) {
|
||||
case XK_Left:
|
||||
case XK_KP_Left:
|
||||
pos.rx() -= delta;
|
||||
break;
|
||||
case XK_Right:
|
||||
case XK_KP_Right:
|
||||
pos.rx() += delta;
|
||||
break;
|
||||
case XK_Up:
|
||||
case XK_KP_Up:
|
||||
pos.ry() -= delta;
|
||||
break;
|
||||
case XK_Down:
|
||||
case XK_KP_Down:
|
||||
pos.ry() += delta;
|
||||
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 );
|
||||
}
|
||||
}
|
||||
// fall through
|
||||
case XK_Escape:
|
||||
XUngrabKeyboard(qt_xdisplay(), kwin_time);
|
||||
mouse_emulation = FALSE;
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
QCursor::setPos( pos );
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -123,7 +123,10 @@ public slots:
|
|||
|
||||
void slotWindowOperations();
|
||||
void slotWindowClose();
|
||||
void slotWindowMove();
|
||||
void slotWindowResize();
|
||||
|
||||
void slotMouseEmulation();
|
||||
|
||||
private slots:
|
||||
void setDecorationStyle( int );
|
||||
|
@ -135,6 +138,7 @@ private slots:
|
|||
protected:
|
||||
bool keyPress( XKeyEvent key );
|
||||
bool keyRelease( XKeyEvent key );
|
||||
bool keyPressMouseEmulation( XKeyEvent key );
|
||||
bool clientMessage( XClientMessageEvent msg );
|
||||
|
||||
private:
|
||||
|
@ -148,6 +152,7 @@ private:
|
|||
Client* active_client;
|
||||
bool control_grab;
|
||||
bool tab_grab;
|
||||
bool mouse_emulation;
|
||||
TabBox* tab_box;
|
||||
void freeKeyboard(bool pass);
|
||||
QGuardedPtr<Client> popup_client;
|
||||
|
|
Loading…
Reference in a new issue