Allow window tabbing titlebar actions to be configurable; Set default

middle-click titlebar action to tab drag; Fix KCM config file corruption
caused by r1015273.
BUG: 214898

svn path=/trunk/KDE/kdebase/workspace/; revision=1050309
This commit is contained in:
Lucas Murray 2009-11-17 07:17:49 +00:00
parent f11a5ad36f
commit 00e131a1a5
17 changed files with 118 additions and 44 deletions

View file

@ -268,4 +268,9 @@ void Bridge::displayClientMenu( int index, const QPoint& pos )
c->clientGroup()->displayClientMenu( index, pos );
}
KDecoration::WindowOperation Bridge::buttonToWindowOperation( Qt::MouseButtons button )
{
return c->mouseButtonToWindowOperation( button );
}
} // namespace

View file

@ -89,6 +89,7 @@ class Bridge : public KDecorationBridgeUnstable
virtual void closeClientGroupItem( int index );
virtual void closeAllInClientGroup();
virtual void displayClientMenu( int index, const QPoint& pos );
virtual WindowOperation buttonToWindowOperation( Qt::MouseButtons button );
private:
Client* c;

View file

@ -247,6 +247,7 @@ class Client
KShortcut shortcut() const;
void setShortcut( const QString& cut );
WindowOperation mouseButtonToWindowOperation( Qt::MouseButtons button );
bool performMouseCommand( Options::MouseCommand, const QPoint& globalPos, bool handled = false );
QRect adjustedClientArea( const QRect& desktop, const QRect& area ) const;
@ -410,7 +411,8 @@ class Client
bool buttonReleaseEvent( Window w, int button, int state, int x, int y, int x_root, int y_root );
bool motionNotifyEvent( Window w, int state, int x, int y, int x_root, int y_root );
void processDecorationButtonPress( int button, int state, int x, int y, int x_root, int y_root );
bool processDecorationButtonPress( int button, int state, int x, int y, int x_root, int y_root,
bool ignoreMenu = false );
protected:
virtual void debug( kdbgstream& stream ) const;

View file

@ -1393,21 +1393,16 @@ namespace Oxygen
QPoint point = event->pos();
if( itemClicked( point ) < 0 ) return false;
mouseButton_ = event->button();
bool accepted( false );
if( event->button() == Qt::MidButton )
if( buttonToWindowOperation( mouseButton_ ) == ClientGroupDragOp )
{
dragPoint_ = point;
mouseButton_ = Qt::MidButton;
accepted = true;
} else if( event->button() == Qt::LeftButton ) {
} else if( buttonToWindowOperation( mouseButton_ ) == OperationsOp ) {
mouseButton_ = Qt::LeftButton;
} else if( event->button() == Qt::RightButton ) {
mouseButton_ = Qt::RightButton;
accepted = true;
}
@ -1419,8 +1414,8 @@ namespace Oxygen
{
bool accepted( false );
if( ( mouseButton_ == Qt::LeftButton && event->button() == Qt::LeftButton ) ||
( mouseButton_ == Qt::MidButton && event->button() == Qt::MidButton ) )
if( mouseButton_ == event->button() &&
buttonToWindowOperation( mouseButton_ ) != OperationsOp )
{
QPoint point = event->pos();
@ -1434,7 +1429,8 @@ namespace Oxygen
accepted = true;
}
} else if( mouseButton_ == Qt::RightButton && event->button() == Qt::RightButton ) {
} else if( mouseButton_ == event->button() &&
buttonToWindowOperation( mouseButton_ ) == OperationsOp ) {
QPoint point = event->pos();
int itemClicked( OxygenClient::itemClicked( point ) );
@ -1456,7 +1452,7 @@ namespace Oxygen
{ return false; }
bool accepted( false );
if( mouseButton_ == Qt::MidButton )
if( buttonToWindowOperation( mouseButton_ ) == ClientGroupDragOp )
{
QPoint point = event->pos();

View file

@ -252,22 +252,15 @@ bool TabstripDecoration::eventFilter( QObject* o, QEvent* e )
else if( e->type() == QEvent::Drop && widget() == o )
state = dropEvent( static_cast< QDropEvent* >( e ) );
else if( TabstripButton *btn = dynamic_cast< TabstripButton* >( o ) )
if( TabstripButton *btn = dynamic_cast< TabstripButton* >( o ) )
{
if( e->type() == QEvent::MouseButtonRelease )
{
if( static_cast<QMouseEvent*>(e)->button() == Qt::LeftButton )
{ closeClientGroupItem( closeButtons.indexOf( btn ) ); }
return true;
}
if( TabstripButton *btn = dynamic_cast< TabstripButton* >( o ) )
if( e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseMove )
{
QMouseEvent *past = static_cast< QMouseEvent* >( e );
QPoint point = btn->mapToParent( past->pos() );
QMouseEvent *ev = new QMouseEvent( past->type(), point, past->button(), past->buttons(), past->modifiers() );
e = dynamic_cast< QEvent* >( ev );
o = widget();
}
}
return state || KCommonDecorationUnstable::eventFilter( o, e );
}
@ -275,12 +268,11 @@ bool TabstripDecoration::mouseButtonPressEvent( QMouseEvent* e )
{
click = widget()->mapToParent( e->pos() );
int item = itemClicked( click );
if( item >= 0 &&
( e->button() == Qt::MidButton || e->button() == Qt::LeftButton || e->button() == Qt::RightButton ))
if( item >= 0 )
{
click_in_progress = true;
button = e->button();
return button != Qt::LeftButton;
return true;
}
click_in_progress = false;
return false;
@ -293,9 +285,9 @@ bool TabstripDecoration::mouseButtonReleaseEvent( QMouseEvent* e )
if( click_in_progress && item >= 0 )
{
click_in_progress = false;
if( e->button() == Qt::LeftButton || e->button() == Qt::MidButton )
if( buttonToWindowOperation( e->button() ) != OperationsOp )
setVisibleClientGroupItem( item );
else if( e->button() == Qt::RightButton )
else
displayClientMenu( item, widget()->mapToGlobal( release ) );
return true;
}
@ -307,7 +299,8 @@ bool TabstripDecoration::mouseMoveEvent( QMouseEvent* e )
{
QPoint c = e->pos();
int item = itemClicked( c );
if( item >= 0 && click_in_progress && button == Qt::MidButton && ( c - click ).manhattanLength() >= 4 )
if( item >= 0 && click_in_progress && buttonToWindowOperation( button ) == ClientGroupDragOp &&
( c - click ).manhattanLength() >= 4 )
{
click_in_progress = false;
drag_in_progress = true;

View file

@ -1279,7 +1279,13 @@ bool Client::buttonPressEvent( Window w, int button, int state, int x, int y, in
return true;
}
if( w == decorationId())
return false; // don't eat decoration events
{
if( dynamic_cast<KDecorationUnstable*>( decoration ))
// New API processes core events FIRST and only passes unused ones to the decoration
return processDecorationButtonPress( button, state, x, y, x_root, y_root, true );
else
return false; // Don't eat old API decoration events
}
if( w == frameId())
processDecorationButtonPress( button, state, x, y, x_root, y_root );
return true;
@ -1288,7 +1294,8 @@ bool Client::buttonPressEvent( Window w, int button, int state, int x, int y, in
// this function processes button press events only after decoration decides not to handle them,
// unlike buttonPressEvent(), which (when the window is decoration) filters events before decoration gets them
void Client::processDecorationButtonPress( int button, int /*state*/, int x, int y, int x_root, int y_root )
bool Client::processDecorationButtonPress( int button, int /*state*/, int x, int y, int x_root, int y_root,
bool ignoreMenu )
{
Options::MouseCommand com = Options::MouseNothing;
bool active = isActive();
@ -1303,7 +1310,8 @@ void Client::processDecorationButtonPress( int button, int /*state*/, int x, int
com = active ? options->commandActiveTitlebar3() : options->commandInactiveTitlebar3();
if( button == Button1
&& com != Options::MouseOperationsMenu // actions where it's not possible to get the matching
&& com != Options::MouseMinimize ) // mouse release event
&& com != Options::MouseMinimize // mouse release event
&& com != Options::MouseClientGroupDrag )
{
mode = mousePosition( QPoint( x, y ));
buttonDown = true;
@ -1313,7 +1321,19 @@ void Client::processDecorationButtonPress( int button, int /*state*/, int x, int
startDelayedMoveResize();
updateCursor();
}
performMouseCommand( com, QPoint( x_root, y_root ));
// In the new API the decoration may process the menu action to display an inactive tab's menu.
// If the event is unhandled then the core will create one for the active window in the group.
if( !ignoreMenu || com != Options::MouseOperationsMenu )
performMouseCommand( com, QPoint( x_root, y_root ));
return !( // Return events that should be passed to the decoration in the new API
com == Options::MouseRaise ||
com == Options::MouseOperationsMenu ||
com == Options::MouseActivateAndRaise ||
com == Options::MouseActivate ||
com == Options::MouseActivateRaiseAndPassClick ||
com == Options::MouseActivateAndPassClick ||
com == Options::MouseClientGroupDrag ||
com == Options::MouseNothing );
}
// called from decoration

View file

@ -518,6 +518,10 @@ void KDecorationPreviewBridge::displayClientMenu( int, const QPoint& )
{
}
KDecoration::WindowOperation KDecorationPreviewBridge::buttonToWindowOperation( Qt::MouseButtons )
{
return KDecoration::NoOp;
}
KDecorationPreviewOptions::KDecorationPreviewOptions()
{

View file

@ -128,6 +128,7 @@ class KDecorationPreviewBridge
virtual void closeClientGroupItem( int index );
virtual void closeAllInClientGroup();
virtual void displayClientMenu( int index, const QPoint& pos );
virtual WindowOperation buttonToWindowOperation( Qt::MouseButtons button );
private:
KDecorationPreview* preview;

View file

@ -253,6 +253,8 @@ KTitleBarActionsConfig::KTitleBarActionsConfig (bool _standAlone, KConfig *_conf
combo->addItem(i18n("Lower"));
combo->addItem(i18n("Operations Menu"));
combo->addItem(i18n("Toggle Raise & Lower"));
combo->addItem(i18n("Close"));
combo->addItem(i18n("Start Window Tab Drag"));
combo->addItem(i18n("Nothing"));
connect(combo, SIGNAL(activated(int)), SLOT(changed()));
coTiAct1 = combo;
@ -274,9 +276,10 @@ KTitleBarActionsConfig::KTitleBarActionsConfig (bool _standAlone, KConfig *_conf
<< i18n("Lower")
<< i18n("Operations Menu")
<< i18n("Toggle Raise & Lower")
<< i18n("Shade")
<< i18n("Close")
<< i18n("Nothing");
<< i18n("Start Window Tab Drag")
<< i18n("Nothing")
<< i18n("Shade");
combo = new KComboBox(box);
combo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@ -319,6 +322,7 @@ KTitleBarActionsConfig::KTitleBarActionsConfig (bool _standAlone, KConfig *_conf
<< i18n("Raise")
<< i18n("Lower")
<< i18n("Close")
<< i18n("Start Window Tab Drag")
<< i18n("Nothing");
combo = new KComboBox(box);
@ -422,9 +426,10 @@ const char* const tbl_TiAc[] = {
"Lower",
"Operations menu",
"Toggle raise and lower",
"Shade",
"Close",
"Start window tab drag",
"Nothing",
"Shade",
"" };
const char* const tbl_TiInAc[] = {
@ -436,6 +441,7 @@ const char* const tbl_TiInAc[] = {
"Raise",
"Lower",
"Close",
"Start window tab drag",
"Nothing",
"" };
@ -570,11 +576,11 @@ void KTitleBarActionsConfig::load()
KConfigGroup cg(config, "MouseBindings");
setComboText(coTiAct1,cg.readEntry("CommandActiveTitlebar1","Raise").toAscii());
setComboText(coTiAct2,cg.readEntry("CommandActiveTitlebar2","Lower").toAscii());
setComboText(coTiAct2,cg.readEntry("CommandActiveTitlebar2","Start Window Tab Drag").toAscii());
setComboText(coTiAct3,cg.readEntry("CommandActiveTitlebar3","Operations menu").toAscii());
setComboText(coTiAct4,cg.readEntry("CommandTitlebarWheel","Switch to Group Window to the Left/Right").toAscii());
setComboText(coTiInAct1,cg.readEntry("CommandInactiveTitlebar1","Activate and raise").toAscii());
setComboText(coTiInAct2,cg.readEntry("CommandInactiveTitlebar2","Activate and lower").toAscii());
setComboText(coTiInAct2,cg.readEntry("CommandInactiveTitlebar2","Start Window Tab Drag").toAscii());
setComboText(coTiInAct3,cg.readEntry("CommandInactiveTitlebar3","Operations menu").toAscii());
}
@ -609,11 +615,11 @@ void KTitleBarActionsConfig::defaults()
{
setComboText(coTiDbl, "Shade");
setComboText(coTiAct1,"Raise");
setComboText(coTiAct2,"Lower");
setComboText(coTiAct2,"Start Window Tab Drag");
setComboText(coTiAct3,"Operations menu");
setComboText(coTiAct4,"Switch to Group Window to the Left/Right");
setComboText(coTiInAct1,"Activate and raise");
setComboText(coTiInAct2,"Activate and lower");
setComboText(coTiInAct2,"Start Window Tab Drag");
setComboText(coTiInAct3,"Operations menu");
for (int t = 0; t < 3; ++t)
setComboText(coMax[t], tbl_Max[t]);

View file

@ -1336,6 +1336,11 @@ void KCommonDecorationUnstable::displayClientMenu( int index, const QPoint& pos
static_cast<const KDecorationUnstable*>( decoration() )->displayClientMenu( index, pos );
}
KDecoration::WindowOperation KCommonDecorationUnstable::buttonToWindowOperation( Qt::MouseButtons button )
{
return static_cast<const KDecorationUnstable*>( decoration() )->buttonToWindowOperation( button );
}
bool KCommonDecorationUnstable::eventFilter( QObject* o, QEvent* e )
{
return KCommonDecoration::eventFilter( o, e );

View file

@ -394,6 +394,7 @@ class KWIN_EXPORT KCommonDecorationUnstable
void closeAllInClientGroup();
void displayClientMenu( int index, const QPoint& pos );
WindowOperation buttonToWindowOperation( Qt::MouseButtons button );
virtual bool eventFilter( QObject* o, QEvent* e );
};

View file

@ -460,6 +460,10 @@ void KDecorationUnstable::displayClientMenu( int index, const QPoint& pos )
static_cast< KDecorationBridgeUnstable* >( bridge_ )->displayClientMenu( index, pos );
}
KDecoration::WindowOperation KDecorationUnstable::buttonToWindowOperation( Qt::MouseButtons button )
{
return static_cast< KDecorationBridgeUnstable* >( bridge_ )->buttonToWindowOperation( button );
}
QString KDecorationDefines::clientGroupItemDragMimeType()
{

View file

@ -109,7 +109,8 @@ public:
RemoveClientFromGroupOp, // Remove from group
CloseClientGroupOp, // Close the group
MoveClientInGroupLeftOp, // Move left in the group
MoveClientInGroupRightOp // Move right in the group
MoveClientInGroupRightOp, // Move right in the group
ClientGroupDragOp
};
/**
* Basic color types that should be recognized by all decoration styles.
@ -979,6 +980,11 @@ class KWIN_EXPORT KDecorationUnstable
* global coordinates specified by \p pos.
*/
void displayClientMenu( int index, const QPoint& pos );
/**
* Determine which action the user has mapped \p button to. Useful for determining whether
* a button press was for window tab dragging or for displaying the client menu.
*/
WindowOperation buttonToWindowOperation( Qt::MouseButtons button );
};
inline

View file

@ -107,6 +107,7 @@ class KWIN_EXPORT KDecorationBridgeUnstable
virtual void closeClientGroupItem( int index ) = 0;
virtual void closeAllInClientGroup() = 0;
virtual void displayClientMenu( int index, const QPoint& pos ) = 0;
virtual WindowOperation buttonToWindowOperation( Qt::MouseButtons button ) = 0;
};
/** @} */

View file

@ -177,10 +177,10 @@ unsigned long Options::updateSettings()
// Mouse bindings
config = KConfigGroup( _config, "MouseBindings" );
CmdActiveTitlebar1 = mouseCommand(config.readEntry("CommandActiveTitlebar1","Raise"), true );
CmdActiveTitlebar2 = mouseCommand(config.readEntry("CommandActiveTitlebar2","Lower"), true );
CmdActiveTitlebar2 = mouseCommand(config.readEntry("CommandActiveTitlebar2","Start Window Tab Drag"), true );
CmdActiveTitlebar3 = mouseCommand(config.readEntry("CommandActiveTitlebar3","Operations menu"), true );
CmdInactiveTitlebar1 = mouseCommand(config.readEntry("CommandInactiveTitlebar1","Activate and raise"), true );
CmdInactiveTitlebar2 = mouseCommand(config.readEntry("CommandInactiveTitlebar2","Activate and lower"), true );
CmdInactiveTitlebar2 = mouseCommand(config.readEntry("CommandInactiveTitlebar2","Start Window Tab Drag"), true );
CmdInactiveTitlebar3 = mouseCommand(config.readEntry("CommandInactiveTitlebar3","Operations menu"), true );
CmdTitlebarWheel = mouseWheelCommand(config.readEntry("CommandTitlebarWheel","Switch to Group Window to the Left/Right"));
CmdWindow1 = mouseCommand(config.readEntry("CommandWindow1","Activate, raise and pass click"), false );
@ -327,6 +327,7 @@ Options::MouseCommand Options::mouseCommand(const QString &name, bool restricted
if (lowerName == "resize") return restricted ? MouseResize : MouseUnrestrictedResize;
if (lowerName == "shade") return MouseShade;
if (lowerName == "minimize") return MouseMinimize;
if (lowerName == "start window tab drag") return MouseClientGroupDrag;
if (lowerName == "close") return MouseClose;
if (lowerName == "nothing") return MouseNothing;
return MouseNothing;

View file

@ -229,7 +229,7 @@ class Options : public KDecorationOptions
MouseNextDesktop, MousePreviousDesktop,
MouseAbove, MouseBelow,
MouseOpacityMore, MouseOpacityLess,
MouseClose, MouseLeftGroupWindow, MouseRightGroupWindow,
MouseClose, MouseLeftGroupWindow, MouseRightGroupWindow, MouseClientGroupDrag,
MouseNothing
};

View file

@ -747,6 +747,7 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op )
case Options::LowerOp:
lowerClient(c);
break;
case Options::ClientGroupDragOp: // Handled by decoration itself
case Options::NoOp:
break;
case Options::RemoveClientFromGroupOp:
@ -777,6 +778,32 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op )
}
}
/**
* Called by the decoration in the new API to determine what buttons the user has configured for
* window tab dragging and the operations menu.
*/
Options::WindowOperation Client::mouseButtonToWindowOperation( Qt::MouseButtons button )
{
Options::MouseCommand com = Options::MouseNothing;
bool active = isActive();
if( !wantsInput() ) // we cannot be active, use it anyway
active = true;
if( button == Qt::LeftButton )
com = active ? options->commandActiveTitlebar1() : options->commandInactiveTitlebar1();
else if( button == Qt::MidButton )
com = active ? options->commandActiveTitlebar2() : options->commandInactiveTitlebar2();
else if( button == Qt::RightButton )
com = active ? options->commandActiveTitlebar3() : options->commandInactiveTitlebar3();
// TODO: Complete the list
if( com == Options::MouseClientGroupDrag )
return Options::ClientGroupDragOp;
if( com == Options::MouseOperationsMenu )
return Options::OperationsOp;
return Options::NoOp;
}
/*!
Performs a mouse command on this client (see options.h)
*/
@ -957,6 +984,7 @@ bool Client::performMouseCommand( Options::MouseCommand command, const QPoint &g
case Options::MouseClose:
closeWindow();
break;
case Options::MouseClientGroupDrag:
case Options::MouseNothing:
replay = true;
break;