From b91ddd8116374910bd94bfe3592615f7799dc948 Mon Sep 17 00:00:00 2001 From: Clemens Zeidler Date: Mon, 4 Jul 2011 21:04:55 +0000 Subject: [PATCH] * Make the magnetic border code more accessible by moving the code into a separate class and use it in a new protected WindowBehaviour method. * Simplify the algorithm a bit, no functional changes are intended. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42377 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/DefaultWindowBehaviour.cpp | 85 +++------------------ src/servers/app/DefaultWindowBehaviour.h | 8 +- src/servers/app/Jamfile | 1 + src/servers/app/MagneticBorder.cpp | 87 ++++++++++++++++++++++ src/servers/app/MagneticBorder.h | 34 +++++++++ src/servers/app/WindowBehaviour.cpp | 7 ++ src/servers/app/WindowBehaviour.h | 8 ++ 7 files changed, 154 insertions(+), 76 deletions(-) create mode 100644 src/servers/app/MagneticBorder.cpp create mode 100644 src/servers/app/MagneticBorder.h diff --git a/src/servers/app/DefaultWindowBehaviour.cpp b/src/servers/app/DefaultWindowBehaviour.cpp index 4e3b78b686..c49a6df485 100644 --- a/src/servers/app/DefaultWindowBehaviour.cpp +++ b/src/servers/app/DefaultWindowBehaviour.cpp @@ -210,8 +210,7 @@ struct DefaultWindowBehaviour::DragState : MouseTrackingState { bool activateOnMouseUp, bool minimizeCheckOnMouseUp) : MouseTrackingState(behavior, where, activateOnMouseUp, - minimizeCheckOnMouseUp), - fLastSnapTime(0) + minimizeCheckOnMouseUp) { } @@ -235,7 +234,7 @@ struct DefaultWindowBehaviour::DragState : MouseTrackingState { if (!(fWindow->Flags() & B_NOT_MOVABLE)) { BPoint oldLeftTop = fWindow->Frame().LeftTop(); - _AlterDeltaForSnap(delta, now); + fBehavior.AlterDeltaForSnap(fWindow, delta, now); fDesktop->MoveWindowBy(fWindow, delta.x, delta.y); // constrain delta to true change in position @@ -243,78 +242,6 @@ struct DefaultWindowBehaviour::DragState : MouseTrackingState { } else delta = BPoint(0, 0); } - -private: - void _AlterDeltaForSnap(BPoint& delta, bigtime_t now) - { - // Alter the delta (which is a proposed offset used while dragging a - // window) so that the frame of the window 'snaps' to the edges of the - // screen. - - const bigtime_t kSnappingDuration = 1500000LL; - const bigtime_t kSnappingPause = 3000000LL; - const float kSnapDistance = 8.0f; - - if (now - fLastSnapTime > kSnappingDuration - && now - fLastSnapTime < kSnappingPause) { - // Maintain a pause between snapping. - return; - } - - BRect frame = fWindow->Frame(); - BPoint offsetWithinFrame; - // TODO: Perhaps obtain the usable area (not covered by the Deskbar)? - BRect screenFrame = fWindow->Screen()->Frame(); - - Decorator* decorator = fWindow->Decorator(); - if (decorator) { - frame = decorator->GetFootprint().Frame(); - offsetWithinFrame.x = fWindow->Frame().left - frame.left; - offsetWithinFrame.y = fWindow->Frame().top - frame.top; - } - - frame.OffsetBy(delta); - - float leftDist = fabs(frame.left - screenFrame.left); - float topDist = fabs(frame.top - screenFrame.top); - float rightDist = fabs(frame.right - screenFrame.right); - float bottomDist = fabs(frame.bottom - screenFrame.bottom); - - bool snapped = false; - if (leftDist < kSnapDistance || rightDist < kSnapDistance) { - snapped = true; - if (leftDist < rightDist) { - frame.right -= frame.left; - frame.left = 0.0f; - } else { - frame.left -= frame.right - screenFrame.right; - frame.right = screenFrame.right; - } - } - - if (topDist < kSnapDistance || bottomDist < kSnapDistance) { - snapped = true; - if (topDist < bottomDist) { - frame.bottom -= frame.top; - frame.top = 0.0f; - } else { - frame.top -= frame.bottom - screenFrame.bottom; - frame.bottom = screenFrame.bottom; - } - } - if (snapped && now - fLastSnapTime > kSnappingPause) - fLastSnapTime = now; - - - frame.top += offsetWithinFrame.y; - frame.left += offsetWithinFrame.x; - - delta.y = frame.top - fWindow->Frame().top; - delta.x = frame.left - fWindow->Frame().left; - } - -private: - bigtime_t fLastSnapTime; }; @@ -965,6 +892,14 @@ DefaultWindowBehaviour::ModifiersChanged(int32 modifiers) } +bool +DefaultWindowBehaviour::AlterDeltaForSnap(Window* window, BPoint& delta, + bigtime_t now) +{ + return fMagneticBorder.AlterDeltaForSnap(window, delta, now); +} + + bool DefaultWindowBehaviour::_IsWindowModifier(int32 modifiers) const { diff --git a/src/servers/app/DefaultWindowBehaviour.h b/src/servers/app/DefaultWindowBehaviour.h index 14a0977092..6452eb43bc 100644 --- a/src/servers/app/DefaultWindowBehaviour.h +++ b/src/servers/app/DefaultWindowBehaviour.h @@ -17,8 +17,9 @@ #include "WindowBehaviour.h" -#include "ServerCursor.h" #include "Decorator.h" +#include "MagneticBorder.h" +#include "ServerCursor.h" class Desktop; @@ -39,6 +40,9 @@ public: virtual void ModifiersChanged(int32 modifiers); +protected: + virtual bool AlterDeltaForSnap(Window* window, BPoint& delta, + bigtime_t now); private: enum Action { ACTION_NONE, @@ -104,6 +108,8 @@ protected: Desktop* fDesktop; State* fState; int32 fLastModifiers; + + MagneticBorder fMagneticBorder; }; diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile index 0eca58afa8..6fb19d7b7f 100644 --- a/src/servers/app/Jamfile +++ b/src/servers/app/Jamfile @@ -39,6 +39,7 @@ Server app_server : InputManager.cpp IntPoint.cpp IntRect.cpp + MagneticBorder.cpp MessageLooper.cpp MultiLocker.cpp OffscreenServerWindow.cpp diff --git a/src/servers/app/MagneticBorder.cpp b/src/servers/app/MagneticBorder.cpp new file mode 100644 index 0000000000..a402608524 --- /dev/null +++ b/src/servers/app/MagneticBorder.cpp @@ -0,0 +1,87 @@ +/* + * Copyright 2010-2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Stephan Aßmus + * Ingo Weinhold + * Clemens Zeidler + */ + + +#include "MagneticBorder.h" + +#include "Decorator.h" +#include "Window.h" +#include "Screen.h" + + +MagneticBorder::MagneticBorder() + : + fLastSnapTime(0) +{ + +} + + +bool +MagneticBorder::AlterDeltaForSnap(Window* window, BPoint& delta, bigtime_t now) +{ + BRect frame = window->Frame(); + Decorator* decorator = window->Decorator(); + if (decorator) + frame = decorator->GetFootprint().Frame(); + + return AlterDeltaForSnap(window->Screen(), frame, delta, now); +} + + +bool +MagneticBorder::AlterDeltaForSnap(const Screen* screen, BRect& frame, + BPoint& delta, bigtime_t now) +{ + // Alter the delta (which is a proposed offset used while dragging a + // window) so that the frame of the window 'snaps' to the edges of the + // screen. + + const bigtime_t kSnappingDuration = 1500000LL; + const bigtime_t kSnappingPause = 3000000LL; + const float kSnapDistance = 8.0f; + + if (now - fLastSnapTime > kSnappingDuration + && now - fLastSnapTime < kSnappingPause) { + // Maintain a pause between snapping. + return false; + } + + // TODO: Perhaps obtain the usable area (not covered by the Deskbar)? + BRect screenFrame = screen->Frame(); + BRect originalFrame = frame; + frame.OffsetBy(delta); + + float leftDist = fabs(frame.left - screenFrame.left); + float topDist = fabs(frame.top - screenFrame.top); + float rightDist = fabs(frame.right - screenFrame.right); + float bottomDist = fabs(frame.bottom - screenFrame.bottom); + + bool snapped = false; + if (leftDist < kSnapDistance || rightDist < kSnapDistance) { + snapped = true; + if (leftDist < rightDist) + delta.x = screenFrame.left - originalFrame.left; + else + delta.x = screenFrame.right - originalFrame.right; + } + + if (topDist < kSnapDistance || bottomDist < kSnapDistance) { + snapped = true; + if (topDist < bottomDist) + delta.y = screenFrame.top - originalFrame.top; + else + delta.y = screenFrame.bottom - originalFrame.bottom; + } + if (snapped && now - fLastSnapTime > kSnappingPause) + fLastSnapTime = now; + + return snapped; +} diff --git a/src/servers/app/MagneticBorder.h b/src/servers/app/MagneticBorder.h new file mode 100644 index 0000000000..88818ad437 --- /dev/null +++ b/src/servers/app/MagneticBorder.h @@ -0,0 +1,34 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Clemens Zeidler + */ +#ifndef MAGNETIC_BORDRER_H +#define MAGNETIC_BORDRER_H + + +#include +#include + + +class Screen; +class Window; + + +class MagneticBorder { +public: + MagneticBorder(); + + bool AlterDeltaForSnap(Window* window, BPoint& delta, + bigtime_t now); + bool AlterDeltaForSnap(const Screen* screen, + BRect& frame, BPoint& delta, bigtime_t now); + +private: + bigtime_t fLastSnapTime; +}; + + +#endif // MAGNETIC_BORDRER_H diff --git a/src/servers/app/WindowBehaviour.cpp b/src/servers/app/WindowBehaviour.cpp index ccc9a0868c..1a3108bd2f 100644 --- a/src/servers/app/WindowBehaviour.cpp +++ b/src/servers/app/WindowBehaviour.cpp @@ -29,6 +29,13 @@ WindowBehaviour::ModifiersChanged(int32 modifiers) } +bool +WindowBehaviour::AlterDeltaForSnap(Window* window, BPoint& delta, bigtime_t now) +{ + return false; +} + + /*! \fn WindowBehaviour::MouseDown() \brief Handles a mouse-down message for the window. diff --git a/src/servers/app/WindowBehaviour.h b/src/servers/app/WindowBehaviour.h index 425ef2a5fd..00770d5dcc 100644 --- a/src/servers/app/WindowBehaviour.h +++ b/src/servers/app/WindowBehaviour.h @@ -16,6 +16,7 @@ class BMessage; class ClickTarget; +class Window; class WindowBehaviour { @@ -35,6 +36,13 @@ public: bool IsDragging() const { return fIsDragging; } bool IsResizing() const { return fIsResizing; } +protected: + /*! The window is going to be moved by delta. This hook should be used to + implement the magnetic screen border, i.e. alter the delta accordantly. + \return true if delta has been modified. */ + virtual bool AlterDeltaForSnap(Window* window, BPoint& delta, + bigtime_t now); + protected: bool fIsResizing : 1; bool fIsDragging : 1;