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

  • From: clemens.zeidler@xxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 8 Jun 2010 00:14:16 +0200 (CEST)

Author: czeidler
Date: 2010-06-08 00:14:16 +0200 (Tue, 08 Jun 2010)
New Revision: 37053
Changeset: http://dev.haiku-os.org/changeset/37053/haiku

Added:
   
haiku/branches/features/stack-and-tile/src/servers/app/DefaultWindowBehaviour.cpp
   
haiku/branches/features/stack-and-tile/src/servers/app/DefaultWindowBehaviour.h
   haiku/branches/features/stack-and-tile/src/servers/app/WindowBehaviour.cpp
   haiku/branches/features/stack-and-tile/src/servers/app/WindowBehaviour.h
Modified:
   haiku/branches/features/stack-and-tile/src/servers/app/Jamfile
   haiku/branches/features/stack-and-tile/src/servers/app/Window.cpp
   haiku/branches/features/stack-and-tile/src/servers/app/Window.h
Log:
Introduce a new WindowBehaviour class as proposed by Ryan and Stippi. This 
class handle decorator events, e.g. mouse down/up/moved and translate them into 
the according actions.



Added: 
haiku/branches/features/stack-and-tile/src/servers/app/DefaultWindowBehaviour.cpp
===================================================================
--- 
haiku/branches/features/stack-and-tile/src/servers/app/DefaultWindowBehaviour.cpp
                           (rev 0)
+++ 
haiku/branches/features/stack-and-tile/src/servers/app/DefaultWindowBehaviour.cpp
   2010-06-07 22:14:16 UTC (rev 37053)
@@ -0,0 +1,505 @@
+#include "DefaultWindowBehaviour.h"
+
+#include "Desktop.h"
+#include "DrawingEngine.h"
+#include "Window.h"
+
+
+//#define DEBUG_WINDOW_CLICK
+
+#ifdef DEBUG_WINDOW_CLICK
+#      define STRACE_CLICK(x) printf x
+#else
+#      define STRACE_CLICK(x) ;
+#endif
+
+
+DefaultWindowBehaviour::DefaultWindowBehaviour(Window* window,
+       Decorator* decorator)
+       :
+       fWindow(window),
+       fDecorator(decorator),
+
+       fIsClosing(false),
+       fIsMinimizing(false),
+       fIsZooming(false),
+       fIsSlidingTab(false),
+       fActivateOnMouseUp(false),
+
+       fLastMousePosition(0.0f, 0.0f),
+       fMouseMoveDistance(0.0f),
+       fLastMoveTime(0),
+       fLastSnapTime(0)
+{
+       fDesktop = fWindow->Desktop();
+}
+
+
+DefaultWindowBehaviour::~DefaultWindowBehaviour()
+{
+       
+}
+
+
+static const bigtime_t kWindowActivationTimeout = 500000LL;
+
+
+bool
+DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where)
+{
+       int32 modifiers = _ExtractModifiers(message);
+       bool inBorderRegion = fWindow->BorderRegion().Contains(where);
+       bool windowModifier =
+               (fWindow->Flags() & B_NO_SERVER_SIDE_WINDOW_MODIFIERS) == 0
+               && (modifiers & (B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY
+                       | B_SHIFT_KEY)) == (B_COMMAND_KEY | B_CONTROL_KEY);
+       click_type action = CLICK_NONE;
+
+       if (windowModifier || inBorderRegion) {
+               // clicking Window visible area
+
+               int32 buttons = _ExtractButtons(message);
+
+               if (inBorderRegion)
+                       action = _ActionFor(message, buttons, modifiers);
+               else {
+                       if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0)
+                               action = CLICK_MOVE_TO_BACK;
+                       else if ((fWindow->Flags() & B_NOT_MOVABLE) == 0
+                                       && fDecorator != NULL)
+                               action = CLICK_DRAG;
+                       else {
+                               // pass click on to the application
+                               windowModifier = false;
+                       }
+               }
+       }
+
+       DesktopSettings desktopSettings(fDesktop);
+       if (windowModifier || inBorderRegion) {
+               if (!desktopSettings.AcceptFirstClick()) {
+                       // Ignore clicks on decorator buttons if the
+                       // non-floating window doesn't have focus
+                       if (!fWindow->IsFocus() && !fWindow->IsFloating()
+                               && action != CLICK_MOVE_TO_BACK
+                               && action != CLICK_RESIZE && action != 
CLICK_SLIDE_TAB)
+                               action = CLICK_DRAG;
+               }
+
+               // set decorator internals
+               switch (action) {
+                       case CLICK_CLOSE:
+                               fIsClosing = true;
+                               STRACE_CLICK(("===> CLICK_CLOSE\n"));
+                               break;
+
+                       case CLICK_ZOOM:
+                               fIsZooming = true;
+                               STRACE_CLICK(("===> CLICK_ZOOM\n"));
+                               break;
+
+                       case CLICK_MINIMIZE:
+                               if ((fWindow->Flags() & B_NOT_MINIMIZABLE) == 
0) {
+                                       fIsMinimizing = true;
+                                       STRACE_CLICK(("===> CLICK_MINIMIZE\n"));
+                               }
+                               break;
+
+                       case CLICK_DRAG:
+                               fIsDragging = true;
+                               fLastMousePosition = where;
+                               STRACE_CLICK(("===> CLICK_DRAG\n"));
+                               break;
+
+                       case CLICK_RESIZE:
+                               fIsResizing = true;
+                               fLastMousePosition = where;
+                               STRACE_CLICK(("===> CLICK_RESIZE\n"));
+                               break;
+
+                       case CLICK_SLIDE_TAB:
+                               fIsSlidingTab = true;
+                               fLastMousePosition = where;
+                               STRACE_CLICK(("===> CLICK_SLIDE_TAB\n"));
+                               break;
+
+                       default:
+                               break;
+               }
+
+               if (fDecorator != NULL) {
+                       // redraw decorator
+                       BRegion* visibleBorder = 
fWindow->RegionPool()->GetRegion();
+                       fWindow->GetBorderRegion(visibleBorder);
+                       visibleBorder->IntersectWith(&fWindow->VisibleRegion());
+
+                       DrawingEngine* engine = fDecorator->GetDrawingEngine();
+                       engine->LockParallelAccess();
+                       engine->ConstrainClippingRegion(visibleBorder);
+
+                       if (fIsZooming)
+                               fDecorator->SetZoom(true);
+                       else if (fIsClosing)
+                               fDecorator->SetClose(true);
+                       else if (fIsMinimizing)
+                               fDecorator->SetMinimize(true);
+
+                       engine->UnlockParallelAccess();
+
+                       fWindow->RegionPool()->Recycle(visibleBorder);
+               }
+
+               if (action == CLICK_MOVE_TO_BACK) {
+                       if (desktopSettings.MouseMode() == 
B_CLICK_TO_FOCUS_MOUSE) {
+                               bool covered = true;
+                               BRegion fullRegion;
+                               fWindow->GetFullRegion(&fullRegion);
+                               if (fullRegion == fWindow->VisibleRegion()) {
+                               // window is overlapped.
+                               covered = false;
+                               }
+                               if (fWindow != fDesktop->FrontWindow() && 
covered)
+                                       fDesktop->ActivateWindow(fWindow);
+                               else
+                                       fDesktop->SendWindowBehind(fWindow);
+                       } else
+                               fDesktop->SendWindowBehind(fWindow);
+               } else {
+                       fDesktop->SetMouseEventWindow(fWindow);
+
+                       // activate window if in click to activate mode, else 
only focus it
+                       if (desktopSettings.MouseMode() == B_NORMAL_MOUSE)
+                               fDesktop->ActivateWindow(fWindow);
+                       else {
+                               fDesktop->SetFocusWindow(fWindow);
+                               if (desktopSettings.MouseMode() == 
B_FOCUS_FOLLOWS_MOUSE
+                                       && (action == CLICK_DRAG || action == 
CLICK_RESIZE)) {
+                                       fActivateOnMouseUp = true;
+                                       fMouseMoveDistance = 0.0f;
+                                       fLastMoveTime = system_time();
+                               }
+                       }
+               }
+
+               return true;
+       }
+       return false;
+}
+
+
+void
+DefaultWindowBehaviour::MouseUp(BMessage* message, BPoint where)
+{
+       bool invalidate = false;
+       if (fDecorator) {
+               click_type action = _ActionFor(message);
+
+               // redraw decorator
+               BRegion* visibleBorder = fWindow->RegionPool()->GetRegion();
+               fWindow->GetBorderRegion(visibleBorder);
+               visibleBorder->IntersectWith(&fWindow->VisibleRegion());
+
+               DrawingEngine* engine = fDecorator->GetDrawingEngine();
+               engine->LockParallelAccess();
+               engine->ConstrainClippingRegion(visibleBorder);
+
+               if (fIsZooming) {
+                       fIsZooming = false;
+                       fDecorator->SetZoom(false);
+                       if (action == CLICK_ZOOM) {
+                               invalidate = true;
+                               fWindow->ServerWindow()->NotifyZoom();
+                       }
+               }
+               if (fIsClosing) {
+                       fIsClosing = false;
+                       fDecorator->SetClose(false);
+                       if (action == CLICK_CLOSE) {
+                               invalidate = true;
+                               fWindow->ServerWindow()->NotifyQuitRequested();
+                       }
+               }
+               if (fIsMinimizing) {
+                       fIsMinimizing = false;
+                       fDecorator->SetMinimize(false);
+                       if (action == CLICK_MINIMIZE) {
+                               invalidate = true;
+                               fWindow->ServerWindow()->NotifyMinimize(true);
+                       }
+               }
+
+               engine->UnlockParallelAccess();
+
+               fWindow->RegionPool()->Recycle(visibleBorder);
+
+               int32 buttons;
+               if (message->FindInt32("buttons", &buttons) != B_OK)
+                       buttons = 0;
+
+               // if the primary mouse button is released, stop
+               // dragging/resizing/sliding
+               if ((buttons & B_PRIMARY_MOUSE_BUTTON) == 0) {
+                       fIsDragging = false;
+                       fIsResizing = false;
+                       fIsSlidingTab = false;
+               }
+       }
+
+       // in FFM mode, activate the window and bring it
+       // to front in case this was a drag click but the
+       // mouse was not moved
+       if (fActivateOnMouseUp) {
+               fActivateOnMouseUp = false;
+               // on R5, there is a time window for this feature
+               // ie, click and press too long, nothing will happen
+               if (system_time() - fLastMoveTime < kWindowActivationTimeout)
+                       fDesktop->ActivateWindow(fWindow);
+       }
+}
+
+
+void
+DefaultWindowBehaviour::MouseMoved(BMessage *message, BPoint where, bool 
isFake)
+{
+       #if 0
+       if (fDecorator != NULL && fTopView != NULL) {
+               DrawingEngine* engine = fDecorator->GetDrawingEngine();
+               engine->LockParallelAccess();
+               engine->ConstrainClippingRegion(&VisibleRegion());
+
+               fTopView->MarkAt(engine, where);
+               engine->UnlockParallelAccess();
+       }
+       #endif
+       // limit the rate at which "mouse moved" events
+       // are handled that move or resize the window
+       bigtime_t now = 0;
+       if (fIsDragging || fIsResizing) {
+               now = system_time();
+               if (now - fLastMoveTime < 13333) {
+                       // TODO: add a "timed event" to query for
+                       // the then current mouse position
+                       return;
+               }
+               if (fActivateOnMouseUp) {
+                       if (now - fLastMoveTime >= kWindowActivationTimeout) {
+                               // This click is too long already for window 
activation.
+                               fActivateOnMouseUp = false;
+                       }
+               } else
+                       fLastMoveTime = now;
+       }
+
+       if (fDecorator) {
+               BRegion* visibleBorder = fWindow->RegionPool()->GetRegion();
+               fWindow->GetBorderRegion(visibleBorder);
+               visibleBorder->IntersectWith(&fWindow->VisibleRegion());
+
+               DrawingEngine* engine = fDecorator->GetDrawingEngine();
+               engine->LockParallelAccess();
+               engine->ConstrainClippingRegion(visibleBorder);
+
+               if (fIsZooming) {
+                       fDecorator->SetZoom(_ActionFor(message) == CLICK_ZOOM);
+               } else if (fIsClosing) {
+                       fDecorator->SetClose(_ActionFor(message) == 
CLICK_CLOSE);
+               } else if (fIsMinimizing) {
+                       fDecorator->SetMinimize(_ActionFor(message) == 
CLICK_MINIMIZE);
+               }
+
+               engine->UnlockParallelAccess();
+               fWindow->RegionPool()->Recycle(visibleBorder);
+       }
+
+       BPoint delta = where - fLastMousePosition;
+       // NOTE: "delta" is later used to change fLastMousePosition.
+       // If for some reason no change should take effect, delta
+       // is to be set to (0, 0) so that fLastMousePosition is not
+       // adjusted. This way the relative mouse position to the
+       // item being changed (border during resizing, tab during
+       // sliding...) stays fixed when the mouse is moved so that
+       // changes are taking effect again.
+
+       // If the window was moved enough, it doesn't come to
+       // the front in FFM mode when the mouse is released.
+       if (fActivateOnMouseUp) {
+               fMouseMoveDistance += delta.x * delta.x + delta.y * delta.y;
+               if (fMouseMoveDistance > 16.0f)
+                       fActivateOnMouseUp = false;
+               else
+                       delta = B_ORIGIN;
+       }
+
+       // moving
+       if (fIsDragging) {
+               if (!(fWindow->Flags() & B_NOT_MOVABLE)) {
+                       BPoint oldLeftTop = fWindow->Frame().LeftTop();
+
+                       _AlterDeltaForSnap(delta, now);
+                       fDesktop->MoveWindowBy(fWindow, delta.x, delta.y);
+
+                       // constrain delta to true change in position
+                       delta = fWindow->Frame().LeftTop() - oldLeftTop;
+               } else
+                       delta = BPoint(0, 0);
+       }
+       // resizing
+       if (fIsResizing) {
+               if (!(fWindow->Flags() & B_NOT_RESIZABLE)) {
+                       if (fWindow->Flags() & B_NOT_V_RESIZABLE)
+                               delta.y = 0;
+                       if (fWindow->Flags() & B_NOT_H_RESIZABLE)
+                               delta.x = 0;
+
+                       BPoint oldRightBottom = fWindow->Frame().RightBottom();
+
+                       fDesktop->ResizeWindowBy(fWindow, delta.x, delta.y);
+
+                       // constrain delta to true change in size
+                       delta = fWindow->Frame().RightBottom() - oldRightBottom;
+               } else
+                       delta = BPoint(0, 0);
+       }
+       // sliding tab
+       if (fIsSlidingTab) {
+               float loc = fWindow->TabLocation();
+               // TODO: change to [0:1]
+               loc += delta.x;
+               if (fDesktop->SetWindowTabLocation(fWindow, loc))
+                       delta.y = 0;
+               else
+                       delta = BPoint(0, 0);
+       }
+
+       // NOTE: fLastMousePosition is currently only
+       // used for window moving/resizing/sliding the tab
+       fLastMousePosition += delta;
+
+       // change focus in FFM mode
+       DesktopSettings desktopSettings(fDesktop);
+       if (desktopSettings.FocusFollowsMouse()
+               && !fWindow->IsFocus() && !(fWindow->Flags() & B_AVOID_FOCUS)) {
+               // If the mouse move is a fake one, we set the focus to NULL, 
which
+               // will cause the window that had focus last to retrieve it 
again - this
+               // makes FFM much nicer to use with the keyboard.
+               fDesktop->SetFocusWindow(isFake ? NULL : fWindow);
+       }
+}
+
+
+int32
+DefaultWindowBehaviour::_ExtractButtons(const BMessage* message) const
+{
+       int32 buttons;
+       if (message->FindInt32("buttons", &buttons) != B_OK)
+               buttons = 0;
+       return buttons;
+}
+
+
+int32
+DefaultWindowBehaviour::_ExtractModifiers(const BMessage* message) const
+{
+       int32 modifiers;
+       if (message->FindInt32("modifiers", &modifiers) != B_OK)
+               modifiers = 0;
+       return modifiers;
+}
+
+
+click_type
+DefaultWindowBehaviour::_ActionFor(const BMessage* message) const
+{
+       if (fDecorator == NULL)
+               return CLICK_NONE;
+
+       int32 buttons = _ExtractButtons(message);
+       int32 modifiers = _ExtractModifiers(message);
+       return _ActionFor(message, buttons, modifiers);
+}
+
+
+click_type
+DefaultWindowBehaviour::_ActionFor(const BMessage* message, int32 buttons,
+       int32 modifiers) const
+{
+       if (fDecorator == NULL)
+               return CLICK_NONE;
+
+       BPoint where;
+       if (message->FindPoint("where", &where) != B_OK)
+               return CLICK_NONE;
+
+       return fDecorator->Clicked(where, buttons, modifiers);
+}
+
+
+void
+DefaultWindowBehaviour::_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();
+
+       if (fDecorator) {
+               BRegion reg;
+               fDecorator->GetFootprint(&reg);
+               frame = reg.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;
+}

Added: 
haiku/branches/features/stack-and-tile/src/servers/app/DefaultWindowBehaviour.h
===================================================================
--- 
haiku/branches/features/stack-and-tile/src/servers/app/DefaultWindowBehaviour.h 
                            (rev 0)
+++ 
haiku/branches/features/stack-and-tile/src/servers/app/DefaultWindowBehaviour.h 
    2010-06-07 22:14:16 UTC (rev 37053)
@@ -0,0 +1,54 @@
+#ifndef DEFAULT_WINDOW_BEHAVIOUR_H
+#define DEFAULT_WINDOW_BEHAVIOUR_H
+
+
+#include "WindowBehaviour.h"
+
+#include "Decorator.h"
+
+
+class Desktop;
+class Window;
+
+
+class DefaultWindowBehaviour : public WindowBehaviour
+{
+       public:
+                                               DefaultWindowBehaviour(Window* 
window,
+                                                       Decorator* decorator);
+               virtual                 ~DefaultWindowBehaviour();
+
+               virtual bool    MouseDown(BMessage* message, BPoint where);
+               virtual void    MouseUp(BMessage* message, BPoint where);
+               virtual void    MouseMoved(BMessage *message, BPoint where,
+                                                       bool isFake);
+               
+       protected:
+               Window*                 fWindow;
+               Decorator*              fDecorator;
+               Desktop*                fDesktop;
+
+               bool                    fIsClosing : 1;
+               bool                    fIsMinimizing : 1;
+               bool                    fIsZooming : 1;
+               bool                    fIsSlidingTab : 1;
+               bool                    fActivateOnMouseUp : 1;
+
+               BPoint                  fLastMousePosition;
+               float                   fMouseMoveDistance;
+               bigtime_t               fLastMoveTime;
+               bigtime_t               fLastSnapTime;
+
+       private:
+               int32                   _ExtractButtons(const BMessage* 
message) const;
+               int32                   _ExtractModifiers(const BMessage* 
message) const;
+               click_type              _ActionFor(const BMessage* message) 
const;
+               click_type              _ActionFor(const BMessage* message, 
int32 buttons,
+                                                       int32 modifiers) const;
+
+               void                    _AlterDeltaForSnap(BPoint& delta,
+                                                       bigtime_t now);
+};
+
+
+#endif

Modified: haiku/branches/features/stack-and-tile/src/servers/app/Jamfile
===================================================================
--- haiku/branches/features/stack-and-tile/src/servers/app/Jamfile      
2010-06-07 21:17:49 UTC (rev 37052)
+++ haiku/branches/features/stack-and-tile/src/servers/app/Jamfile      
2010-06-07 22:14:16 UTC (rev 37053)
@@ -22,6 +22,7 @@
        DecorManager.cpp
        Decorator.cpp
        DefaultDecorator.cpp
+       DefaultWindowBehaviour.cpp
        Desktop.cpp
        DesktopSettings.cpp
        DirectWindowInfo.cpp
@@ -61,6 +62,7 @@
        View.cpp
        VirtualScreen.cpp
        Window.cpp
+       WindowBehaviour.cpp
        WindowList.cpp
        Workspace.cpp
        WorkspacesView.cpp

Modified: haiku/branches/features/stack-and-tile/src/servers/app/Window.cpp
===================================================================
--- haiku/branches/features/stack-and-tile/src/servers/app/Window.cpp   
2010-06-07 21:17:49 UTC (rev 37052)
+++ haiku/branches/features/stack-and-tile/src/servers/app/Window.cpp   
2010-06-07 22:14:16 UTC (rev 37053)
@@ -16,12 +16,14 @@
 #include "Decorator.h"
 #include "DecorManager.h"
 #include "Desktop.h"
+#include "DefaultWindowBehaviour.h"
 #include "DrawingEngine.h"
 #include "HWInterface.h"
 #include "MessagePrivate.h"
 #include "PortLink.h"
 #include "ServerApp.h"
 #include "ServerWindow.h"
+#include "WindowBehaviour.h"
 #include "Workspace.h"
 #include "WorkspacesView.h"
 
@@ -39,7 +41,6 @@
 
 // Toggle debug output
 //#define DEBUG_WINDOW
-//#define DEBUG_WINDOW_CLICK
 
 #ifdef DEBUG_WINDOW
 #      define STRACE(x) printf x
@@ -47,12 +48,6 @@
 #      define STRACE(x) ;
 #endif
 
-#ifdef DEBUG_WINDOW_CLICK
-#      define STRACE_CLICK(x) printf x
-#else
-#      define STRACE_CLICK(x) ;
-#endif
-
 // IMPORTANT: nested LockSingleWindow()s are not supported (by MultiLocker)
 
 using std::nothrow;
@@ -96,25 +91,13 @@
 
        fRegionPool(),
 
-       fIsClosing(false),
-       fIsMinimizing(false),
-       fIsZooming(false),
-       fIsResizing(false),
-       fIsSlidingTab(false),
-       fIsDragging(false),
-       fActivateOnMouseUp(false),
-
+       fWindowBehaviour(NULL),
        fDecorator(NULL),
        fTopView(NULL),
        fWindow(window),
        fDrawingEngine(drawingEngine),
        fDesktop(window->Desktop()),
 
-       fLastMousePosition(0.0f, 0.0f),
-       fMouseMoveDistance(0.0f),
-       fLastMoveTime(0),
-       fLastSnapTime(0),
-
        fCurrentUpdateSession(&fUpdateSessions[0]),
        fPendingUpdateSession(&fUpdateSessions[1]),
        fUpdateRequested(false),
@@ -154,6 +137,7 @@
                                &fMaxWidth, &fMaxHeight);
                }
        }
+       fWindowBehaviour = new DefaultWindowBehaviour(this, fDecorator);
 
        // do we need to change our size to let the decorator fit?
        // _ResizeBy() will adapt the frame for validity before resizing
@@ -196,7 +180,7 @@
 status_t
 Window::InitCheck() const
 {
-       if (!fDrawingEngine)
+       if (!fDrawingEngine || !fWindowBehaviour)
                return B_NO_MEMORY;
        // TODO: anything else?
        return B_OK;
@@ -775,9 +759,6 @@
 // #pragma mark -
 
 
-static const bigtime_t kWindowActivationTimeout = 500000LL;
-
-
 void
 Window::MouseDown(BMessage* message, BPoint where, int32* _viewToken)
 {
@@ -787,136 +768,8 @@
        if (!fBorderRegionValid)
                GetBorderRegion(&fBorderRegion);
 
-       int32 modifiers = _ExtractModifiers(message);
-       bool inBorderRegion = fBorderRegion.Contains(where);
-       bool windowModifier = (fFlags & B_NO_SERVER_SIDE_WINDOW_MODIFIERS) == 0
-               && (modifiers & (B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY
-                       | B_SHIFT_KEY)) == (B_COMMAND_KEY | B_CONTROL_KEY);
-       click_type action = CLICK_NONE;
-
-       if (windowModifier || inBorderRegion) {
-               // clicking Window visible area
-
-               int32 buttons = _ExtractButtons(message);
-
-               if (inBorderRegion)
-                       action = _ActionFor(message, buttons, modifiers);
-               else {
-                       if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0)
-                               action = CLICK_MOVE_TO_BACK;
-                       else if ((fFlags & B_NOT_MOVABLE) == 0 && fDecorator != 
NULL)
-                               action = CLICK_DRAG;
-                       else {
-                               // pass click on to the application
-                               windowModifier = false;
-                       }
-               }
-       }
-
-       if (windowModifier || inBorderRegion) {
-               if (!desktopSettings.AcceptFirstClick()) {
-                       // Ignore clicks on decorator buttons if the
-                       // non-floating window doesn't have focus
-                       if (!IsFocus() && !IsFloating() && action != 
CLICK_MOVE_TO_BACK
-                               && action != CLICK_RESIZE && action != 
CLICK_SLIDE_TAB)
-                               action = CLICK_DRAG;
-               }
-
-               // set decorator internals
-               switch (action) {
-                       case CLICK_CLOSE:
-                               fIsClosing = true;
-                               STRACE_CLICK(("===> CLICK_CLOSE\n"));
-                               break;
-
-                       case CLICK_ZOOM:
-                               fIsZooming = true;
-                               STRACE_CLICK(("===> CLICK_ZOOM\n"));
-                               break;
-
-                       case CLICK_MINIMIZE:
-                               if ((Flags() & B_NOT_MINIMIZABLE) == 0) {
-                                       fIsMinimizing = true;
-                                       STRACE_CLICK(("===> CLICK_MINIMIZE\n"));
-                               }
-                               break;
-
-                       case CLICK_DRAG:
-                               fIsDragging = true;
-                               fLastMousePosition = where;
-                               STRACE_CLICK(("===> CLICK_DRAG\n"));
-                               break;
-
-                       case CLICK_RESIZE:
-                               fIsResizing = true;
-                               fLastMousePosition = where;
-                               STRACE_CLICK(("===> CLICK_RESIZE\n"));
-                               break;
-
-                       case CLICK_SLIDE_TAB:
-                               fIsSlidingTab = true;
-                               fLastMousePosition = where;
-                               STRACE_CLICK(("===> CLICK_SLIDE_TAB\n"));
-                               break;
-
-                       default:
-                               break;
-               }
-
-               if (fDecorator != NULL) {
-                       // redraw decorator
-                       BRegion* visibleBorder = fRegionPool.GetRegion();
-                       GetBorderRegion(visibleBorder);
-                       visibleBorder->IntersectWith(&VisibleRegion());
-
-                       DrawingEngine* engine = fDecorator->GetDrawingEngine();
-                       engine->LockParallelAccess();
-                       engine->ConstrainClippingRegion(visibleBorder);
-
-                       if (fIsZooming)
-                               fDecorator->SetZoom(true);
-                       else if (fIsClosing)
-                               fDecorator->SetClose(true);
-                       else if (fIsMinimizing)
-                               fDecorator->SetMinimize(true);
-
-                       engine->UnlockParallelAccess();
-
-                       fRegionPool.Recycle(visibleBorder);
-               }
-
-               if (action == CLICK_MOVE_TO_BACK) {
-                       if (desktopSettings.MouseMode() == 
B_CLICK_TO_FOCUS_MOUSE) {
-                               bool covered = true;
-                               BRegion fullRegion;
-                               GetFullRegion(&fullRegion);
-                               if (fullRegion == VisibleRegion()) {
-                               // window is overlapped.
-                               covered = false;
-                               }
-                               if (this != fDesktop->FrontWindow() && covered)
-                                       fDesktop->ActivateWindow(this);
-                               else
-                                       fDesktop->SendWindowBehind(this);
-                       } else
-                               fDesktop->SendWindowBehind(this);
-               } else {
-                       fDesktop->SetMouseEventWindow(this);
-
-                       // activate window if in click to activate mode, else 
only focus it
-                       if (desktopSettings.MouseMode() == B_NORMAL_MOUSE)
-                               fDesktop->ActivateWindow(this);
-                       else {
-                               fDesktop->SetFocusWindow(this);
-                               if (desktopSettings.MouseMode() == 
B_FOCUS_FOLLOWS_MOUSE
-                                       && (action == CLICK_DRAG || action == 
CLICK_RESIZE)) {
-                                       fActivateOnMouseUp = true;
-                                       fMouseMoveDistance = 0.0f;
-                                       fLastMoveTime = system_time();
-                               }
-                       }
-               }
-       } else {
+       bool eventEaten = fWindowBehaviour->MouseDown(message, where);
+       if (!eventEaten) {
                // click was inside the window contents
                if (View* view = ViewAt(where)) {
                        if (HasModal())
@@ -957,72 +810,8 @@
 void
 Window::MouseUp(BMessage* message, BPoint where, int32* _viewToken)
 {
-       bool invalidate = false;
-       if (fDecorator) {
-               click_type action = _ActionFor(message);
+       fWindowBehaviour->MouseUp(message, where);
 
-               // redraw decorator
-               BRegion* visibleBorder = fRegionPool.GetRegion();
-               GetBorderRegion(visibleBorder);
-               visibleBorder->IntersectWith(&VisibleRegion());
-
-               DrawingEngine* engine = fDecorator->GetDrawingEngine();
-               engine->LockParallelAccess();
-               engine->ConstrainClippingRegion(visibleBorder);
-
-               if (fIsZooming) {
-                       fIsZooming = false;
-                       fDecorator->SetZoom(false);
-                       if (action == CLICK_ZOOM) {
-                               invalidate = true;
-                               fWindow->NotifyZoom();
-                       }
-               }
-               if (fIsClosing) {
-                       fIsClosing = false;
-                       fDecorator->SetClose(false);
-                       if (action == CLICK_CLOSE) {
-                               invalidate = true;
-                               fWindow->NotifyQuitRequested();
-                       }
-               }
-               if (fIsMinimizing) {
-                       fIsMinimizing = false;
-                       fDecorator->SetMinimize(false);
-                       if (action == CLICK_MINIMIZE) {
-                               invalidate = true;
-                               fWindow->NotifyMinimize(true);
-                       }
-               }
-
-               engine->UnlockParallelAccess();
-
-               fRegionPool.Recycle(visibleBorder);
-
-               int32 buttons;
-               if (message->FindInt32("buttons", &buttons) != B_OK)
-                       buttons = 0;
-
-               // if the primary mouse button is released, stop
-               // dragging/resizing/sliding
-               if ((buttons & B_PRIMARY_MOUSE_BUTTON) == 0) {
-                       fIsDragging = false;
-                       fIsResizing = false;
-                       fIsSlidingTab = false;
-               }
-       }
-
-       // in FFM mode, activate the window and bring it
-       // to front in case this was a drag click but the
-       // mouse was not moved
-       if (fActivateOnMouseUp) {
-               fActivateOnMouseUp = false;
-               // on R5, there is a time window for this feature
-               // ie, click and press too long, nothing will happen
-               if (system_time() - fLastMoveTime < kWindowActivationTimeout)
-                       fDesktop->ActivateWindow(this);
-       }
-
        if (View* view = ViewAt(where)) {
                if (HasModal())
                        return;
@@ -1037,17 +826,6 @@
 Window::MouseMoved(BMessage *message, BPoint where, int32* _viewToken,
        bool isLatestMouseMoved, bool isFake)
 {
-#if 0
-       if (fDecorator != NULL && fTopView != NULL) {
-               DrawingEngine* engine = fDecorator->GetDrawingEngine();
-               engine->LockParallelAccess();
-               engine->ConstrainClippingRegion(&VisibleRegion());
-
-               fTopView->MarkAt(engine, where);
-               engine->UnlockParallelAccess();
-       }
-#endif
-
        View* view = ViewAt(where);
        if (view != NULL)
                *_viewToken = view->Token();
@@ -1056,120 +834,8 @@
        if (!isLatestMouseMoved)
                return;
 
-       // limit the rate at which "mouse moved" events
-       // are handled that move or resize the window
-       bigtime_t now = 0;
-       if (fIsDragging || fIsResizing) {
-               now = system_time();
-               if (now - fLastMoveTime < 13333) {
-                       // TODO: add a "timed event" to query for
-                       // the then current mouse position
-                       return;
-               }
-               if (fActivateOnMouseUp) {
-                       if (now - fLastMoveTime >= kWindowActivationTimeout) {
-                               // This click is too long already for window 
activation.
-                               fActivateOnMouseUp = false;
-                       }
-               } else
-                       fLastMoveTime = now;
-       }
+       fWindowBehaviour->MouseMoved(message, where, isFake);
 
-       if (fDecorator) {
-               BRegion* visibleBorder = fRegionPool.GetRegion();
-               GetBorderRegion(visibleBorder);
-               visibleBorder->IntersectWith(&VisibleRegion());
-
-               DrawingEngine* engine = fDecorator->GetDrawingEngine();
-               engine->LockParallelAccess();
-               engine->ConstrainClippingRegion(visibleBorder);
-
-               if (fIsZooming) {
-                       fDecorator->SetZoom(_ActionFor(message) == CLICK_ZOOM);
-               } else if (fIsClosing) {
-                       fDecorator->SetClose(_ActionFor(message) == 
CLICK_CLOSE);
-               } else if (fIsMinimizing) {
-                       fDecorator->SetMinimize(_ActionFor(message) == 
CLICK_MINIMIZE);
-               }
-
-               engine->UnlockParallelAccess();
-               fRegionPool.Recycle(visibleBorder);
-       }
-
-       BPoint delta = where - fLastMousePosition;
-       // NOTE: "delta" is later used to change fLastMousePosition.
-       // If for some reason no change should take effect, delta
-       // is to be set to (0, 0) so that fLastMousePosition is not
-       // adjusted. This way the relative mouse position to the
-       // item being changed (border during resizing, tab during
-       // sliding...) stays fixed when the mouse is moved so that
-       // changes are taking effect again.
-
-       // If the window was moved enough, it doesn't come to
-       // the front in FFM mode when the mouse is released.
-       if (fActivateOnMouseUp) {
-               fMouseMoveDistance += delta.x * delta.x + delta.y * delta.y;
-               if (fMouseMoveDistance > 16.0f)
-                       fActivateOnMouseUp = false;
-               else
-                       delta = B_ORIGIN;
-       }
-
-       // moving
-       if (fIsDragging) {
-               if (!(Flags() & B_NOT_MOVABLE)) {
-                       BPoint oldLeftTop = fFrame.LeftTop();
-
-                       _AlterDeltaForSnap(delta, now);
-                       fDesktop->MoveWindowBy(this, delta.x, delta.y);
-
-                       // constrain delta to true change in position
-                       delta = fFrame.LeftTop() - oldLeftTop;
-               } else
-                       delta = BPoint(0, 0);
-       }
-       // resizing
-       if (fIsResizing) {
-               if (!(Flags() & B_NOT_RESIZABLE)) {
-                       if (Flags() & B_NOT_V_RESIZABLE)
-                               delta.y = 0;
-                       if (Flags() & B_NOT_H_RESIZABLE)

[... truncated: 338 lines follow ...]

Other related posts:

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