focus policies and alt-tab style:

/*!
      Different focus policies:
      <ul>

      <li>ClickToFocus - Clicking into a window activates it. This is
      also the default.

      <li>FocusFollowsMouse - Moving the mouse pointer actively onto a
      normal window activates it. For convenience, the desktop and
      windows on the dock are excluded. They require clicking.

      <li>FocusUnderMouse - The window that happens to be under the
      mouse pointer becomes active. The invariant is: no window can
      have focus that is not under the mouse. This also means that
      Alt-Tab won't work properly and popup dialogs are usually
      unsable with the keyboard. Note that the desktop and windows on
      the dock are excluded for convenience. They get focus only when
      clicking on it.

      <li>FocusStrictlyUnderMouse - this is even worse than
      FocusUnderMouse. Only the window under the mouse pointer is
      active. If the mouse points nowhere, nothing has the focus. If
      the mouse points onto the desktop, the desktop has focus. The
      same holds for windows on the dock.

      Note that FocusUnderMouse and FocusStrictlyUnderMouse are not
      particulary useful. They are only provided for old-fashined
      die-hard UNIX people ;-)

      </ul>
     */
FocusPolicy=ClickToFocus | FocusFollowsMouse | FocusUnderMouse | FocusStrictlyUnderMouse


    /**
       Different Alt-Tab-Styles:
       <ul>

       <li> KDE - the recommended KDE style. Alt-Tab opens a nice icon
       box that makes it easy to select the window you want to tab
       to. The order automatically adjusts to the most recently used
       windows. Note that KDE style does not work with the
       FocusUnderMouse and FocusStrictlyUnderMouse focus
       policies. Choose ClickToFocus or FocusFollowsMouse instead.

       <li> CDE - the old-fashion CDE style. Alt-Tab cycles between
       the windows in static order. The current window gets raised,
       the previous window gets lowered.

       </ul>
     */
AltTabStyle=KDE | CDE

svn path=/trunk/kdebase/kwin/; revision=54010
This commit is contained in:
Matthias Ettrich 2000-06-22 18:08:35 +00:00
parent 4ea2a5c27f
commit 6655d0207d
7 changed files with 221 additions and 111 deletions

66
README
View file

@ -7,15 +7,71 @@ Currently supported options in the kwinrc:
[Windows]
MoveMode=Opaque|Transparent
ResizeMode=Opaque|Transparent
Placement=Smart|Random|Cascade
MoveMode=Opaque |Transparent
ResizeMode=Opaque |Transparent
Placement=Smart | Random | Cascade
AnimateShade=true|false
AnimSteps=<integer=20>
BorderSnapZone=<integer=10>
WindowSnapZone=<integer=10>
TitlebarDoubleClickCommand=Move|Resize|
Maximize|Iconify|Close|Sticky|Shade|Operations
TitlebarDoubleClickCommand=Move | Resize |
Maximize | Iconify | Close | Sticky | Shade | Operations
/*!
Different focus policies:
<ul>
<li>ClickToFocus - Clicking into a window activates it. This is
also the default.
<li>FocusFollowsMouse - Moving the mouse pointer actively onto a
normal window activates it. For convenience, the desktop and
windows on the dock are excluded. They require clicking.
<li>FocusUnderMouse - The window that happens to be under the
mouse pointer becomes active. The invariant is: no window can
have focus that is not under the mouse. This also means that
Alt-Tab won't work properly and popup dialogs are usually
unsable with the keyboard. Note that the desktop and windows on
the dock are excluded for convenience. They get focus only when
clicking on it.
<li>FocusStrictlyUnderMouse - this is even worse than
FocusUnderMouse. Only the window under the mouse pointer is
active. If the mouse points nowhere, nothing has the focus. If
the mouse points onto the desktop, the desktop has focus. The
same holds for windows on the dock.
Note that FocusUnderMouse and FocusStrictlyUnderMouse are not
particulary useful. They are only provided for old-fashined
die-hard UNIX people ;-)
</ul>
*/
FocusPolicy=ClickToFocus | FocusFollowsMouse | FocusUnderMouse | FocusStrictlyUnderMouse
/**
Different Alt-Tab-Styles:
<ul>
<li> KDE - the recommended KDE style. Alt-Tab opens a nice icon
box that makes it easy to select the window you want to tab
to. The order automatically adjusts to the most recently used
windows. Note that KDE style does not work with the
FocusUnderMouse and FocusStrictlyUnderMouse focus
policies. Choose ClickToFocus or FocusFollowsMouse instead.
<li> CDE - the old-fashion CDE style. Alt-Tab cycles between
the windows in static order. The current window gets raised,
the previous window gets lowered.
</ul>
*/
AltTabStyle=KDE | CDE
[MouseBindings]

View file

@ -1052,7 +1052,7 @@ void Client::mouseMoveEvent( QMouseEvent * e)
return;
}
if ( !mayMove()) return;
if ( !isMovable()) return;
if ( !moveResizeMode )
{
@ -1326,7 +1326,7 @@ void Client::invalidateWindow()
void Client::iconify()
{
if (!mayMove())
if (!isMovable())
return;
if ( isShade() )
@ -1371,7 +1371,7 @@ void Client::killWindow()
void Client::maximize( MaximizeMode m)
{
if (!mayMove())
if (!isMovable())
return;
QRect clientArea = workspace()->clientArea();
@ -1423,9 +1423,6 @@ void Client::maximize( MaximizeMode m)
void Client::toggleSticky()
{
if (!mayMove())
return;
setSticky( !isSticky() );
}
@ -1514,23 +1511,28 @@ void Client::gravitate( bool invert )
/*!
Reimplement to handle crossing events (qt should provide xroot, yroot)
Crossing events are necessary for the focus-follows-mouse focus
policies, to do proper activation and deactivation.
*/
bool Client::x11Event( XEvent * e)
{
if ( e->type == EnterNotify ) {
if (( options->focusPolicy != Options::ClickToFocus ) &&
(( options->focusPolicy != Options::FocusFollowsMouse) ||
!passiveFocus()))
workspace()->requestFocus( this );
if ( e->type == EnterNotify && e->xcrossing.mode == NotifyNormal ) {
if ( options->focusPolicy == Options::ClickToFocus )
return TRUE;
if ( options->focusPolicy != Options::FocusStrictlyUnderMouse && ( isDesktop() || isDock() ) )
return TRUE;
workspace()->requestFocus( this );
return TRUE;
}
if ( e->type == LeaveNotify ) {
if ( e->type == LeaveNotify && e->xcrossing.mode == NotifyNormal ) {
if ( !buttonDown )
setCursor( arrowCursor );
if ( options->focusPolicy == Options::FocusStrictlyUnderMouse ) {
if ( options->focusPolicy == Options::FocusStrictlyUnderMouse )
if ( isActive() && !rect().contains( QPoint( e->xcrossing.x, e->xcrossing.y ) ) )
workspace()->requestFocus( 0 ) ;
}
return TRUE;
}
return FALSE;
@ -1613,7 +1615,7 @@ bool Client::isShade() const
void Client::setShade( bool s )
{
if (!mayMove())
if (!isMovable())
return;
if ( shaded == s )
@ -1864,7 +1866,7 @@ bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPo
replay = TRUE;
break;
case Options::MouseMove:
if (!mayMove())
if (!isMovable())
break;
mode = Center;
moveResizeMode = TRUE;
@ -1878,7 +1880,7 @@ bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPo
XGrabServer( qt_xdisplay() );
break;
case Options::MouseResize:
if (!mayMove())
if (!isMovable())
break;
moveResizeMode = TRUE;
workspace()->setEnableFocusChange(false);
@ -2070,6 +2072,35 @@ void Client::activateLayout()
}
NET::WindowType Client::windowType() const
{
NET::WindowType wt = info->windowType();
if ( wt == NET::Unknown )
wt = NET::Normal;
return wt;
}
bool Client::wantsTabFocus() const
{
return windowType() == NET::Normal;
}
bool Client::isMovable() const
{
return windowType() == NET::Normal || windowType() == NET::Toolbar;
}
bool Client::isDesktop() const
{
return windowType() == NET::Desktop;
}
bool Client::isDock() const
{
return windowType() == NET::Dock;
}
/*!
Returns \a area with the client's strut taken into account.

View file

@ -11,6 +11,7 @@ Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
#include <qvbox.h>
#include <qpixmap.h>
#include <qtimer.h>
#include <netwm_def.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@ -69,6 +70,7 @@ public:
WId transientFor() const;
bool isTransient() const;
Client* mainClient();
NET::WindowType windowType() const;
virtual bool windowEvent( XEvent * );
@ -115,15 +117,12 @@ public:
bool isSticky() const;
void setSticky( bool );
bool mayMove() const { return may_move; }
void setMayMove( bool m) { may_move = m; }
/**
* A window with passive focus will only get focus when
* the user explicitly selects the window.
**/
bool passiveFocus() const { return passive_focus; }
void setPassiveFocus( bool p) { passive_focus = p; }
// auxiliary functions, depend on the windowType
bool wantsTabFocus() const;
bool isMovable() const;
bool isDesktop() const;
bool isDock() const;
void takeFocus();
@ -147,7 +146,6 @@ public:
{ move( p.x(), p.y() ); }
virtual bool wantsTabFocus() const { return TRUE;} //### just for now
bool providesContextHelp() const;
@ -155,7 +153,7 @@ public:
QCString windowRole();
QCString sessionId();
QRect adjustedClientArea( const QRect& area ) const;
public slots:
@ -235,22 +233,22 @@ private:
XSizeHints xSizeHint;
void sendSynteticConfigureNotify();
int state;
bool active;
QRect original_geometry;
QRect geom; //### TODO
bool shaded;
WId transient_for;
bool is_sticky;
bool is_shape;
bool may_move;
bool passive_focus;
void getWMHints();
void getWindowProtocols();
uint shaded :1;
uint active :1;
uint is_sticky :1;
uint is_shape :1;
uint may_move :1;
uint passive_focus :1;
uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol?
uint Ptakefocus :1;// does the window understand the TakeFocus protocol?
uint Pcontexthelp : 1; // does the window understand the ContextHelp protocol?
uint input :1; // does the window want input in its wm_hints
uint mapped :1; // keeps track of our visiblity within the asynchronous event flow
void getWMHints();
void getWindowProtocols();
QPixmap icon_pix;
QPixmap miniicon_pix;
QRect geom_restore;
@ -348,6 +346,7 @@ inline bool Client::shape() const
return is_shape;
}
inline const QRegion& Client::getMask() const
{
return mask;
@ -360,7 +359,6 @@ public:
NoBorderClient( Workspace *ws, WId w, QWidget *parent=0, const char *name=0 );
~NoBorderClient();
bool wantsTabFocus() const { return FALSE;} //### just for now
};
#endif

View file

@ -1,6 +1,6 @@
/*****************************************************************
kwin - the KDE window manager
Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
******************************************************************/
#include "options.h"
@ -134,11 +134,19 @@ void Options::reload()
QString val;
val = config->readEntry ("focusPolicy", "ClickToFocus");
if (val == "ClickToFocus")
focusPolicy = ClickToFocus;
else
val = config->readEntry ("FocusPolicy", "ClickToFocus");
focusPolicy = ClickToFocus; // what a default :-)
if ( val == "FocusFollowsMouse" )
focusPolicy = FocusFollowsMouse;
else if ( val == "FocusUnderMouse" )
focusPolicy = FocusUnderMouse;
else if ( val == "FocusStrictlyUnderMouse" )
focusPolicy = FocusStrictlyUnderMouse;
val = config->readEntry ("AltTabStyle", "KDE");
altTabStyle = KDE; // what a default :-)
if ( val == "CDE" )
altTabStyle = CDE;
val = config->readEntry("Placement","Smart");
if (val == "Smart") placement = Smart;

View file

@ -1,6 +1,6 @@
/*****************************************************************
kwin - the KDE window manager
Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
******************************************************************/
#ifndef OPTIONS_H
@ -29,15 +29,22 @@ public:
also the default.
<li>FocusFollowsMouse - Moving the mouse pointer actively onto a
window activates it.
normal window activates it. For convenience, the desktop and
windows on the dock are excluded. They require clicking.
<li>FocusUnderMouse - The window that happens to be under the
mouse pointer becomes active.
mouse pointer becomes active. The invariant is: no window can
have focus that is not under the mouse. This also means that
Alt-Tab won't work properly and popup dialogs are usually
unsable with the keyboard. Note that the desktop and windows on
the dock are excluded for convenience. They get focus only when
clicking on it.
<li>FocusStrictlyUnderMouse - Only the window under the mouse
pointer is active. If the mouse points nowhere, nothing has the
focus. In practice, this is the same as FocusUnderMouse, since
kdesktop can take the focus.
<li>FocusStrictlyUnderMouse - this is even worse than
FocusUnderMouse. Only the window under the mouse pointer is
active. If the mouse points nowhere, nothing has the focus. If
the mouse points onto the desktop, the desktop has focus. The
same holds for windows on the dock.
Note that FocusUnderMouse and FocusStrictlyUnderMouse are not
particulary useful. They are only provided for old-fashined
@ -48,15 +55,32 @@ public:
enum FocusPolicy { ClickToFocus, FocusFollowsMouse, FocusUnderMouse, FocusStrictlyUnderMouse };
FocusPolicy focusPolicy;
enum MoveResizeMode { Transparent, Opaque };
/**
* Basic color types that should be recognized by all decoration styles.
* Not all styles have to implement all the colors, but for the ones that
* are implemented you should retrieve them here.
Different Alt-Tab-Styles:
<ul>
<li> KDE - the recommended KDE style. Alt-Tab opens a nice icon
box that makes it easy to select the window you want to tab
to. The order automatically adjusts to the most recently used
windows. Note that KDE style does not work with the
FocusUnderMouse and FocusStrictlyUnderMouse focus
policies. Choose ClickToFocus or FocusFollowsMouse instead.
<li> CDE - the old-fashion CDE style. Alt-Tab cycles between
the windows in static order. The current window gets raised,
the previous window gets lowered.
</ul>
*/
// increment KWINCOLORS if you add something (mosfet)
enum ColorType{TitleBar=0, TitleBlend, Font, ButtonBg, Frame, Handle};
enum AltTabStyle { KDE, CDE };
AltTabStyle altTabStyle;
/**
MoveResizeMode, either Tranparent or Opaque.
*/
enum MoveResizeMode { Transparent, Opaque };
MoveResizeMode resizeMode;
MoveResizeMode moveMode;
@ -74,6 +98,14 @@ public:
return focusPolicy == ClickToFocus || focusPolicy == FocusFollowsMouse;
}
/**
* Basic color types that should be recognized by all decoration styles.
* Not all styles have to implement all the colors, but for the ones that
* are implemented you should retrieve them here.
*/
// increment KWINCOLORS if you add something (mosfet)
enum ColorType{TitleBar=0, TitleBlend, Font, ButtonBg, Frame, Handle};
/**
* Return the color for the given decoration.
*/

View file

@ -174,25 +174,14 @@ Client* Workspace::clientFactory( WId w )
XLowerWindow( qt_xdisplay(), w );
Client * c = new NoBorderClient( this, w);
c->setSticky( TRUE );
c->setMayMove( FALSE );
setDesktopClient( c );
c->setPassiveFocus( TRUE );
return c;
}
case NET::Menu:
case NET::Dock: {
Client * c = new NoBorderClient( this, w);
c->setSticky( TRUE );
c->setMayMove( FALSE );
c->setPassiveFocus( TRUE );
return c;
}
case NET::Menu: {
Client * c = new NoBorderClient( this, w);
c->setSticky( TRUE );
c->setMayMove( FALSE );
c->setPassiveFocus( TRUE );
return c;
}
@ -665,8 +654,6 @@ bool Workspace::keyPress(XKeyEvent key)
int kc = XKeycodeToKeysym(qt_xdisplay(), key.keycode, 0);
int km = key.state & (ControlMask | Mod1Mask | ShiftMask);
const bool options_alt_tab_mode_is_CDE_style = FALSE; // TODO
if (!control_grab){
if( (kc == XK_Tab) &&
@ -674,7 +661,7 @@ bool Workspace::keyPress(XKeyEvent key)
|| km == (Mod1Mask)
)){
if (!tab_grab){
if (options_alt_tab_mode_is_CDE_style ){
if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable() ){
// CDE style raise / lower
Client* c = topClientOnDesktop();
Client* nc = c;
@ -683,7 +670,7 @@ bool Workspace::keyPress(XKeyEvent key)
nc = previousStaticClient(nc);
} while (nc && nc != c &&
(!nc->isOnDesktop(currentDesktop()) ||
nc->isIconified()));
nc->isIconified() || !nc->wantsTabFocus() ) );
}
else
@ -691,11 +678,15 @@ bool Workspace::keyPress(XKeyEvent key)
nc = nextStaticClient(nc);
} while (nc && nc != c &&
(!nc->isOnDesktop(currentDesktop()) ||
nc->isIconified()));
nc->isIconified() || !nc->wantsTabFocus() ) );
if (c && c != nc)
;//TODO lowerClient(c);
if (nc)
activateClient( nc );
lowerClient( c, false );
if (nc) {
if ( options->focusPolicyIsReasonable() )
activateClient( nc );
else
raiseClient( nc );
}
freeKeyboard(FALSE);
return TRUE;
}
@ -725,10 +716,6 @@ bool Workspace::keyPress(XKeyEvent key)
( km == (ControlMask | ShiftMask)
|| km == (ControlMask)
)){
//TODO if (!options.ControlTab){
// freeKeyboard(TRUE);
// return TRUE;
// }
if (!control_grab){
XGrabPointer( qt_xdisplay(), root, TRUE,
(uint)(ButtonPressMask | ButtonReleaseMask |
@ -872,14 +859,16 @@ Client* Workspace::previousStaticClient( Client* c ) const
}
/*!
Returns topmost visible client within the specified layer range on
the current desktop, or 0 if no clients are visible. \a fromLayer has to
be smaller than \a toLayer.
/*!
Returns topmost visible client. Windows on the dock and the
desktop are excluded.
*/
Client* Workspace::topClientOnDesktop( int fromLayer, int toLayer) const
Client* Workspace::topClientOnDesktop() const
{
fromLayer = toLayer = 0;
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
if ( !(*it)->isDesktop() && !(*it)->isDock() )
return *it;
}
return 0;
}
@ -1439,7 +1428,7 @@ void Workspace::cascadeDesktop()
if((!(*it)->isOnDesktop(currentDesktop())) ||
((*it)->isIconified()) ||
((*it)->isSticky()) ||
(!(*it)->mayMove()) )
(!(*it)->isMovable()) )
continue;
cascadePlacement(*it);
}
@ -1456,7 +1445,7 @@ void Workspace::unclutterDesktop()
if((!(*it)->isOnDesktop(currentDesktop())) ||
((*it)->isIconified()) ||
((*it)->isSticky()) ||
(!(*it)->mayMove()) )
(!(*it)->isMovable()) )
continue;
smartPlacement(*it);
}
@ -1684,7 +1673,7 @@ void Workspace::setCurrentDesktop( int new_desktop ){
if (options->focusPolicy == Options::FocusFollowsMouse) {
// Search in focus chain
for( ClientList::ConstIterator it = focus_chain.fromLast(); it != focus_chain.end(); --it) {
if ( (*it)->isVisible() && !(*it)->passiveFocus() ) {
if ( (*it)->isVisible() ) {
c = *it;
break;
}
@ -1695,7 +1684,7 @@ void Workspace::setCurrentDesktop( int new_desktop ){
if (!c) {
// Search top-most visible window
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
if ( (*it)->isVisible() && !(*it)->passiveFocus() ) {
if ( (*it)->isVisible() ) {
c = *it;
break;
}
@ -2072,7 +2061,7 @@ void Workspace::slotWindowOperations()
{
if ( !active_client )
return;
if ( !active_client->mayMove())
if ( !active_client->isMovable())
return;
QPopupMenu* p = clientPopup( active_client );
@ -2512,6 +2501,10 @@ SessionInfo* Workspace::takeSessionInfo( Client* c )
Updates the current client area according to the current clients.
If the area changes, the new area is propagate to the world.
The client area is the area that is available for clients (that
which is not taken by windows like panels, the top-of-screen menu
etc).
\sa clientArea()
*/
@ -2537,8 +2530,12 @@ void Workspace::updateClientArea()
}
/*!
Returns the current client area
/*!
returns the area available for clients. This is the desktop
geometry minus windows on the dock. Placement algorithms should
refer to this rather than geometry().
\sa geometry()
*/
QRect Workspace::clientArea()
{

View file

@ -92,12 +92,6 @@ public:
QRect geometry() const;
/**
* @return the area available for clients. This is the desktop
* geometry adjusted for edge-anchored windows.
* Placement algorithms should refer to this rather than geometry().
* @sa geometry()
*/
QRect clientArea();
bool destroyClient( Client* );
@ -152,8 +146,7 @@ public:
*/
const ClientList& stackingOrder() const;
//#### TODO right layers as default
Client* topClientOnDesktop( int fromLayer = 0, int toLayer = 0) const;
Client* topClientOnDesktop() const;
QPopupMenu* clientPopup( Client* );
@ -172,11 +165,6 @@ public:
SessionInfo* takeSessionInfo( Client* );
/**
* When the area that is available for clients (that which is not
* taken by windows like panels, the top-of-screen menu etc) may
* have changed, this will recalculate the available space.
*/
virtual void updateClientArea();