diff --git a/kcmkwin/kwinrules/ruleswidget.cpp b/kcmkwin/kwinrules/ruleswidget.cpp
index fc33265621..ce7d2d023d 100644
--- a/kcmkwin/kwinrules/ruleswidget.cpp
+++ b/kcmkwin/kwinrules/ruleswidget.cpp
@@ -99,6 +99,7 @@ RulesWidget::RulesWidget( QWidget* parent )
SETUP( acceptfocus, force );
SETUP( closeable, force );
SETUP( autogroup, force );
+ SETUP( autogroupid, force );
SETUP( opacityactive, force );
SETUP( opacityinactive, force );
SETUP( shortcut, force );
@@ -147,6 +148,7 @@ UPDATE_ENABLE_SLOT( skippager )
UPDATE_ENABLE_SLOT( acceptfocus )
UPDATE_ENABLE_SLOT( closeable )
UPDATE_ENABLE_SLOT( autogroup )
+UPDATE_ENABLE_SLOT( autogroupid )
UPDATE_ENABLE_SLOT( opacityactive )
UPDATE_ENABLE_SLOT( opacityinactive )
void RulesWidget::updateEnableshortcut()
@@ -423,6 +425,7 @@ void RulesWidget::setRules( Rules* rules )
CHECKBOX_FORCE_RULE( acceptfocus, );
CHECKBOX_FORCE_RULE( closeable, );
CHECKBOX_FORCE_RULE( autogroup, );
+ LINEEDIT_FORCE_RULE( autogroupid, );
LINEEDIT_FORCE_RULE( opacityactive, intToStr );
LINEEDIT_FORCE_RULE( opacityinactive, intToStr );
LINEEDIT_SET_RULE( shortcut, );
@@ -514,6 +517,7 @@ Rules* RulesWidget::rules() const
CHECKBOX_FORCE_RULE( acceptfocus, );
CHECKBOX_FORCE_RULE( closeable, );
CHECKBOX_FORCE_RULE( autogroup, );
+ LINEEDIT_FORCE_RULE( autogroupid, );
LINEEDIT_FORCE_RULE( opacityactive, strToInt );
LINEEDIT_FORCE_RULE( opacityinactive, strToInt );
LINEEDIT_SET_RULE( shortcut, );
@@ -632,6 +636,7 @@ void RulesWidget::prefillUnusedValues( const KWindowInfo& info )
//CHECKBOX_PREFILL( acceptfocus, );
//CHECKBOX_PREFILL( closeable, );
//CHECKBOX_PREFILL( autogroup, );
+ //LINEEDIT_PREFILL( autogroupid, );
LINEEDIT_PREFILL( opacityactive, intToStr, 100 /*get the actual opacity somehow*/);
LINEEDIT_PREFILL( opacityinactive, intToStr, 100 /*get the actual opacity somehow*/);
//LINEEDIT_PREFILL( shortcut, );
diff --git a/kcmkwin/kwinrules/ruleswidget.h b/kcmkwin/kwinrules/ruleswidget.h
index 3de4963b8b..fd65ce4bda 100644
--- a/kcmkwin/kwinrules/ruleswidget.h
+++ b/kcmkwin/kwinrules/ruleswidget.h
@@ -73,6 +73,7 @@ class RulesWidget
void updateEnableacceptfocus();
void updateEnablecloseable();
void updateEnableautogroup();
+ void updateEnableautogroupid();
void updateEnableopacityactive();
void updateEnableopacityinactive();
// workarounds tab
diff --git a/kcmkwin/kwinrules/ruleswidgetbase.ui b/kcmkwin/kwinrules/ruleswidgetbase.ui
index 4171e62fd5..3f617d3a30 100644
--- a/kcmkwin/kwinrules/ruleswidgetbase.ui
+++ b/kcmkwin/kwinrules/ruleswidgetbase.ui
@@ -1157,13 +1157,20 @@
-
+
+
+ Autogroup by I&D
+
+
+
+ -
A&ctive opacity in %
- -
+
-
false
@@ -1185,7 +1192,7 @@
- -
+
-
false
@@ -1275,6 +1282,35 @@
+ -
+
+
+ false
+
+
+
+ -
+
+
+ false
+
+
-
+
+ Do Not Affect
+
+
+ -
+
+ Force
+
+
+ -
+
+ Force Temporarily
+
+
+
+
-
@@ -1526,7 +1562,7 @@
- -
+
-
Qt::Vertical
@@ -1542,7 +1578,7 @@
- -
+
-
false
@@ -1564,7 +1600,7 @@
- -
+
-
false
@@ -1574,14 +1610,14 @@
- -
+
-
I&nactive opacity in %
- -
+
-
Shortcut
@@ -1591,7 +1627,7 @@
- -
+
-
false
@@ -1628,14 +1664,14 @@
- -
+
-
Edit...
- -
+
-
false
diff --git a/manage.cpp b/manage.cpp
index f89fbfa772..e21a392b76 100644
--- a/manage.cpp
+++ b/manage.cpp
@@ -297,6 +297,7 @@ bool Client::manage( Window w, bool isMapped )
move( geom.x(), geom.y() ); // Before gravitating
// Create client group if the window will have a decoration
+ bool dontKeepInArea = false;
if( !noBorder() )
{
client_group = NULL;
@@ -312,14 +313,16 @@ bool Client::manage( Window w, bool isMapped )
group->add( this, -1, true );
break;
}
- if( !client_group && !isMapped && !session &&
- rules()->checkAutogrouping( options->autogroupSimilarWindows ))
+ if( !client_group && !isMapped && !session )
{ // Attempt to automatically group similar windows
const Client* similar = workspace()->findSimilarClient( this );
if( similar && similar->clientGroup() && !similar->noBorder() )
{
similar->clientGroup()->add( this, -1, true );
- placementDone = true; // Don't move entire group
+ // Don't move entire group
+ geom = QRect( similar->pos() + similar->clientPos(), similar->clientSize() );
+ placementDone = true;
+ dontKeepInArea = true;
}
}
if( !client_group )
@@ -345,7 +348,7 @@ bool Client::manage( Window w, bool isMapped )
placementDone = true;
}
- if(( !isSpecialWindow() || isToolbar() ) && isMovable() )
+ if(( !isSpecialWindow() || isToolbar() ) && isMovable() && !dontKeepInArea )
keepInArea( area, partial_keep_in_area );
updateShape();
diff --git a/rules.cpp b/rules.cpp
index bbf33da1e3..37d9b71f65 100644
--- a/rules.cpp
+++ b/rules.cpp
@@ -69,6 +69,7 @@ Rules::Rules()
, moveresizemoderule( UnusedForceRule )
, closeablerule( UnusedForceRule )
, autogrouprule( UnusedForceRule )
+ , autogroupidrule( UnusedForceRule )
, strictgeometryrule( UnusedForceRule )
, shortcutrule( UnusedSetRule )
, disableglobalshortcutsrule( UnusedForceRule )
@@ -170,6 +171,7 @@ void Rules::readFromCfg( const KConfigGroup& cfg )
READ_FORCE_RULE( moveresizemode,Options::stringToMoveResizeMode, QString());
READ_FORCE_RULE( closeable, , false);
READ_FORCE_RULE( autogroup,, false);
+ READ_FORCE_RULE( autogroupid,, QString());
READ_FORCE_RULE( strictgeometry, , false);
READ_SET_RULE( shortcut, ,QString() );
READ_FORCE_RULE( disableglobalshortcuts, , false);
@@ -255,6 +257,7 @@ void Rules::write( KConfigGroup& cfg ) const
WRITE_FORCE_RULE( moveresizemode, Options::moveResizeModeToString );
WRITE_FORCE_RULE( closeable, );
WRITE_FORCE_RULE( autogroup, );
+ WRITE_FORCE_RULE( autogroupid, );
WRITE_FORCE_RULE( strictgeometry, );
WRITE_SET_RULE( shortcut, );
WRITE_FORCE_RULE( disableglobalshortcuts, );
@@ -292,6 +295,7 @@ bool Rules::isEmpty() const
&& moveresizemoderule == UnusedForceRule
&& closeablerule == UnusedForceRule
&& autogrouprule == UnusedForceRule
+ && autogroupidrule == UnusedForceRule
&& strictgeometryrule == UnusedForceRule
&& shortcutrule == UnusedSetRule
&& disableglobalshortcutsrule == UnusedForceRule );
@@ -617,6 +621,7 @@ APPLY_FORCE_RULE( acceptfocus, AcceptFocus, bool )
APPLY_FORCE_RULE( moveresizemode, MoveResizeMode, Options::MoveResizeMode )
APPLY_FORCE_RULE( closeable, Closeable, bool )
APPLY_FORCE_RULE( autogroup, Autogrouping, bool )
+APPLY_FORCE_RULE( autogroupid, AutogroupById, QString )
APPLY_FORCE_RULE( strictgeometry, StrictGeometry, bool )
APPLY_RULE( shortcut, Shortcut, QString )
APPLY_FORCE_RULE( disableglobalshortcuts, DisableGlobalShortcuts, bool )
@@ -680,6 +685,7 @@ void Rules::discardUsed( bool withdrawn )
DISCARD_USED_FORCE_RULE( moveresizemode );
DISCARD_USED_FORCE_RULE( closeable );
DISCARD_USED_FORCE_RULE( autogroup );
+ DISCARD_USED_FORCE_RULE( autogroupid );
DISCARD_USED_FORCE_RULE( strictgeometry );
DISCARD_USED_SET_RULE( shortcut );
DISCARD_USED_FORCE_RULE( disableglobalshortcuts );
@@ -801,6 +807,7 @@ CHECK_FORCE_RULE( AcceptFocus, bool )
CHECK_FORCE_RULE( MoveResizeMode, Options::MoveResizeMode )
CHECK_FORCE_RULE( Closeable, bool )
CHECK_FORCE_RULE( Autogrouping, bool )
+CHECK_FORCE_RULE( AutogroupById, QString )
CHECK_FORCE_RULE( StrictGeometry, bool )
CHECK_RULE( Shortcut, QString )
CHECK_FORCE_RULE( DisableGlobalShortcuts, bool )
@@ -857,6 +864,7 @@ void Client::applyWindowRules()
if( s != size())
resizeWithChecks( s );
// Autogrouping : Only checked on window manage
+ // AutogroupById : Only checked on window manage
// StrictGeometry
setShortcut( rules()->checkShortcut( shortcut().toString()));
// see also Client::setActive()
diff --git a/rules.h b/rules.h
index 28f9575c0a..55e1a75f90 100644
--- a/rules.h
+++ b/rules.h
@@ -78,6 +78,7 @@ class WindowRules
Options::MoveResizeMode checkMoveResizeMode( Options::MoveResizeMode mode ) const;
bool checkCloseable( bool closeable ) const;
bool checkAutogrouping( bool autogroup ) const;
+ QString checkAutogroupById( QString id ) const;
bool checkStrictGeometry( bool strict ) const;
QString checkShortcut( QString s, bool init = false ) const;
bool checkDisableGlobalShortcuts( bool disable ) const;
@@ -131,6 +132,7 @@ class Rules
bool applyMoveResizeMode( Options::MoveResizeMode& mode ) const;
bool applyCloseable( bool& closeable ) const;
bool applyAutogrouping( bool& autogroup ) const;
+ bool applyAutogroupById( QString& id ) const;
bool applyStrictGeometry( bool& strict ) const;
bool applyShortcut( QString& shortcut, bool init ) const;
bool applyDisableGlobalShortcuts( bool& disable ) const;
@@ -246,6 +248,8 @@ class Rules
ForceRule closeablerule;
bool autogroup;
ForceRule autogrouprule;
+ QString autogroupid;
+ ForceRule autogroupidrule;
bool strictgeometry;
ForceRule strictgeometryrule;
QString shortcut;
diff --git a/workspace.cpp b/workspace.cpp
index 4c353fe8a8..eaf9e6a44a 100644
--- a/workspace.cpp
+++ b/workspace.cpp
@@ -2892,19 +2892,45 @@ Client* Workspace::findSimilarClient( Client* c )
{ // Attempt to find a similar window to the input. If we find multiple possibilities that are in
// different groups then ignore all of them. This function is for automatic window grouping.
Client* found = NULL;
- QByteArray wRole = truncatedWindowRole( c->windowRole() );
- foreach( Client* cl, clients )
+
+ // See if the window has a group ID to match with
+ QString wGId = c->rules()->checkAutogroupById( QString() );
+ if( !wGId.isEmpty() )
{
- QByteArray wRoleB = truncatedWindowRole( cl->windowRole() );
- if( c->resourceClass() == cl->resourceClass() && // Same resource class
- wRole == wRoleB && // Same window role
- cl->isNormalWindow() ) // Normal window TODO: Can modal windows be "normal"?
+ foreach( Client* cl, clients )
{
- if( found && found->clientGroup() != cl->clientGroup() ) // We've found two, ignore both
- return NULL;
- found = cl;
+ if( wGId == cl->rules()->checkAutogroupById( QString() ))
+ {
+ if( found && found->clientGroup() != cl->clientGroup() ) // We've found two, ignore both
+ {
+ found = NULL;
+ break; // Continue to the next test
+ }
+ found = cl;
+ }
+ }
+ if( found )
+ return found;
+ }
+
+ // If we don't have an ID take a guess
+ if( c->rules()->checkAutogrouping( options->autogroupSimilarWindows ))
+ {
+ QByteArray wRole = truncatedWindowRole( c->windowRole() );
+ foreach( Client* cl, clients )
+ {
+ QByteArray wRoleB = truncatedWindowRole( cl->windowRole() );
+ if( c->resourceClass() == cl->resourceClass() && // Same resource class
+ wRole == wRoleB && // Same window role
+ cl->isNormalWindow() ) // Normal window TODO: Can modal windows be "normal"?
+ {
+ if( found && found->clientGroup() != cl->clientGroup() ) // We've found two, ignore both
+ return NULL;
+ found = cl;
+ }
}
}
+
return found;
}