[haiku-commits] r36943 - haiku/branches/features/stack-and-tile/src/servers/app

  • From: clemens.zeidler@xxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 27 May 2010 01:07:38 +0200 (CEST)

Author: czeidler
Date: 2010-05-27 01:07:37 +0200 (Thu, 27 May 2010)
New Revision: 36943
Changeset: http://dev.haiku-os.org/changeset/36943/haiku

Added:
   haiku/branches/features/stack-and-tile/src/servers/app/Snapping.cpp
Modified:
   haiku/branches/features/stack-and-tile/src/servers/app/Jamfile
   haiku/branches/features/stack-and-tile/src/servers/app/StackAndTile.cpp
   haiku/branches/features/stack-and-tile/src/servers/app/StackAndTile.h
Log:
Move snapping related stuff into a Snapping sub class.



Modified: haiku/branches/features/stack-and-tile/src/servers/app/Jamfile
===================================================================
--- haiku/branches/features/stack-and-tile/src/servers/app/Jamfile      
2010-05-26 17:24:39 UTC (rev 36942)
+++ haiku/branches/features/stack-and-tile/src/servers/app/Jamfile      
2010-05-26 23:07:37 UTC (rev 36943)
@@ -53,6 +53,7 @@
        ServerFont.cpp
        ServerPicture.cpp
        ServerWindow.cpp
+       Snapping.cpp
        StackAndTile.cpp
        Stacking.cpp
        SystemPalette.cpp

Added: haiku/branches/features/stack-and-tile/src/servers/app/Snapping.cpp
===================================================================
--- haiku/branches/features/stack-and-tile/src/servers/app/Snapping.cpp         
                (rev 0)
+++ haiku/branches/features/stack-and-tile/src/servers/app/Snapping.cpp 
2010-05-26 23:07:37 UTC (rev 36943)
@@ -0,0 +1,1331 @@
+#include "StackAndTile.h"
+
+#include "Window.h"
+
+#include <Debug.h>
+
+
+// #define DEBUG_SNAPPING
+
+
+#ifdef DEBUG_SNAPPING
+#      define STRACE_SAT(x) debug_printf x
+#else
+#      define STRACE_SAT(x) ;
+#endif
+
+#ifdef DEBUG_SNAPPING
+char kSnapOrientationString[][7] = {"left", "right", "top", "bottom"};
+#endif
+
+
+SATWindowSnapping::SATWindowSnapping(Window* window, ::StackAndTile* sat)
+       :
+       SATWindow(window, sat),
+
+       fLeftAdjacentWindows(NULL),
+       fTopAdjacentWindows(NULL),
+       fRightAdjacentWindows(NULL),
+       fBottomAdjacentWindows(NULL),
+       fSnappingConstraints(NULL),
+
+       fLeft2LeftSnappingWindowIds(NULL),
+       fLeft2RightSnappingWindowIds(NULL),
+       fRight2RightSnappingWindowIds(NULL),
+       fRight2LeftSnappingWindowIds(NULL),
+       fTop2TopSnappingWindowIds(NULL),
+       fTop2BottomSnappingWindowIds(NULL),
+       fBottom2BottomSnappingWindowIds(NULL),
+       fBottom2TopSnappingWindowIds(NULL)
+{
+       
+}
+
+
+SATWindowSnapping::~SATWindowSnapping()
+{
+       // clean up the entries in the snapping lists for each combo of
+       // snapping orientations
+       _FreeUpSnappingList(SNAP_LEFT, SNAP_LEFT, false);
+       _FreeUpSnappingList(SNAP_LEFT, SNAP_RIGHT, false);
+       _FreeUpSnappingList(SNAP_RIGHT, SNAP_LEFT, false);
+       _FreeUpSnappingList(SNAP_RIGHT, SNAP_RIGHT, false);
+       _FreeUpSnappingList(SNAP_TOP, SNAP_TOP, false);
+       _FreeUpSnappingList(SNAP_TOP, SNAP_BOTTOM, false);
+       _FreeUpSnappingList(SNAP_BOTTOM, SNAP_TOP, false);
+       _FreeUpSnappingList(SNAP_BOTTOM, SNAP_BOTTOM, false);
+}
+
+
+void
+SATWindowSnapping::MouseDown()
+{
+       SATWindow::MouseDown();
+
+       // Re-stack and re-snap the window if in stacking & snapping mode
+       if (fStackAndTile->IsStackingAndSnapping()) {
+               _RemoveSnappingPersistently();
+               _CheckIfReadyToSnap();
+       }
+}
+
+
+void
+SATWindowSnapping::MouseUp()
+{
+       SATWindow::MouseUp();
+
+       // Snap or stack the window if in stack & tiling mode
+       if (fStackAndTile->IsStackingAndSnapping()) {
+               _RemoveSnappingPersistently();
+               _CheckIfReadyToSnap();
+               _SnapWindow();
+       }
+}
+
+
+void
+SATWindowSnapping::MoveWindow()
+{
+       SATWindow::MoveWindow();
+
+       // Dragging in StackingAndSnapping mode means stacking and
+       // snapping of this window is removed and can be changed.
+       // Otherwise, dragging means the stack & tile constraints are
+       // solved and windows adjusted accordingly.
+       if (fStackAndTile->IsStackingAndSnapping()) {
+               _RemoveSnappingPersistently();
+               _CheckIfReadyToSnap();
+       }
+}
+
+
+void
+SATWindowSnapping::ResizeWindow()
+{
+       SATWindow::ResizeWindow();
+
+       // Resizing in StackingAndSnapping mode means stacking and
+       // snapping of this window is removed and can be changed.
+       // Otherwise, resizing means the stack & tile constraints are
+       // solved and windows adjusted accordingly.
+       if (fStackAndTile->IsStackingAndSnapping()) {
+               _RemoveSnappingPersistently();
+               _CheckIfReadyToSnap();
+       }
+}
+
+
+void
+SATWindowSnapping::ActivateWindow(Window* window, WindowList& bringToTopList)
+{
+       BObjectList<Window> stackedAndTiledWindows;
+
+       //Prepare to move tiled windows to the front as well
+       _AddWindowsByIdsToList(Left2LeftSnappingWindowIds(),
+               stackedAndTiledWindows);
+       _AddWindowsByIdsToList(Left2RightSnappingWindowIds(),
+               stackedAndTiledWindows);
+       _AddWindowsByIdsToList(Right2RightSnappingWindowIds(),
+               stackedAndTiledWindows);
+       _AddWindowsByIdsToList(Right2LeftSnappingWindowIds(),
+               stackedAndTiledWindows);
+       _AddWindowsByIdsToList(Top2TopSnappingWindowIds(),
+               stackedAndTiledWindows);
+       _AddWindowsByIdsToList(Top2BottomSnappingWindowIds(),
+               stackedAndTiledWindows);
+       _AddWindowsByIdsToList(Bottom2TopSnappingWindowIds(),
+               stackedAndTiledWindows);
+       _AddWindowsByIdsToList(Bottom2BottomSnappingWindowIds(),
+               stackedAndTiledWindows);
+
+       // Do the actual moving here
+       for (int i = 0; i < stackedAndTiledWindows.CountItems(); i ++) {
+               Window* win = stackedAndTiledWindows.ItemAt(i);
+               fWindow->Desktop()->CurrentWindows().RemoveWindow(win);
+               bringToTopList.AddWindow(win);
+       }
+
+       SATWindow::ActivateWindow(window, bringToTopList);
+}
+
+
+bool
+SATWindowSnapping::SetSettings(const BMessage& settings)
+{
+       STRACE_SAT(("SATWindowSnapping::SetSettings() on %s\n",
+               fWindow->Title()));
+
+       _SnapWindowFromSettings("snap left2left", SNAP_LEFT, SNAP_LEFT,
+               &settings);
+       _SnapWindowFromSettings("snap left2right", SNAP_LEFT, SNAP_RIGHT,
+               &settings);
+       _SnapWindowFromSettings("snap right2left", SNAP_RIGHT, SNAP_LEFT,
+               &settings);
+       _SnapWindowFromSettings("snap right2right", SNAP_RIGHT, SNAP_RIGHT,
+               &settings);
+       _SnapWindowFromSettings("snap top2top", SNAP_TOP, SNAP_TOP, &settings);
+       _SnapWindowFromSettings("snap top2bottom", SNAP_TOP, SNAP_BOTTOM,
+               &settings);
+       _SnapWindowFromSettings("snap bottom2top", SNAP_BOTTOM, SNAP_TOP,
+               &settings);
+       _SnapWindowFromSettings("snap bottom2bottom", SNAP_BOTTOM, SNAP_BOTTOM,
+               &settings);
+
+       STRACE_SAT(("Finished SATWindowSnapping::SetSettings() on %s\n",
+               fWindow->Title()));
+
+       return SATWindow::SetSettings(settings);
+}
+
+
+bool
+SATWindowSnapping::GetSettings(BMessage* settings) const
+{
+       // store id's of snapped windows
+       if (!StoreIntsInSettings("snap left2left", Left2LeftSnappingWindowIds(),
+               settings))
+               return false;
+       if (!StoreIntsInSettings("snap left2right", 
Left2RightSnappingWindowIds(),
+               settings))
+               return false;
+       if (!StoreIntsInSettings("snap right2right",
+               Right2RightSnappingWindowIds(), settings))
+               return false;
+       if (!StoreIntsInSettings("snap right2left", 
Right2LeftSnappingWindowIds(),
+               settings))
+               return false;
+       if (!StoreIntsInSettings("snap top2top", Top2TopSnappingWindowIds(),
+               settings))
+               return false;
+       if (!StoreIntsInSettings("snap top2bottom", 
Top2BottomSnappingWindowIds(),
+               settings))
+               return false;
+       if (!StoreIntsInSettings("snap bottom2top", 
Bottom2TopSnappingWindowIds(),
+               settings))
+               return false;
+       if (!StoreIntsInSettings("snap bottom2bottom",
+               Bottom2BottomSnappingWindowIds(), settings))
+               return false;
+
+       return SATWindow::GetSettings(settings);
+}
+
+
+void
+SATWindowSnapping::InitStackingAndSnapping()
+{
+       SATWindow::InitStackingAndSnapping();
+       
+       _InitSnapping();
+}
+
+
+void
+SATWindowSnapping::FinishStackingAndSnapping()
+{
+       // clear snapping candidates
+       delete fLeftAdjacentWindows;
+       delete fTopAdjacentWindows;
+       delete fRightAdjacentWindows;
+       delete fBottomAdjacentWindows;
+       fLeftAdjacentWindows = NULL;
+       fTopAdjacentWindows = NULL;
+       fRightAdjacentWindows = NULL;
+       fBottomAdjacentWindows = NULL;
+
+       SATWindow::FinishStackingAndSnapping();
+}
+
+
+void
+SATWindowSnapping::_RemoveSAT()
+{
+       SATWindow::_RemoveSAT();
+       
+       _RemoveSnapping();
+}
+
+
+void
+SATWindowSnapping::_SnapWindowFromSettings(const char* label,
+               SnapOrientation thisSnapOrientation,
+               SnapOrientation otherSnapOrientation,
+               const BMessage* settings)
+{
+       type_code typeFound;
+       int32 countFound;
+       settings->GetInfo(label, &typeFound, &countFound);
+       if (typeFound == B_INT32_TYPE && countFound > 0) {
+               for (int i = 0; i < countFound; i++) {
+                       int32 id;
+                       settings->FindInt32(label, i, &id);
+
+                       SATWindowSnapping* window = 
dynamic_cast<SATWindowSnapping*>(
+                               FindWindow(id));
+                       if (window == this) {
+                               continue;
+                       }
+
+                       char* debug_suffix = "... NOT!";
+
+                       if (window) {
+                               // There can be cases where the other window to 
which this
+                               // window's snapped doesn't contain a reference 
to this window
+                               // in its snapping list. This would happen when 
the other window
+                               // was de-snapped while this window was hidden. 
So only add the
+                               // other window to this window's snapping list 
when such is not
+                               // the case.
+                               BList* otherList = 
window->GetSnappingList(otherSnapOrientation,
+                                       thisSnapOrientation, false);
+                               if (!otherList) {
+                                       debug_suffix = "\n";
+                                       continue;
+                               }
+                               for (int i = 0; i < otherList->CountItems(); 
i++) {
+                                       int32* snappedId = 
static_cast<int32*>(otherList->ItemAt(i));
+                                       if (*snappedId == WindowId()) {
+                                               SnapToWindow(window, 
thisSnapOrientation,
+                                                               
otherSnapOrientation);
+                                               debug_suffix = "";
+                                               break;
+                                       }
+                               }
+                       }
+                       else { // window isn't open - still retain snap id
+                               AddToSnappingList(id, thisSnapOrientation,
+                                       otherSnapOrientation);
+                               debug_suffix = "... ?";
+                       }
+
+                       STRACE_SAT(("\t%s[%d]=%x", label, i, id));
+                       STRACE_SAT(("%s\n", debug_suffix));
+               }
+       }
+}
+
+
+void
+SATWindowSnapping::_EnsureWindowWithinScreenBounds(SATWindowSnapping* window,
+       SATWindow* detached)
+{
+       BRect screenFrame = fWindow->Screen()->Frame();
+       float deltaX = 0;
+       float deltaY = 0;
+
+       BRect windowFrame = window->GetWindow()->Frame();
+
+       BList* windowsToRight = window->Right2LeftSnappingWindowIds();
+       BList* windowsToLeft = window->Left2RightSnappingWindowIds();
+       BList* windowsToTop = window->Bottom2TopSnappingWindowIds();
+       BList* windowsToBottom = window->Top2BottomSnappingWindowIds();
+
+       if (windowFrame.left < 0 && (!windowsToRight || 
windowsToRight->IsEmpty()
+               || windowsToRight->CountItems() == 1)
+               && *static_cast<int32*>(windowsToRight->ItemAt(0))
+                       == detached->WindowId()) {
+               // If window is off-screen to the left and there's no window 
tiled
+               // to its right that can still "save" it from going totally 
off-screen
+               deltaX = 6 - windowFrame.left;
+       }
+       else if (windowFrame.right > screenFrame.right && (!windowsToLeft
+               || windowsToLeft->IsEmpty() || windowsToLeft->CountItems() == 1)
+               && *static_cast<int32*>(windowsToLeft->ItemAt(0))
+                       == detached->WindowId()) {
+               // If window is off-screen to the right and there's no window 
tiled
+               // to its left that can still "save" it from going totally 
off-screen
+               deltaX = screenFrame.right - windowFrame.right - 6;
+       }
+       if (windowFrame.top < 0 && (!windowsToTop || windowsToTop->IsEmpty()
+               || windowsToTop->CountItems() == 1)
+               && *static_cast<int32*>(windowsToTop->ItemAt(0))
+                       == detached->WindowId()) {
+               // If window is off-screen to the top and there's no window 
tiled
+               // to its bottom that can still "save" it from going totally 
off-screen
+               deltaY = 27 - windowFrame.top;
+       }
+       else if (windowFrame.bottom > screenFrame.bottom && (!windowsToBottom
+               || windowsToBottom->IsEmpty() || windowsToBottom->CountItems() 
== 1)
+               && *static_cast<int32*>(windowsToBottom->ItemAt(0))
+                       == detached->WindowId()) {
+               // If window is off-screen to the bottom and there's no window 
tiled
+               // to its top that can still "save" it from going totally 
off-screen
+               deltaY = screenFrame.bottom - windowFrame.bottom - 6;
+       }
+       if (deltaX != 0 || deltaY != 0)
+               fWindow->Desktop()->MoveWindowBy(window->GetWindow(), deltaX, 
deltaY);
+}
+
+
+void
+SATWindowSnapping::_InitSnapping()
+{
+       STRACE_SAT(("SATWindowSnapping::_InitSnapping() on %s, fLeftVar=%d\n",
+               fWindow->Title(), fLeftVar));
+
+       fSnappingConstraints = new BList();
+
+       STRACE_SAT(("Finished SATWindowSnapping::_InitSnapping() on %s\n",
+               fWindow->Title()));
+}
+
+
+void
+SATWindowSnapping::_RemoveSnapping()
+{
+       STRACE_SAT(("SATWindowSnapping::_RemoveSnapping() on %s, fLeftVar=%d\n",
+               fWindow->Title(), fLeftVar));
+
+       // if there are no variables for the sides, then it is not active
+       if (!fSnappingConstraints)
+               return;
+
+       for (int i = 0; i < fSnappingConstraints->CountItems(); i++)
+               delete 
static_cast<Constraint*>(fSnappingConstraints->ItemAt(i));
+       fSnappingConstraints = NULL;
+
+       // For each previously snapped window, make sure that it is within
+       // screen bounds, so as to prevent it from being lost off-screen
+       _EnsureAndSAT(fLeft2LeftSnappingWindowIds);
+       _EnsureAndSAT(fLeft2RightSnappingWindowIds);
+       _EnsureAndSAT(fRight2LeftSnappingWindowIds);
+       _EnsureAndSAT(fRight2RightSnappingWindowIds);
+       _EnsureAndSAT(fTop2TopSnappingWindowIds);
+       _EnsureAndSAT(fTop2BottomSnappingWindowIds);
+       _EnsureAndSAT(fBottom2TopSnappingWindowIds);
+       _EnsureAndSAT(fBottom2BottomSnappingWindowIds);
+
+       STRACE_SAT(("Finished SATWindowSnapping::_RemoveStackingAndSnapping() 
on %s\n",
+               fWindow->Title()));
+}
+
+
+void
+SATWindowSnapping::_EnsureAndSAT(BList* idList)
+{
+       if (!idList)
+               return;
+
+       for (int i = 0; i < idList->CountItems(); i++) {
+               int32* id = static_cast<int32*>(idList->ItemAt(i));
+               SATWindowSnapping* winSAT = dynamic_cast<SATWindowSnapping*>(
+                       FindWindow(*id));
+               if (winSAT) {
+                       _EnsureWindowWithinScreenBounds(winSAT, this);
+                       winSAT->StackAndTile();
+               }
+       }
+}
+
+
+/*!    \brief Compiles suitable snapping candidates by checking which windows
+               are adjacent to this window, and gives visual feedback by 
adjusting
+               window border highlights. This method is called during the 
Stack & Tile
+               configuration mode.
+*/
+void
+SATWindowSnapping::_CheckIfReadyToSnap()
+{
+       if (!fLeftAdjacentWindows) {
+               fLeftAdjacentWindows = new BList();
+               fTopAdjacentWindows = new BList();
+               fRightAdjacentWindows = new BList();
+               fBottomAdjacentWindows = new BList();
+       }
+
+       // remember previous adjacent windows for changing highlights later
+       BList prevLeftAdjacentWindows(*fLeftAdjacentWindows);
+       BList prevTopAdjacentWindows(*fTopAdjacentWindows);
+       BList prevRightAdjacentWindows(*fRightAdjacentWindows);
+       BList prevBottomAdjacentWindows(*fBottomAdjacentWindows);
+
+       // clear lists of old adjacent windows
+       fLeftAdjacentWindows->MakeEmpty();
+       fTopAdjacentWindows->MakeEmpty();
+       fRightAdjacentWindows->MakeEmpty();
+       fBottomAdjacentWindows->MakeEmpty();
+
+       // go through all windows and look for snapping candidates
+       for (Window* window = fWindow->Desktop()->CurrentWindows().LastWindow();
+               window; window = 
window->PreviousWindow(fWindow->CurrentWorkspace())) {
+               Window* windowUnder = fStacking.GetWindowUnder() != NULL
+                       ? fStacking.GetWindowUnder()->GetWindow() : NULL;
+               if (!window->IsHidden()
+                       && fWindow != window    // don't snap window to itself
+                       && window != windowUnder
+                               // don't snap with stacking candidate
+                       && !(strcmp(window->Title(), "Deskbar") == 0)
+                       && !(strcmp(window->Title(), "Desktop") == 0)) {
+
+                       // is window adjacent on the left of this window?
+                       BRect thisLeft(fWindow->Frame().left - 12,
+                               fWindow->Frame().top + 12, 
fWindow->Frame().left + 6,
+                               fWindow->Frame().bottom - 12);
+                       BRect windowRight(window->Frame().right - 6,
+                               window->Frame().top + 12, window->Frame().right 
+ 12,
+                               window->Frame().bottom - 12);
+                       if (thisLeft.Intersects(windowRight))
+                               fLeftAdjacentWindows->AddItem(window);
+
+                       // is window adjacent on the top of this window?
+                       BRect thisTop(fWindow->Frame().left + 12, 
fWindow->Frame().top - 22,
+                               fWindow->Frame().right - 12, 
fWindow->Frame().top + 6);
+                       BRect windowBottom(window->Frame().left + 12,
+                               window->Frame().bottom - 6, 
window->Frame().right - 12,
+                               window->Frame().bottom + 12);
+                       if (thisTop.Intersects(windowBottom))
+                               fTopAdjacentWindows->AddItem(window);
+
+                       // is window adjacent on the right of this window?
+                       BRect thisRight(fWindow->Frame().right - 6,
+                               fWindow->Frame().top + 12, 
fWindow->Frame().right + 12,
+                               fWindow->Frame().bottom - 12);
+                       BRect windowLeft(window->Frame().left - 12,
+                               window->Frame().top + 12, window->Frame().left 
+ 6,
+                               window->Frame().bottom - 12);
+                       if (thisRight.Intersects(windowLeft))
+                               fRightAdjacentWindows->AddItem(window);
+
+                       // is window adjacent on the bottom of this window?
+                       BRect thisBottom(fWindow->Frame().left + 12,
+                               fWindow->Frame().bottom - 6, 
fWindow->Frame().right - 12,
+                               fWindow->Frame().bottom + 12);
+                       BRect windowTop(window->Frame().left + 12,
+                               window->Frame().top - 22, window->Frame().right 
- 12,
+                               window->Frame().top + 6);
+                       if (thisBottom.Intersects(windowTop))
+                               fBottomAdjacentWindows->AddItem(window);
+               }
+       }
+
+       // change window border highlight of this window
+       if (!fLeftAdjacentWindows->IsEmpty()
+               || !fTopAdjacentWindows->IsEmpty()
+               || !fRightAdjacentWindows->IsEmpty()
+               || !fBottomAdjacentWindows->IsEmpty())
+               fWindow->Desktop()->HighlightBorders(fWindow, true);
+       else
+               fWindow->Desktop()->HighlightBorders(fWindow, false);
+
+       // switch off border highlights of windows that are not candidates any 
more
+       for (int i = 0; i < prevLeftAdjacentWindows.CountItems(); i++) {
+               Window* window = static_cast<Window*>(
+                       prevLeftAdjacentWindows.ItemAt(i));
+               if (!fLeftAdjacentWindows->HasItem(window))
+                       fWindow->Desktop()->HighlightBorders(window, false);
+       }
+       for (int i = 0; i < prevTopAdjacentWindows.CountItems(); i++) {
+               Window* window = static_cast<Window*>(
+                       prevTopAdjacentWindows.ItemAt(i));
+               if (!fTopAdjacentWindows->HasItem(window))
+                       fWindow->Desktop()->HighlightBorders(window, false);
+       }
+       for (int i = 0; i < prevRightAdjacentWindows.CountItems(); i++) {
+               Window* window = static_cast<Window*>(
+                       prevRightAdjacentWindows.ItemAt(i));
+               if (!fRightAdjacentWindows->HasItem(window))
+                       fWindow->Desktop()->HighlightBorders(window, false);
+       }
+       for (int i = 0; i < prevBottomAdjacentWindows.CountItems(); i++) {
+               Window* window = static_cast<Window*>(
+                       prevBottomAdjacentWindows.ItemAt(i));
+               if (!fBottomAdjacentWindows->HasItem(window))
+                       fWindow->Desktop()->HighlightBorders(window, false);
+       }
+
+       // switch on border highlights of candidate windows
+       // if they are already on, HighlightBorders will detect this
+       for (int i = 0; i < fLeftAdjacentWindows->CountItems(); i++)
+               fWindow->Desktop()->HighlightBorders(
+                       static_cast<Window*>(fLeftAdjacentWindows->ItemAt(i)), 
true);
+       for (int i = 0; i < fTopAdjacentWindows->CountItems(); i++)
+               fWindow->Desktop()->HighlightBorders(
+                       static_cast<Window*>(fTopAdjacentWindows->ItemAt(i)), 
true);
+       for (int i = 0; i < fRightAdjacentWindows->CountItems(); i++)
+               fWindow->Desktop()->HighlightBorders(
+                       static_cast<Window*>(fRightAdjacentWindows->ItemAt(i)), 
true);
+       for (int i = 0; i < fBottomAdjacentWindows->CountItems(); i++)
+               fWindow->Desktop()->HighlightBorders(
+                       
static_cast<Window*>(fBottomAdjacentWindows->ItemAt(i)), true);
+}
+
+
+/*!    \brief Snaps this window to the current candidate windows for snapping
+       on each side. Afterwards snapping candidates are cleared.
+*/
+void
+SATWindowSnapping::_SnapWindow()
+{
+       BRect bounds;
+       SATWindowSnapping* leftmostWindow;
+       SATWindowSnapping* topmostWindow;
+       SATWindowSnapping* rightmostWindow;
+       SATWindowSnapping* bottommostWindow;
+
+       // snap other windows to the left border
+       if (!fLeftAdjacentWindows->IsEmpty()) {
+               bounds = _BoundingRectAndWindows(fLeftAdjacentWindows,
+                       &leftmostWindow, &topmostWindow,
+                       &rightmostWindow, &bottommostWindow);
+
+               // adjust window position & initialize snapping
+               fWindow->Desktop()->MoveWindowBy(fWindow,
+                       bounds.right - fWindow->Frame().left + 11, 0);
+               InitStackingAndSnapping();
+               topmostWindow->InitStackingAndSnapping();
+               bottommostWindow->InitStackingAndSnapping();
+
+               // adjust top border
+               if (fTopAdjacentWindows->IsEmpty()) {
+                       fWindow->Desktop()->MoveWindowBy(fWindow, 0,
+                               bounds.top - fWindow->Frame().top);
+                       Constraint* topSnapping = fTopVar->IsEqual(
+                               topmostWindow->fTopVar);
+                       BString label("topSnapping of ");
+                       label << fWindow->Title();
+                       topSnapping->SetLabel(label.String());
+                       fSnappingConstraints->AddItem(topSnapping);
+
+                       AddToSnappingList(topmostWindow, SNAP_TOP, SNAP_TOP);
+                       AddToSnappingList(topmostWindow, SNAP_LEFT, SNAP_RIGHT);
+                       topmostWindow->AddToSnappingList(this, SNAP_TOP, 
SNAP_TOP);
+                       topmostWindow->AddToSnappingList(this, SNAP_RIGHT, 
SNAP_LEFT);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s T2T & L2R 
list\n",
+                               topmostWindow->Title(), 
topmostWindow->WindowId(),
+                               fWindow->Title(), WindowId()));
+               }
+
+               // adjust bottom border
+               if (fBottomAdjacentWindows->IsEmpty()) {
+                       fWindow->Desktop()->ResizeWindowBy(fWindow, 0,
+                               bounds.bottom - fWindow->Frame().bottom);
+                       Constraint* bottomSnapping = fBottomVar->IsEqual(
+                               bottommostWindow->fBottomVar);
+                       BString label("bottomSnapping of ");
+                       label << fWindow->Title();
+                       bottomSnapping->SetLabel(label.String());
+                       fSnappingConstraints->AddItem(bottomSnapping);
+
+                       AddToSnappingList(bottommostWindow, SNAP_BOTTOM, 
SNAP_BOTTOM);
+                       AddToSnappingList(bottommostWindow, SNAP_LEFT, 
SNAP_RIGHT);
+                       bottommostWindow->AddToSnappingList(this, SNAP_BOTTOM, 
SNAP_BOTTOM);
+                       bottommostWindow->AddToSnappingList(this, SNAP_RIGHT, 
SNAP_LEFT);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s B2B & L2R 
list\n",
+                               bottommostWindow->Title(), 
bottommostWindow->WindowId(),
+                               fWindow->Title(), WindowId()));
+               }
+
+               // adjust other windows
+               for (int i = 0; i < fLeftAdjacentWindows->CountItems(); i++) {
+                       SATWindowSnapping* window = 
dynamic_cast<SATWindowSnapping*>(
+                               
fStackAndTile->GetSATWindow(static_cast<Window*>(
+                                       fLeftAdjacentWindows->ItemAt(i))));
+                       ASSERT(window);
+                       window->InitStackingAndSnapping();
+                       Constraint* leftSnapping =
+                               
fStackAndTile->GetLinearSpec()->AddConstraint(-1,
+                                       window->RightVariable(), 1, fLeftVar, 
OperatorType(EQ), 11);
+                       BString label("leftSnapping of ");
+                       label << fWindow->Title();
+                       leftSnapping->SetLabel(label.String());
+                       window->fSnappingConstraints->AddItem(leftSnapping);
+
+                       AddToSnappingList(window, SNAP_LEFT, SNAP_RIGHT);
+                       window->AddToSnappingList(this, SNAP_RIGHT, SNAP_LEFT);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s L2R list\n", 
window->Title(),
+                               window->WindowId(), fWindow->Title(), 
WindowId()));
+               }
+       }
+
+       // snap other windows to the top border
+       if (!fTopAdjacentWindows->IsEmpty()) {
+               bounds = _BoundingRectAndWindows(fTopAdjacentWindows,
+                       &leftmostWindow, &topmostWindow,
+                       &rightmostWindow, &bottommostWindow);
+
+               // adjust window position & initialize snapping
+               fWindow->Desktop()->MoveWindowBy(fWindow, 0,
+                       bounds.bottom - fWindow->Frame().top + 32);
+               InitStackingAndSnapping();
+               leftmostWindow->InitStackingAndSnapping();
+               rightmostWindow->InitStackingAndSnapping();
+
+               // adjust left border
+               if (fLeftAdjacentWindows->IsEmpty()) {
+                       fWindow->Desktop()->MoveWindowBy(
+                               fWindow, bounds.left - fWindow->Frame().left, 
0);
+                       Constraint* leftSnapping = fLeftVar->IsEqual(
+                               leftmostWindow->fLeftVar);
+                       BString label("leftSnapping of ");
+                       label << fWindow->Title();
+                       leftSnapping->SetLabel(label.String());
+                       fSnappingConstraints->AddItem(leftSnapping);
+
+                       AddToSnappingList(leftmostWindow, SNAP_LEFT, SNAP_LEFT);
+                       AddToSnappingList(leftmostWindow, SNAP_TOP, 
SNAP_BOTTOM);
+                       leftmostWindow->AddToSnappingList(this, SNAP_LEFT, 
SNAP_LEFT);
+                       leftmostWindow->AddToSnappingList(this, SNAP_BOTTOM, 
SNAP_TOP);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s L2L & T2B 
list\n",
+                               leftmostWindow->Title(), 
leftmostWindow->WindowId(),
+                               fWindow->Title(), WindowId()));
+               }
+
+               // adjust right border
+               if (fRightAdjacentWindows->IsEmpty()) {
+                       fWindow->Desktop()->ResizeWindowBy(fWindow,
+                               bounds.right - fWindow->Frame().right, 0);
+                       Constraint* rightSnapping = fRightVar->IsEqual(
+                               rightmostWindow->fRightVar);
+                       BString label("rightSnapping of ");
+                       label << fWindow->Title();
+                       rightSnapping->SetLabel(label.String());
+                       fSnappingConstraints->AddItem(rightSnapping);
+
+                       AddToSnappingList(rightmostWindow, SNAP_RIGHT, 
SNAP_RIGHT);
+                       AddToSnappingList(rightmostWindow, SNAP_TOP, 
SNAP_BOTTOM);
+                       rightmostWindow->AddToSnappingList(this, SNAP_RIGHT, 
SNAP_RIGHT);
+                       rightmostWindow->AddToSnappingList(this, SNAP_BOTTOM, 
SNAP_TOP);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s R2R & T2B 
list\n",
+                               rightmostWindow->Title(), 
rightmostWindow->WindowId(),
+                               fWindow->Title(), WindowId()));
+               }
+
+               // adjust other windows
+               for (int i = 0; i < fTopAdjacentWindows->CountItems(); i++) {
+                       SATWindowSnapping* window = 
dynamic_cast<SATWindowSnapping*>(
+                               
fStackAndTile->GetSATWindow(static_cast<Window*>(
+                                       fTopAdjacentWindows->ItemAt(i))));
+                       ASSERT(window);
+                       window->InitStackingAndSnapping();
+                       Constraint* topSnapping =
+                               
fStackAndTile->GetLinearSpec()->AddConstraint(-1,
+                                       window->fBottomVar, 1, fTopVar, 
OperatorType(EQ), 32);
+                       BString label("topSnapping of ");
+                       label << fWindow->Title();
+                       topSnapping->SetLabel(label.String());
+                       window->fSnappingConstraints->AddItem(topSnapping);
+
+                       AddToSnappingList(window, SNAP_TOP, SNAP_BOTTOM);
+                       window->AddToSnappingList(this, SNAP_BOTTOM, SNAP_TOP);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s T2B list\n", 
window->Title(),
+                               window->WindowId(), fWindow->Title(), 
WindowId()));
+               }
+       }
+
+       // snap other windows to the right border
+       if (!fRightAdjacentWindows->IsEmpty()) {
+               bounds = _BoundingRectAndWindows(fRightAdjacentWindows,
+                       &leftmostWindow, &topmostWindow, &rightmostWindow,
+                       &bottommostWindow);
+
+               // adjust window position & initialize snapping
+               fWindow->Desktop()->MoveWindowBy(fWindow,
+                       bounds.left - fWindow->Frame().right - 11, 0);
+               InitStackingAndSnapping();
+               topmostWindow->InitStackingAndSnapping();
+               bottommostWindow->InitStackingAndSnapping();
+
+               // adjust top border
+               if (fTopAdjacentWindows->IsEmpty()) {
+                       fWindow->Desktop()->MoveWindowBy(fWindow, 0,
+                               bounds.top - fWindow->Frame().top);
+                       Constraint* topSnapping = 
fTopVar->IsEqual(topmostWindow->fTopVar);
+                       BString label("topSnapping of ");
+                       label << fWindow->Title();
+                       topSnapping->SetLabel(label.String());
+                       fSnappingConstraints->AddItem(topSnapping);
+
+                       AddToSnappingList(topmostWindow, SNAP_TOP, SNAP_TOP);
+                       AddToSnappingList(topmostWindow, SNAP_RIGHT, SNAP_LEFT);
+                       topmostWindow->AddToSnappingList(this, SNAP_TOP, 
SNAP_TOP);
+                       topmostWindow->AddToSnappingList(this, SNAP_LEFT, 
SNAP_RIGHT);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s T2T & R2L 
list\n",
+                               topmostWindow->Title(), 
topmostWindow->WindowId(),
+                               fWindow->Title(), WindowId()));
+               }
+
+               // adjust bottom border
+               if (fBottomAdjacentWindows->IsEmpty()) {
+                       fWindow->Desktop()->ResizeWindowBy(fWindow, 0,
+                               bounds.bottom - fWindow->Frame().bottom);
+                       Constraint* bottomSnapping = fBottomVar->IsEqual(
+                               bottommostWindow->fBottomVar);
+                       BString label("bottomSnapping of ");
+                       label << fWindow->Title();
+                       bottomSnapping->SetLabel(label.String());
+                       fSnappingConstraints->AddItem(bottomSnapping);
+
+                       AddToSnappingList(bottommostWindow, SNAP_BOTTOM, 
SNAP_BOTTOM);
+                       AddToSnappingList(bottommostWindow, SNAP_RIGHT, 
SNAP_LEFT);
+                       bottommostWindow->AddToSnappingList(this, SNAP_BOTTOM, 
SNAP_BOTTOM);
+                       bottommostWindow->AddToSnappingList(this, SNAP_LEFT, 
SNAP_RIGHT);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s B2B & R2L 
list\n",
+                               bottommostWindow->Title(), 
bottommostWindow->WindowId(),
+                               fWindow->Title(), WindowId()));
+               }
+
+               // adjust other windows
+               for (int i = 0; i < fRightAdjacentWindows->CountItems(); i++) {
+                       SATWindowSnapping* window = 
dynamic_cast<SATWindowSnapping*>(
+                               
fStackAndTile->GetSATWindow(static_cast<Window*>(
+                                       fRightAdjacentWindows->ItemAt(i))));
+                       ASSERT(window);
+                       window->InitStackingAndSnapping();
+                       Constraint* rightSnapping =
+                               
fStackAndTile->GetLinearSpec()->AddConstraint(-1, fRightVar, 1,
+                                       window->fLeftVar, OperatorType(EQ), 11);
+                       BString label("rightSnapping of ");
+                       label << fWindow->Title();
+                       rightSnapping->SetLabel(label.String());
+                       window->fSnappingConstraints->AddItem(rightSnapping);
+
+                       AddToSnappingList(window, SNAP_RIGHT, SNAP_LEFT);
+                       window->AddToSnappingList(this, SNAP_LEFT, SNAP_RIGHT);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s R2L list\n", 
window->Title(),
+                               WindowId(), window->Title(), WindowId()));
+               }
+       }
+
+       // snap other windows to the bottom border
+       if (!fBottomAdjacentWindows->IsEmpty()) {
+               bounds = _BoundingRectAndWindows(fBottomAdjacentWindows,
+                       &leftmostWindow, &topmostWindow,
+                       &rightmostWindow, &bottommostWindow);
+
+               // adjust window position & initialize snapping
+               fWindow->Desktop()->MoveWindowBy(fWindow, 0,
+                       bounds.top - fWindow->Frame().bottom - 32);
+               InitStackingAndSnapping();
+               leftmostWindow->InitStackingAndSnapping();
+               rightmostWindow->InitStackingAndSnapping();
+
+               // adjust left border
+               if (fLeftAdjacentWindows->IsEmpty()) {
+                       fWindow->Desktop()->MoveWindowBy(fWindow,
+                               bounds.left - fWindow->Frame().left, 0);
+                       Constraint* leftSnapping = fLeftVar->IsEqual(
+                               leftmostWindow->fLeftVar);
+                       BString label("leftSnapping of ");
+                       label << fWindow->Title();
+                       leftSnapping->SetLabel(label.String());
+                       fSnappingConstraints->AddItem(leftSnapping);
+
+                       AddToSnappingList(leftmostWindow, SNAP_LEFT, SNAP_LEFT);
+                       AddToSnappingList(leftmostWindow, SNAP_BOTTOM, 
SNAP_TOP);
+                       leftmostWindow->AddToSnappingList(this, SNAP_LEFT, 
SNAP_LEFT);
+                       leftmostWindow->AddToSnappingList(this, SNAP_TOP, 
SNAP_BOTTOM);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s L2L & B2T 
list\n",
+                               leftmostWindow->Title(), 
leftmostWindow->WindowId(),
+                               fWindow->Title(), WindowId()));
+               }
+
+               // adjust right border
+               if (fRightAdjacentWindows->IsEmpty()) {
+                       fWindow->Desktop()->ResizeWindowBy(fWindow,
+                               bounds.right - fWindow->Frame().right, 0);
+                       Constraint* rightSnapping = fRightVar->IsEqual(
+                               rightmostWindow->fRightVar);
+                       BString label("rightSnapping of ");
+                       label << fWindow->Title();
+                       rightSnapping->SetLabel(label.String());
+                       fSnappingConstraints->AddItem(rightSnapping);
+
+                       AddToSnappingList(rightmostWindow, SNAP_RIGHT, 
SNAP_RIGHT);
+                       AddToSnappingList(rightmostWindow, SNAP_BOTTOM, 
SNAP_TOP);
+                       rightmostWindow->AddToSnappingList(this, SNAP_RIGHT, 
SNAP_RIGHT);
+                       rightmostWindow->AddToSnappingList(this, SNAP_TOP, 
SNAP_BOTTOM);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s R2R & B2T 
list\n",
+                               rightmostWindow->Title(), 
rightmostWindow->WindowId(),
+                               fWindow->Title(), WindowId()));
+               }
+
+               // adjust other windows
+               for (int i = 0; i < fBottomAdjacentWindows->CountItems(); i++) {
+                       SATWindowSnapping* window = 
dynamic_cast<SATWindowSnapping*>(
+                               
fStackAndTile->GetSATWindow(static_cast<Window*>(
+                                       fBottomAdjacentWindows->ItemAt(i))));
+                       ASSERT(window);
+                       window->InitStackingAndSnapping();
+                       Constraint* bottomSnapping =
+                               
fStackAndTile->GetLinearSpec()->AddConstraint(-1, fBottomVar, 1,
+                                       window->fTopVar, OperatorType(EQ), 32);
+                       BString label("bottomSnapping of ");
+                       label << fWindow->Title();
+                       bottomSnapping->SetLabel(label.String());
+                       window->fSnappingConstraints->AddItem(bottomSnapping);
+
+                       AddToSnappingList(window, SNAP_BOTTOM, SNAP_TOP);
+                       window->AddToSnappingList(this, SNAP_TOP, SNAP_BOTTOM);
+
+                       STRACE_SAT(("Adding %s[%d] to %s[%d]'s B2T list\n", 
window->Title(),
+                               window->WindowId(), fWindow->Title(), 
WindowId()));
+               }
+       }
+
+       // clear snapping candidates
+       delete fLeftAdjacentWindows;
+       delete fTopAdjacentWindows;
+       delete fRightAdjacentWindows;
+       delete fBottomAdjacentWindows;
+       fLeftAdjacentWindows = NULL;
+       fTopAdjacentWindows = NULL;
+       fRightAdjacentWindows = NULL;
+       fBottomAdjacentWindows = NULL;
+
+       STRACE_SAT(("Finished: SATWindowSnapping::_SnapWindow()\n"));
+}
+
+
+void
+SATWindowSnapping::AddToSnappingList(SATWindow* window,
+       SnapOrientation thisSnapOrientation, SnapOrientation 
otherSnapOrientation)
+{
+       AddToSnappingList(window->WindowId(),
+               thisSnapOrientation, otherSnapOrientation);
+}
+
+
+/*!    \brief Adds the given window's id to current window's snapping list,
+               according to given combo of snapping orientations. For example, 
if
+               thisSnapOrientation is SNAP_LEFT and otherSnapOrientation is
+               SNAP_RIGHT, then add the window's id to the left2right snapping 
list.
+               Discards duplicate id's
+
+       \param thisSnapOrientation snapping orientation for current window
+       \param otherSnapOrientation snapping orientation for given window
+ */
+void
+SATWindowSnapping::AddToSnappingList(int32 windowId,
+               SnapOrientation thisSnapOrientation,
+               SnapOrientation otherSnapOrientation) {
+
+       BList* windowIdList = GetSnappingList(thisSnapOrientation,
+               otherSnapOrientation, true);
+       // This may be the case if invalid snap orientation combo is given
+       // (e.g. top to left)
+       if (!windowIdList)
+               return;
+
+       // don't add id if already contained
+       for (int i = 0; i < windowIdList->CountItems(); i++) {
+               int32* id = static_cast<int32*>(windowIdList->ItemAt(i));
+               if (*id == windowId) {
+                       return;
+               }
+       }
+       int32* id = static_cast<int32*>(malloc(sizeof(int32)));
+       *id = windowId;
+       windowIdList->AddItem(id);
+
+       STRACE_SAT(("\tAdded %i to %s's %s 2 %s list\n",
+               windowId, fWindow->Title(), 
kSnapOrientationString[thisSnapOrientation],
+               kSnapOrientationString[otherSnapOrientation]));
+}
+
+
+/*!    \brief Removes given window from the snapping list according to the
+               combination of given snapping orientations (e.g. left to left,
+               top to bottom, etc.)
+
+       \param window the window to remove
+       \param thisSnapOrientation snapping orientation for this window
+       \param otherSnapOrientation snapping orientation for other window
+ */
+void
+SATWindowSnapping::RemoveFromSnappingList(int32 windowId,
+               SnapOrientation thisSnapOrientation,
+               SnapOrientation otherSnapOrientation) {
+       BList* windowIdList = GetSnappingList(thisSnapOrientation,
+               otherSnapOrientation, false);
+
+       // This may be the case if invalid snap orientation combo is given
+       // (e.g. top to left)
+       if (!windowIdList)
+               return;
+
+       for (int i = 0; i < windowIdList->CountItems(); i++) {
+               int32* id = static_cast<int32*>(windowIdList->ItemAt(i));
+               if (*id == windowId) {
+                       windowIdList->RemoveItem(i);
+                       free(id);
+
+                       STRACE_SAT(("\tRemoved %x from %s's %s 2 %s list\n",
+                               windowId, fWindow->Title(),
+                               kSnapOrientationString[thisSnapOrientation],
+                               kSnapOrientationString[otherSnapOrientation]));
+                       return;
+               }
+       }
+}
+
+
+/*!    \brief Returns a reference to the snapping list according to the
+               combination of given snapping orientations (e.g. left to left,
+               top to bottom, etc.). If the snapping list is not initialised,
+               then creates it before returning its reference.
+
+       \param thisSnapOrientation snapping orientation for this window
+       \param otherSnapOrientation snapping orientation for other window
+       \param createIfNull whether to create the list if null
+ */
+BList*

[... truncated: 1931 lines follow ...]

Other related posts:

  • » [haiku-commits] r36943 - haiku/branches/features/stack-and-tile/src/servers/app - clemens . zeidler