Bug 84424 - CDE Alt-Tab skips window after window set to "Keep Below Others"
Summary: CDE Alt-Tab skips window after window set to "Keep Below Others"
Status: RESOLVED FIXED
Alias: None
Product: kwin
Classification: Plasma
Component: general (show other bugs)
Version: unspecified
Platform: Debian testing Linux
: NOR normal (vote)
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords:
: 97173 (view as bug list)
Depends on:
Blocks:
 
Reported: 2004-07-03 19:25 UTC by Mathijs Romans
Modified: 2006-04-10 15:12 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mathijs Romans 2004-07-03 19:25:44 UTC
Version:            (using KDE KDE 3.2.3)
Installed from:    Debian testing/unstable Packages
Compiler:          gcc version 3.3.4 (Debian 1:3.3.4-2) 
OS:                Linux

Setting a window to "Keep Below Others" messes up the order of walking through the windows with Alt-Tab in CDE mode. 

For example: I have only two windows open: one window maximised, that has the focus, and one other window that is set to "Keep below others", on the background (of course), but not minimised. Then I press Alt-Tab. Now the window set to "Keep below others" has the focus, and my maximised window has not, although I can still only see the maximised window. Then I press Alt-Tab again, expecting the maximised window to get focus again. But it doesn't, the window set to "Keep below others" retains focus. That means I have to reach for my mouse ...
Comment 1 Lubos Lunak 2004-08-26 17:15:03 UTC
Hmm, I have some trouble determining how exactly the CDE-style Alt+Tab should work, as I've never used it. From the source it seems it always tries to put the topmost window to the back, and raise+active the next window. Which also explains why keeping windows on top/bottom breaks it.
I see two options how to fix this problem:
a) Windows kept on top or bottom are excluded, as it wouldn't work with it anyway.
b) It wouldn't start from the topmost, but from the active window, like the normal KDE-style Alt+Tab. However, there's most probably a reason why it works differently in the CDE style, I'd say to work reasonably with focus under mouse policies.
You suggestion?
Comment 2 Mathijs Romans 2004-10-13 12:19:49 UTC
I sent this to your personal email, but it should go here:

thanks for your comments. What is most important for me is that I would
never have to reach for my mouse to activate a window that CAN be above
others. So my suggestion is your b): to start walking from the active
window, and include windows that are set-above-others. But then it is better
to exclude windows that are set-below-others, as they cannot be raised, so
you cannot see if it is active. I think this option also makes most sense
from a user-perspective.
Comment 3 Lubos Lunak 2005-04-29 18:03:51 UTC
*** Bug 97173 has been marked as a duplicate of this bug. ***
Comment 4 Lubos Lunak 2005-05-13 14:41:19 UTC
*** Bug has been marked as fixed ***.
Comment 5 Lubos Lunak 2006-04-10 15:12:41 UTC
SVN commit 528225 by lunakl:

Ok, I've had enough with Alt+Tab and mouse focus policies:
- use click to focus or focus follows mouse and I'll be fine
- with the remaining unreasonable focus policies only the CDE-style
  tabbox works that raises and lowers windows and ignores
  keep above/below windows
- if you don't like that, provide a patch for kwin/tabbox.cpp
- tabbox should be completely redesigned for KDE4
BUG: 123890
CCBUG: 105263
CCBUG: 84424



 M  +8 -0      kcmkwin/kwinoptions/windows.cpp  
 M  +1 -0      kcmkwin/kwinoptions/windows.h  
 M  +20 -4     tabbox.cpp  


--- branches/KDE/3.5/kdebase/kwin/kcmkwin/kwinoptions/windows.cpp #528224:528225
@@ -228,6 +228,7 @@
                  " is pressed, with no popup widget.  In addition, the previously"
                  " activated window will be sent to the back in this mode.");
     QWhatsThis::add( altTabPopup, wtstr );
+    connect(focusCombo, SIGNAL(activated(int)), this, SLOT(updateAltTabMode()));
 
     traverseAll = new QCheckBox( i18n( "&Traverse windows on all desktops" ), kbdBox );
     kLay->addWidget( traverseAll );
@@ -279,8 +280,15 @@
 
     // this will disable/hide the auto raise delay widget if focus==click
     setAutoRaiseEnabled();
+    updateAltTabMode();
 }
 
+void KFocusConfig::updateAltTabMode()
+{
+    // not KDE-style Alt+Tab with unreasonable focus policies
+    altTabPopup->setEnabled( focusCombo->currentItem() == 0 || focusCombo->currentItem() == 1 );
+}
+
 void KFocusConfig::setAutoRaiseInterval(int tb)
 {
     autoRaise->setValue(tb);
--- branches/KDE/3.5/kdebase/kwin/kcmkwin/kwinoptions/windows.h #528224:528225
@@ -85,6 +85,7 @@
   void autoRaiseOnTog(bool);//CT 23Oct1998
   void delayFocusOnTog(bool);
   void clickRaiseOnTog(bool);
+  void updateAltTabMode();
 	void changed() { emit KCModule::changed(true); }
 
 
--- branches/KDE/3.5/kdebase/kwin/tabbox.cpp #528224:528225
@@ -763,7 +763,7 @@
         return;
     if ( tab_grab || control_grab )
         return;
-    if ( options->altTabStyle == Options::CDE )
+    if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable())
         {
         //XUngrabKeyboard(qt_xdisplay(), qt_x_time); // need that because of accelerator raw mode
         // CDE style raise / lower
@@ -789,7 +789,7 @@
         return;
     if( tab_grab || control_grab )
         return;
-    if ( options->altTabStyle == Options::CDE )
+    if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable())
         {
         // CDE style raise / lower
         CDEWalkThroughWindows( false );
@@ -926,7 +926,23 @@
 
 void Workspace::CDEWalkThroughWindows( bool forward )
     {
-    Client* c = activeClient();
+    Client* c = NULL;
+// this function find the first suitable client for unreasonable focus
+// policies - the topmost one, with some exceptions (can't be keepabove/below,
+// otherwise it gets stuck on them)
+    Q_ASSERT( block_stacking_updates == 0 );
+    for( ClientList::ConstIterator it = stacking_order.fromLast();
+         it != stacking_order.end();
+         --it )
+        {
+        if ( (*it)->isOnCurrentDesktop() && !(*it)->isSpecialWindow()
+            && (*it)->isShown( false ) && (*it)->wantsTabFocus()
+            && !(*it)->keepAbove() && !(*it)->keepBelow())
+            {
+            c = *it;
+            break;
+            }
+        }
     Client* nc = c;
     bool options_traverse_all;
         {
@@ -952,7 +968,7 @@
             }
         } while (nc && nc != c &&
             (( !options_traverse_all && !nc->isOnDesktop(currentDesktop())) ||
-             nc->isMinimized() || !nc->wantsTabFocus() ) );
+             nc->isMinimized() || !nc->wantsTabFocus() || nc->keepAbove() || nc->keepBelow() ) );
     if (nc)
         {
         if (c && c != nc)