diff --git a/src/add-ons/decorators/SATDecorator/StackAndTile.cpp b/src/add-ons/decorators/SATDecorator/StackAndTile.cpp index 3c0f360804..8c35123435 100644 --- a/src/add-ons/decorators/SATDecorator/StackAndTile.cpp +++ b/src/add-ons/decorators/SATDecorator/StackAndTile.cpp @@ -113,7 +113,7 @@ StackAndTile::WindowRemoved(Window* window) } -void +bool StackAndTile::KeyPressed(uint32 what, int32 key, int32 modifiers) { // switch to and from stacking and snapping mode @@ -126,7 +126,83 @@ StackAndTile::KeyPressed(uint32 what, int32 key, int32 modifiers) _StartSAT(); } - return; + if (!SATKeyPressed() || what != B_KEY_DOWN) + return false; + + const int kArrowKeyUp = 87; + const int kArrowKeyDown = 98; + + switch (key) { + case kArrowKeyDown: + { + SATWindow* frontWindow = GetSATWindow(fDesktop->FocusWindow()); + SATGroup* currentGroup = NULL; + if (frontWindow) + currentGroup = frontWindow->GetGroup(); + if (currentGroup && currentGroup->CountItems() <= 1) + currentGroup = NULL; + + GroupIterator groups(this, fDesktop); + bool currentFound = false; + while (true) { + SATGroup* group = groups.NextGroup(); + if (group == NULL) + break; + if (group->CountItems() <= 1) + continue; + + if (currentGroup == NULL) + currentFound = true; + // if no group is selected just activate the first one + else if (currentGroup == group) { + currentFound = true; + continue; + } + if (currentFound) { + _ActivateWindow(group->WindowAt(0)); + if (currentGroup) { + Window* window = currentGroup->WindowAt(0)->GetWindow(); + fDesktop->SendWindowBehind(window); + WindowSentBehind(window, NULL); + } + return true; + } + } + break; + } + + case kArrowKeyUp: + { + SATWindow* frontWindow = GetSATWindow(fDesktop->FocusWindow()); + SATGroup* currentGroup = NULL; + if (frontWindow) + currentGroup = frontWindow->GetGroup(); + if (currentGroup && currentGroup->CountItems() <= 1) + currentGroup = NULL; + + SATGroup* backmostGroup = NULL; + GroupIterator groups(this, fDesktop); + while (true) { + SATGroup* group = groups.NextGroup(); + if (group == NULL) + break; + if (group->CountItems() <= 1) + continue; + // if no group is selected just activate the first one + if (currentGroup == NULL) { + _ActivateWindow(group->WindowAt(0)); + return true; + } + backmostGroup = group; + } + if (backmostGroup && backmostGroup != currentGroup) { + _ActivateWindow(backmostGroup->WindowAt(0)); + return true; + } + break; + } + } + return false; } @@ -369,6 +445,9 @@ StackAndTile::GetDecoratorSettings(Window* window, BMessage& settings) SATWindow* StackAndTile::GetSATWindow(Window* window) { + if (window == NULL) + return NULL; + SATWindowMap::const_iterator it = fSATWindowMap.find( window); if (it != fSATWindowMap.end()) diff --git a/src/add-ons/decorators/SATDecorator/StackAndTile.h b/src/add-ons/decorators/SATDecorator/StackAndTile.h index cd0ba9361f..18b125c219 100644 --- a/src/add-ons/decorators/SATDecorator/StackAndTile.h +++ b/src/add-ons/decorators/SATDecorator/StackAndTile.h @@ -54,7 +54,7 @@ public: virtual void WindowAdded(Window* window); virtual void WindowRemoved(Window* window); - virtual void KeyPressed(uint32 what, int32 key, + virtual bool KeyPressed(uint32 what, int32 key, int32 modifiers); virtual void MouseEvent(BMessage* message) {} virtual void MouseDown(Window* window, BMessage* message, diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 934137466c..370400e874 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -221,9 +221,7 @@ KeyboardFilter::Filter(BMessage* message, EventTarget** _target, || message->what == B_INPUT_METHOD_EVENT) _UpdateFocus(key, modifiers, _target); - fDesktop->KeyEvent(message->what, key, modifiers); - - return B_DISPATCH_MESSAGE; + return fDesktop->KeyEvent(message->what, key, modifiers); } @@ -578,7 +576,7 @@ Desktop::BroadcastToAllWindows(int32 code) } -void +filter_result Desktop::KeyEvent(uint32 what, int32 key, int32 modifiers) { if (LockAllWindows()) { @@ -594,7 +592,10 @@ Desktop::KeyEvent(uint32 what, int32 key, int32 modifiers) UnlockAllWindows(); } - NotifyKeyPressed(what, key, modifiers); + if (NotifyKeyPressed(what, key, modifiers)) + return B_SKIP_MESSAGE; + + return B_DISPATCH_MESSAGE; } diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index 077c60d0fe..3bc22d2d6b 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -72,7 +72,7 @@ public: void BroadcastToAllApps(int32 code); void BroadcastToAllWindows(int32 code); - void KeyEvent(uint32 what, int32 key, + filter_result KeyEvent(uint32 what, int32 key, int32 modifiers); // Locking bool LockSingleWindow() diff --git a/src/servers/app/DesktopListener.cpp b/src/servers/app/DesktopListener.cpp index 6580663145..84599c5ab1 100644 --- a/src/servers/app/DesktopListener.cpp +++ b/src/servers/app/DesktopListener.cpp @@ -91,16 +91,20 @@ DesktopObservable::NotifyWindowRemoved(Window* window) } -void +bool DesktopObservable::NotifyKeyPressed(uint32 what, int32 key, int32 modifiers) { if (fWeAreInvoking) - return; + return false; InvokeGuard invokeGuard(fWeAreInvoking); + bool skipEvent = false; for (DesktopListener* listener = fDesktopListenerList.First(); - listener != NULL; listener = fDesktopListenerList.GetNext(listener)) - listener->KeyPressed(what, key, modifiers); + listener != NULL; listener = fDesktopListenerList.GetNext(listener)) { + if (listener->KeyPressed(what, key, modifiers)) + skipEvent = true; + } + return skipEvent; } diff --git a/src/servers/app/DesktopListener.h b/src/servers/app/DesktopListener.h index a8aceeb049..df102a5399 100644 --- a/src/servers/app/DesktopListener.h +++ b/src/servers/app/DesktopListener.h @@ -38,7 +38,7 @@ public: virtual void WindowAdded(Window* window) = 0; virtual void WindowRemoved(Window* window) = 0; - virtual void KeyPressed(uint32 what, int32 key, + virtual bool KeyPressed(uint32 what, int32 key, int32 modifiers) = 0; virtual void MouseEvent(BMessage* message) = 0; virtual void MouseDown(Window* window, BMessage* message, @@ -92,7 +92,7 @@ public: void NotifyWindowAdded(Window* window); void NotifyWindowRemoved(Window* window); - void NotifyKeyPressed(uint32 what, int32 key, + bool NotifyKeyPressed(uint32 what, int32 key, int32 modifiers); void NotifyMouseEvent(BMessage* message); void NotifyMouseDown(Window* window,