Bug 123890 - Window switching (alt-tab) with focus (strictly) under or follow mouse does not switch all windows and newly focused window doesn't get focus
Summary: Window switching (alt-tab) with focus (strictly) under or follow mouse does n...
Status: RESOLVED FIXED
Alias: None
Product: kwin
Classification: Plasma
Component: general (show other bugs)
Version: unspecified
Platform: Debian testing Linux
: NOR normal
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-03-19 11:37 UTC by Janne Hayrynen
Modified: 2006-04-10 15:12 UTC (History)
0 users

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 Janne Hayrynen 2006-03-19 11:37:33 UTC
Version:           3.5.1-1 (using KDE KDE 3.5.1)
Installed from:    Debian testing/unstable Packages
OS:                Linux

It seems that when focus mode is anything else _but_ click to focus, alt-tab switching doesn't go through all the windows, only those that are under mouse pointer it seems. Also occasionally a window NOT under pointer does get cycled, but the window which was newly cycled to, doesn't get focus.

Expected behaviour is that ALL windows on workspace are cycled and (temporarily) raised/focused during alt-tabbing, and that last selected window gets focus no matter where mouse pointer is.

The fix for this might be accompanied with a feature that warps mouse pointer to newly focused window when focus follows mouse is active?

kwin version is 3.5.1 on amd64 debian.
Comment 1 Philip Rodrigues 2006-03-19 18:09:13 UTC
I can't seem to reproduce this on r519427. Do you mean that some windows don't appear in the Alt+Tab popup, or that they can't be selected from it, or...?

For the sake of definiteness, could you describe steps to reproduce? (Starting with an empty desktop)
Comment 2 Janne Hayrynen 2006-03-19 22:24:51 UTC
For me, steps to reproduce on amd64 debian unstable with kde 3.5.1 are as follows:

1. Create new account with useradd -m foo, set password
2. Login using kdm, session type kde
3. In setup wizard, select system behaviour type "Unix", otherwise default settings, clicking next.
4. On the empty desktop, open two terminal windows from utilities menu, for me they are placed side by side.
5. Place mouse on desktop background, now pressing alt-f11 (default for cycling windows) wont do anything.

Additional steps:
6. Move terminal windows so that they overlap somewhat, leave mouse on the moved terminal window (not on overlapped part), now pressing alt-f11 switches window once, but not back again. Focus stays on window that is under the mouse.

What works:
7. Move mouse on the overlapping part of those windows, now alt-f11 will switch between the two terminal windows correctly.
Comment 3 Janne Hayrynen 2006-03-20 01:57:41 UTC
Note on previous comment step 6: the other window is _raised_, not focused, and after that nothing happens when pressing again.

Also activating window list during cycle doesn't fix it, even though different windows in the list are seemingly highlighted, they don't get raised+focused unless the previously mentioned conditions apply.
Comment 4 awendt 2006-04-10 06:11:22 UTC
This problem happens to me, too, in Kubuntu "dapper" flight 6, with their KDE 3.5.2.

The focus policy is set to "Focus Follows Mouse", and "Show window list while switching windows" is turned off.

It seems to me that when you press alt-tab without the window list enabled, not only is the next window in the series raised, but the window that is _losing_ focus is sent _behind_ all other windows. This means multiple previously-occluded windows may become visible. If a newly-visible window that wasn't the next in the alt-tab series is raised, it gets the focus.

Imagine two overlapping windows, B and C, and a maximized window, A. And realize that (I believe) alt-tab without the window list just walks through the windows in series, (instead of the behaviour with the window list enabled, which is that one alt-tab will switch to a different window, and a second alt-tab will switch back to the original window).

Something like this probably happens:
1. A is maximized and has focus, and the window list is A -> B -> C.
2. You press alt-tab. Window A is lowered to be behind B and C, and B is raised to be on top.
3. Unfortunately, the mouse happens to be over window C instead of B, so C gets the focus.
4. Press alt-tab again, and focus goes back to window A, (as expected because A is after C in the window order).

We've skipped over window B in the tab order. Subsequent alt-tab with the mouse in the same position will alternate between A and C. (This is not the regular alt-tab-goes-to-previous-window behaviour. You can easily add another window D, and watch alt-tab cycle A -> C -> D if the mouse overlaps those three windows.)

It could probably be fixed just by no longer lowering the window that's losing focus... Just raise the new window.
Comment 5 Lubos Lunak 2006-04-10 15:12:40 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)