Refactoring of the Window class. Move window behaviour into separate WindowBehaviour class.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37524 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -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 && fWindow->TopView() != NULL) {
|
||||||
|
DrawingEngine* engine = fDecorator->GetDrawingEngine();
|
||||||
|
engine->LockParallelAccess();
|
||||||
|
engine->ConstrainClippingRegion(&fWindow->VisibleRegion());
|
||||||
|
|
||||||
|
fWindow->TopView()->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(®);
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -21,6 +21,7 @@ Server app_server :
|
|||||||
DecorManager.cpp
|
DecorManager.cpp
|
||||||
Decorator.cpp
|
Decorator.cpp
|
||||||
DefaultDecorator.cpp
|
DefaultDecorator.cpp
|
||||||
|
DefaultWindowBehaviour.cpp
|
||||||
Desktop.cpp
|
Desktop.cpp
|
||||||
DesktopSettings.cpp
|
DesktopSettings.cpp
|
||||||
DirectWindowInfo.cpp
|
DirectWindowInfo.cpp
|
||||||
@@ -57,6 +58,7 @@ Server app_server :
|
|||||||
View.cpp
|
View.cpp
|
||||||
VirtualScreen.cpp
|
VirtualScreen.cpp
|
||||||
Window.cpp
|
Window.cpp
|
||||||
|
WindowBehaviour.cpp
|
||||||
WindowList.cpp
|
WindowList.cpp
|
||||||
Workspace.cpp
|
Workspace.cpp
|
||||||
WorkspacesView.cpp
|
WorkspacesView.cpp
|
||||||
|
|||||||
+28
-463
@@ -16,6 +16,7 @@
|
|||||||
#include "Decorator.h"
|
#include "Decorator.h"
|
||||||
#include "DecorManager.h"
|
#include "DecorManager.h"
|
||||||
#include "Desktop.h"
|
#include "Desktop.h"
|
||||||
|
#include "DefaultWindowBehaviour.h"
|
||||||
#include "DrawingEngine.h"
|
#include "DrawingEngine.h"
|
||||||
#include "HWInterface.h"
|
#include "HWInterface.h"
|
||||||
#include "MessagePrivate.h"
|
#include "MessagePrivate.h"
|
||||||
@@ -39,7 +40,6 @@
|
|||||||
|
|
||||||
// Toggle debug output
|
// Toggle debug output
|
||||||
//#define DEBUG_WINDOW
|
//#define DEBUG_WINDOW
|
||||||
//#define DEBUG_WINDOW_CLICK
|
|
||||||
|
|
||||||
#ifdef DEBUG_WINDOW
|
#ifdef DEBUG_WINDOW
|
||||||
# define STRACE(x) printf x
|
# define STRACE(x) printf x
|
||||||
@@ -47,12 +47,6 @@
|
|||||||
# define STRACE(x) ;
|
# define STRACE(x) ;
|
||||||
#endif
|
#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)
|
// IMPORTANT: nested LockSingleWindow()s are not supported (by MultiLocker)
|
||||||
|
|
||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
@@ -96,25 +90,13 @@ Window::Window(const BRect& frame, const char *name,
|
|||||||
|
|
||||||
fRegionPool(),
|
fRegionPool(),
|
||||||
|
|
||||||
fIsClosing(false),
|
fWindowBehaviour(NULL),
|
||||||
fIsMinimizing(false),
|
|
||||||
fIsZooming(false),
|
|
||||||
fIsResizing(false),
|
|
||||||
fIsSlidingTab(false),
|
|
||||||
fIsDragging(false),
|
|
||||||
fActivateOnMouseUp(false),
|
|
||||||
|
|
||||||
fDecorator(NULL),
|
fDecorator(NULL),
|
||||||
fTopView(NULL),
|
fTopView(NULL),
|
||||||
fWindow(window),
|
fWindow(window),
|
||||||
fDrawingEngine(drawingEngine),
|
fDrawingEngine(drawingEngine),
|
||||||
fDesktop(window->Desktop()),
|
fDesktop(window->Desktop()),
|
||||||
|
|
||||||
fLastMousePosition(0.0f, 0.0f),
|
|
||||||
fMouseMoveDistance(0.0f),
|
|
||||||
fLastMoveTime(0),
|
|
||||||
fLastSnapTime(0),
|
|
||||||
|
|
||||||
fCurrentUpdateSession(&fUpdateSessions[0]),
|
fCurrentUpdateSession(&fUpdateSessions[0]),
|
||||||
fPendingUpdateSession(&fUpdateSessions[1]),
|
fPendingUpdateSession(&fUpdateSessions[1]),
|
||||||
fUpdateRequested(false),
|
fUpdateRequested(false),
|
||||||
@@ -154,6 +136,8 @@ Window::Window(const BRect& frame, const char *name,
|
|||||||
&fMaxWidth, &fMaxHeight);
|
&fMaxWidth, &fMaxHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fWindowBehaviour = new (std::nothrow)DefaultWindowBehaviour(this,
|
||||||
|
fDecorator);
|
||||||
|
|
||||||
// do we need to change our size to let the decorator fit?
|
// do we need to change our size to let the decorator fit?
|
||||||
// _ResizeBy() will adapt the frame for validity before resizing
|
// _ResizeBy() will adapt the frame for validity before resizing
|
||||||
@@ -187,6 +171,7 @@ Window::~Window()
|
|||||||
delete fTopView;
|
delete fTopView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete fWindowBehaviour;
|
||||||
delete fDecorator;
|
delete fDecorator;
|
||||||
|
|
||||||
delete fDrawingEngine;
|
delete fDrawingEngine;
|
||||||
@@ -196,7 +181,7 @@ Window::~Window()
|
|||||||
status_t
|
status_t
|
||||||
Window::InitCheck() const
|
Window::InitCheck() const
|
||||||
{
|
{
|
||||||
if (!fDrawingEngine)
|
if (!fDrawingEngine || !fWindowBehaviour)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
// TODO: anything else?
|
// TODO: anything else?
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -775,9 +760,6 @@ Window::EnableUpdateRequests()
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
static const bigtime_t kWindowActivationTimeout = 500000LL;
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Window::MouseDown(BMessage* message, BPoint where, int32* _viewToken)
|
Window::MouseDown(BMessage* message, BPoint where, int32* _viewToken)
|
||||||
{
|
{
|
||||||
@@ -787,136 +769,8 @@ Window::MouseDown(BMessage* message, BPoint where, int32* _viewToken)
|
|||||||
if (!fBorderRegionValid)
|
if (!fBorderRegionValid)
|
||||||
GetBorderRegion(&fBorderRegion);
|
GetBorderRegion(&fBorderRegion);
|
||||||
|
|
||||||
int32 modifiers = _ExtractModifiers(message);
|
bool eventEaten = fWindowBehaviour->MouseDown(message, where);
|
||||||
bool inBorderRegion = fBorderRegion.Contains(where);
|
if (!eventEaten) {
|
||||||
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 {
|
|
||||||
// click was inside the window contents
|
// click was inside the window contents
|
||||||
if (View* view = ViewAt(where)) {
|
if (View* view = ViewAt(where)) {
|
||||||
if (HasModal())
|
if (HasModal())
|
||||||
@@ -957,71 +811,7 @@ Window::MouseDown(BMessage* message, BPoint where, int32* _viewToken)
|
|||||||
void
|
void
|
||||||
Window::MouseUp(BMessage* message, BPoint where, int32* _viewToken)
|
Window::MouseUp(BMessage* message, BPoint where, int32* _viewToken)
|
||||||
{
|
{
|
||||||
bool invalidate = false;
|
fWindowBehaviour->MouseUp(message, where);
|
||||||
if (fDecorator) {
|
|
||||||
click_type action = _ActionFor(message);
|
|
||||||
|
|
||||||
// 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 (View* view = ViewAt(where)) {
|
||||||
if (HasModal())
|
if (HasModal())
|
||||||
@@ -1037,17 +827,6 @@ void
|
|||||||
Window::MouseMoved(BMessage *message, BPoint where, int32* _viewToken,
|
Window::MouseMoved(BMessage *message, BPoint where, int32* _viewToken,
|
||||||
bool isLatestMouseMoved, bool isFake)
|
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);
|
View* view = ViewAt(where);
|
||||||
if (view != NULL)
|
if (view != NULL)
|
||||||
*_viewToken = view->Token();
|
*_viewToken = view->Token();
|
||||||
@@ -1056,119 +835,7 @@ Window::MouseMoved(BMessage *message, BPoint where, int32* _viewToken,
|
|||||||
if (!isLatestMouseMoved)
|
if (!isLatestMouseMoved)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// limit the rate at which "mouse moved" events
|
fWindowBehaviour->MouseMoved(message, where, isFake);
|
||||||
// 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 = 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)
|
|
||||||
delta.x = 0;
|
|
||||||
|
|
||||||
BPoint oldRightBottom = fFrame.RightBottom();
|
|
||||||
|
|
||||||
fDesktop->ResizeWindowBy(this, delta.x, delta.y);
|
|
||||||
|
|
||||||
// constrain delta to true change in size
|
|
||||||
delta = fFrame.RightBottom() - oldRightBottom;
|
|
||||||
} else
|
|
||||||
delta = BPoint(0, 0);
|
|
||||||
}
|
|
||||||
// sliding tab
|
|
||||||
if (fIsSlidingTab) {
|
|
||||||
float loc = TabLocation();
|
|
||||||
// TODO: change to [0:1]
|
|
||||||
loc += delta.x;
|
|
||||||
if (fDesktop->SetWindowTabLocation(this, 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()
|
|
||||||
&& !IsFocus() && !(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 : this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mouse cursor
|
// mouse cursor
|
||||||
|
|
||||||
@@ -1182,77 +849,6 @@ Window::MouseMoved(BMessage *message, BPoint where, int32* _viewToken,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Window::_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 = fFrame;
|
|
||||||
BPoint offsetWithinFrame;
|
|
||||||
// TODO: Perhaps obtain the usable area (not covered by the Deskbar)?
|
|
||||||
BRect screenFrame = Screen()->Frame();
|
|
||||||
|
|
||||||
if (fDecorator) {
|
|
||||||
BRegion reg;
|
|
||||||
fDecorator->GetFootprint(®);
|
|
||||||
frame = reg.Frame();
|
|
||||||
offsetWithinFrame.x = fFrame.left - frame.left;
|
|
||||||
offsetWithinFrame.y = fFrame.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 - fFrame.top;
|
|
||||||
delta.x = frame.left - fFrame.left;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -1375,6 +971,24 @@ Window::IsVisible() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Window::IsDragging() const
|
||||||
|
{
|
||||||
|
if (!fWindowBehaviour)
|
||||||
|
return false;
|
||||||
|
return fWindowBehaviour->IsDragging();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Window::IsResizing() const
|
||||||
|
{
|
||||||
|
if (!fWindowBehaviour)
|
||||||
|
return false;
|
||||||
|
return fWindowBehaviour->IsResizing();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Window::SetSizeLimits(int32 minWidth, int32 maxWidth, int32 minHeight,
|
Window::SetSizeLimits(int32 minWidth, int32 maxWidth, int32 minHeight,
|
||||||
int32 maxHeight)
|
int32 maxHeight)
|
||||||
@@ -2226,53 +1840,6 @@ Window::_UpdateContentRegion()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
Window::_ExtractButtons(const BMessage* message) const
|
|
||||||
{
|
|
||||||
int32 buttons;
|
|
||||||
if (message->FindInt32("buttons", &buttons) != B_OK)
|
|
||||||
buttons = 0;
|
|
||||||
return buttons;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
Window::_ExtractModifiers(const BMessage* message) const
|
|
||||||
{
|
|
||||||
int32 modifiers;
|
|
||||||
if (message->FindInt32("modifiers", &modifiers) != B_OK)
|
|
||||||
modifiers = 0;
|
|
||||||
return modifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
click_type
|
|
||||||
Window::_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
|
|
||||||
Window::_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
|
void
|
||||||
Window::_ObeySizeLimits()
|
Window::_ObeySizeLimits()
|
||||||
{
|
{
|
||||||
@@ -2370,5 +1937,3 @@ Window::UpdateSession::AddCause(uint8 cause)
|
|||||||
{
|
{
|
||||||
fCause |= cause;
|
fCause |= cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class Desktop;
|
|||||||
class DrawingEngine;
|
class DrawingEngine;
|
||||||
class EventDispatcher;
|
class EventDispatcher;
|
||||||
class Screen;
|
class Screen;
|
||||||
|
class WindowBehaviour;
|
||||||
class WorkspacesView;
|
class WorkspacesView;
|
||||||
|
|
||||||
// TODO: move this into a proper place
|
// TODO: move this into a proper place
|
||||||
@@ -169,10 +170,12 @@ public:
|
|||||||
|
|
||||||
void SetCurrentWorkspace(int32 index)
|
void SetCurrentWorkspace(int32 index)
|
||||||
{ fCurrentWorkspace = index; }
|
{ fCurrentWorkspace = index; }
|
||||||
|
int32 CurrentWorkspace() const
|
||||||
|
{ return fCurrentWorkspace; }
|
||||||
bool IsVisible() const;
|
bool IsVisible() const;
|
||||||
|
|
||||||
bool IsDragging() const { return fIsDragging; }
|
bool IsDragging() const;
|
||||||
bool IsResizing() const { return fIsResizing; }
|
bool IsResizing() const;
|
||||||
|
|
||||||
void SetSizeLimits(int32 minWidth, int32 maxWidth,
|
void SetSizeLimits(int32 minWidth, int32 maxWidth,
|
||||||
int32 minHeight, int32 maxHeight);
|
int32 minHeight, int32 maxHeight);
|
||||||
@@ -244,6 +247,7 @@ public:
|
|||||||
static uint32 ValidWindowFlags();
|
static uint32 ValidWindowFlags();
|
||||||
static uint32 ValidWindowFlags(window_feel feel);
|
static uint32 ValidWindowFlags(window_feel feel);
|
||||||
|
|
||||||
|
BRegion& BorderRegion() { return fBorderRegion; }
|
||||||
protected:
|
protected:
|
||||||
void _ShiftPartOfRegion(BRegion* region,
|
void _ShiftPartOfRegion(BRegion* region,
|
||||||
BRegion* regionToShift, int32 xOffset,
|
BRegion* regionToShift, int32 xOffset,
|
||||||
@@ -260,20 +264,9 @@ protected:
|
|||||||
|
|
||||||
void _UpdateContentRegion();
|
void _UpdateContentRegion();
|
||||||
|
|
||||||
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 _ObeySizeLimits();
|
void _ObeySizeLimits();
|
||||||
void _PropagatePosition();
|
void _PropagatePosition();
|
||||||
|
|
||||||
void _AlterDeltaForSnap(BPoint& delta,
|
|
||||||
bigtime_t now);
|
|
||||||
|
|
||||||
BString fTitle;
|
BString fTitle;
|
||||||
// TODO: no fp rects anywhere
|
// TODO: no fp rects anywhere
|
||||||
BRect fFrame;
|
BRect fFrame;
|
||||||
@@ -309,26 +302,13 @@ protected:
|
|||||||
|
|
||||||
BObjectList<Window> fSubsets;
|
BObjectList<Window> fSubsets;
|
||||||
|
|
||||||
// TODO: remove those some day (let the decorator handle that stuff)
|
WindowBehaviour* fWindowBehaviour;
|
||||||
bool fIsClosing : 1;
|
|
||||||
bool fIsMinimizing : 1;
|
|
||||||
bool fIsZooming : 1;
|
|
||||||
bool fIsResizing : 1;
|
|
||||||
bool fIsSlidingTab : 1;
|
|
||||||
bool fIsDragging : 1;
|
|
||||||
bool fActivateOnMouseUp : 1;
|
|
||||||
|
|
||||||
::Decorator* fDecorator;
|
::Decorator* fDecorator;
|
||||||
View* fTopView;
|
View* fTopView;
|
||||||
::ServerWindow* fWindow;
|
::ServerWindow* fWindow;
|
||||||
DrawingEngine* fDrawingEngine;
|
DrawingEngine* fDrawingEngine;
|
||||||
::Desktop* fDesktop;
|
::Desktop* fDesktop;
|
||||||
|
|
||||||
BPoint fLastMousePosition;
|
|
||||||
float fMouseMoveDistance;
|
|
||||||
bigtime_t fLastMoveTime;
|
|
||||||
bigtime_t fLastSnapTime;
|
|
||||||
|
|
||||||
// The synchronization, which client drawing commands
|
// The synchronization, which client drawing commands
|
||||||
// belong to the redraw of which dirty region is handled
|
// belong to the redraw of which dirty region is handled
|
||||||
// through an UpdateSession. When the client has
|
// through an UpdateSession. When the client has
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#include "WindowBehaviour.h"
|
||||||
|
|
||||||
|
|
||||||
|
WindowBehaviour::WindowBehaviour()
|
||||||
|
:
|
||||||
|
fIsResizing(false),
|
||||||
|
fIsDragging(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WindowBehaviour::~WindowBehaviour()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef WINDOW_BEHAVIOUR_H
|
||||||
|
#define WINDOW_BEHAVIOUR_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Region.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BMessage;
|
||||||
|
|
||||||
|
|
||||||
|
class WindowBehaviour
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WindowBehaviour();
|
||||||
|
virtual ~WindowBehaviour();
|
||||||
|
|
||||||
|
//! \return true if event was a WindowBehaviour event and should be discard
|
||||||
|
virtual bool MouseDown(BMessage* message, BPoint where) = 0;
|
||||||
|
virtual void MouseUp(BMessage* message, BPoint where) = 0;
|
||||||
|
virtual void MouseMoved(BMessage *message, BPoint where,
|
||||||
|
bool isFake) = 0;
|
||||||
|
|
||||||
|
bool IsDragging() const { return fIsDragging; }
|
||||||
|
bool IsResizing() const { return fIsResizing; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool fIsResizing : 1;
|
||||||
|
bool fIsDragging : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user