* Got rid of DefaultWindowBehaviour::Region again. Since we also need to
discriminate between the different borders and corners, there wasn't much difference between it and Decorator::Region anymore and we can as well use the latter. * Added new state ManageWindowState which is entered when the mouse is over the window and the window management modifiers are held down. When being in this state the borders that will be resized when pressing the right mouse button are highlighted. * Added State::ExitState() hook for cleanup work. * _NextState() does now call Desktop::SetMouseEventWindow() for our window when entering a new state, respectively resets it when going stateless. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39652 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -57,9 +57,13 @@ struct DefaultWindowBehaviour::State {
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool MouseDown(BMessage* message, BPoint where)
|
||||
virtual void ExitState(State* nextState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool MouseDown(BMessage* message, BPoint where, bool& _unhandled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void MouseUp(BMessage* message, BPoint where)
|
||||
@@ -70,6 +74,10 @@ struct DefaultWindowBehaviour::State {
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ModifiersChanged(BPoint where, int32 modifiers)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
DefaultWindowBehaviour& fBehavior;
|
||||
Window* fWindow;
|
||||
@@ -206,7 +214,7 @@ struct DefaultWindowBehaviour::DragState : MouseTrackingState {
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool MouseDown(BMessage* message, BPoint where)
|
||||
virtual bool MouseDown(BMessage* message, BPoint where, bool& _unhandled)
|
||||
{
|
||||
// right-click while dragging shall bring the window to front
|
||||
int32 buttons = message->FindInt32("buttons");
|
||||
@@ -215,10 +223,10 @@ struct DefaultWindowBehaviour::DragState : MouseTrackingState {
|
||||
fDesktop->ActivateWindow(fWindow);
|
||||
else
|
||||
fDesktop->SendWindowBehind(fWindow);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return MouseTrackingState::MouseDown(message, where);
|
||||
return MouseTrackingState::MouseDown(message, where, _unhandled);
|
||||
}
|
||||
|
||||
virtual void MouseMovedAction(BPoint& delta, bigtime_t now)
|
||||
@@ -367,72 +375,61 @@ struct DefaultWindowBehaviour::SlideTabState : MouseTrackingState {
|
||||
|
||||
|
||||
struct DefaultWindowBehaviour::ResizeBorderState : MouseTrackingState {
|
||||
ResizeBorderState(DefaultWindowBehaviour& behavior, BPoint where)
|
||||
ResizeBorderState(DefaultWindowBehaviour& behavior, BPoint where,
|
||||
Decorator::Region region)
|
||||
:
|
||||
MouseTrackingState(behavior, where, true, false,
|
||||
B_SECONDARY_MOUSE_BUTTON),
|
||||
fHorizontal(NONE),
|
||||
fVertical(NONE)
|
||||
{
|
||||
// Compute the window center relative location of where. We divide by
|
||||
// the width respective the height, so we compensate for the window's
|
||||
// aspect ratio.
|
||||
BRect frame(fWindow->Frame());
|
||||
if (frame.Width() + 1 == 0 || frame.Height() + 1 == 0)
|
||||
return;
|
||||
|
||||
float x = (where.x - (frame.left + frame.right) / 2)
|
||||
/ (frame.Width() + 1);
|
||||
float y = (where.y - (frame.top + frame.bottom) / 2)
|
||||
/ (frame.Height() + 1);
|
||||
|
||||
// compute the angle
|
||||
if (x == 0 && y == 0)
|
||||
return;
|
||||
|
||||
float angle = atan2f(y, x);
|
||||
|
||||
// rotate by 22.5 degree to align our sectors with 45 degree multiples
|
||||
angle += M_PI / 8;
|
||||
|
||||
// add 180 degree to the negative values, so we get a nice 0 to 360
|
||||
// degree range
|
||||
if (angle < 0)
|
||||
angle += M_PI * 2;
|
||||
|
||||
switch (int(angle / M_PI_4)) {
|
||||
case 0:
|
||||
fHorizontal = RIGHT;
|
||||
switch (region) {
|
||||
case Decorator::REGION_TAB:
|
||||
// TODO: Handle like the border it is attached to (top/left)?
|
||||
break;
|
||||
case 1:
|
||||
fHorizontal = RIGHT;
|
||||
fVertical = BOTTOM;
|
||||
break;
|
||||
case 2:
|
||||
fVertical = BOTTOM;
|
||||
break;
|
||||
case 3:
|
||||
fHorizontal = LEFT;
|
||||
fVertical = BOTTOM;
|
||||
break;
|
||||
case 4:
|
||||
case Decorator::REGION_LEFT_BORDER:
|
||||
fHorizontal = LEFT;
|
||||
break;
|
||||
case 5:
|
||||
case Decorator::REGION_RIGHT_BORDER:
|
||||
fHorizontal = RIGHT;
|
||||
break;
|
||||
case Decorator::REGION_TOP_BORDER:
|
||||
fVertical = TOP;
|
||||
break;
|
||||
case Decorator::REGION_BOTTOM_BORDER:
|
||||
fVertical = BOTTOM;
|
||||
break;
|
||||
case Decorator::REGION_LEFT_TOP_CORNER:
|
||||
fHorizontal = LEFT;
|
||||
fVertical = TOP;
|
||||
break;
|
||||
case 6:
|
||||
case Decorator::REGION_LEFT_BOTTOM_CORNER:
|
||||
fHorizontal = LEFT;
|
||||
fVertical = BOTTOM;
|
||||
break;
|
||||
case Decorator::REGION_RIGHT_TOP_CORNER:
|
||||
fHorizontal = RIGHT;
|
||||
fVertical = TOP;
|
||||
break;
|
||||
case 7:
|
||||
case Decorator::REGION_RIGHT_BOTTOM_CORNER:
|
||||
fHorizontal = RIGHT;
|
||||
fVertical = BOTTOM;
|
||||
break;
|
||||
default:
|
||||
fHorizontal = RIGHT;
|
||||
fVertical = TOP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ResizeBorderState(DefaultWindowBehaviour& behavior, BPoint where,
|
||||
int8 horizontal, int8 vertical)
|
||||
:
|
||||
MouseTrackingState(behavior, where, true, false,
|
||||
B_SECONDARY_MOUSE_BUTTON),
|
||||
fHorizontal(horizontal),
|
||||
fVertical(vertical)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void MouseMovedAction(BPoint& delta, bigtime_t now)
|
||||
{
|
||||
if ((fWindow->Flags() & B_NOT_RESIZABLE) != 0) {
|
||||
@@ -473,18 +470,6 @@ struct DefaultWindowBehaviour::ResizeBorderState : MouseTrackingState {
|
||||
fDesktop->SendWindowBehind(fWindow);
|
||||
}
|
||||
|
||||
private:
|
||||
enum {
|
||||
// 1 for the "natural" resize border, -1 for the opposite,
|
||||
// so multiplying the movement delta by that value results in the size
|
||||
// change.
|
||||
LEFT = -1,
|
||||
TOP = -1,
|
||||
NONE = 0,
|
||||
RIGHT = 1,
|
||||
BOTTOM = 1
|
||||
};
|
||||
|
||||
private:
|
||||
int8 fHorizontal;
|
||||
int8 fVertical;
|
||||
@@ -495,7 +480,8 @@ private:
|
||||
|
||||
|
||||
struct DefaultWindowBehaviour::DecoratorButtonState : State {
|
||||
DecoratorButtonState(DefaultWindowBehaviour& behavior, Region button)
|
||||
DecoratorButtonState(DefaultWindowBehaviour& behavior,
|
||||
Decorator::Region button)
|
||||
:
|
||||
State(behavior),
|
||||
fButton(button)
|
||||
@@ -525,21 +511,21 @@ struct DefaultWindowBehaviour::DecoratorButtonState : State {
|
||||
engine->ConstrainClippingRegion(visibleBorder);
|
||||
|
||||
switch (fButton) {
|
||||
case REGION_CLOSE_BUTTON:
|
||||
case Decorator::REGION_CLOSE_BUTTON:
|
||||
decorator->SetClose(false);
|
||||
if (fBehavior._RegionFor(message) == REGION_CLOSE_BUTTON)
|
||||
if (fBehavior._RegionFor(message) == fButton)
|
||||
fWindow->ServerWindow()->NotifyQuitRequested();
|
||||
break;
|
||||
|
||||
case REGION_ZOOM_BUTTON:
|
||||
case Decorator::REGION_ZOOM_BUTTON:
|
||||
decorator->SetZoom(false);
|
||||
if (fBehavior._RegionFor(message) == REGION_ZOOM_BUTTON)
|
||||
if (fBehavior._RegionFor(message) == fButton)
|
||||
fWindow->ServerWindow()->NotifyZoom();
|
||||
break;
|
||||
|
||||
case REGION_MINIMIZE_BUTTON:
|
||||
case Decorator::REGION_MINIMIZE_BUTTON:
|
||||
decorator->SetMinimize(false);
|
||||
if (fBehavior._RegionFor(message) == REGION_MINIMIZE_BUTTON)
|
||||
if (fBehavior._RegionFor(message) == fButton)
|
||||
fWindow->ServerWindow()->NotifyMinimize(true);
|
||||
break;
|
||||
|
||||
@@ -572,20 +558,20 @@ private:
|
||||
engine->LockParallelAccess();
|
||||
engine->ConstrainClippingRegion(visibleBorder);
|
||||
|
||||
Region hitRegion = message != NULL
|
||||
Decorator::Region hitRegion = message != NULL
|
||||
? fBehavior._RegionFor(message) : fButton;
|
||||
|
||||
switch (fButton) {
|
||||
case REGION_CLOSE_BUTTON:
|
||||
decorator->SetClose(hitRegion == REGION_CLOSE_BUTTON);
|
||||
case Decorator::REGION_CLOSE_BUTTON:
|
||||
decorator->SetClose(hitRegion == fButton);
|
||||
break;
|
||||
|
||||
case REGION_ZOOM_BUTTON:
|
||||
decorator->SetZoom(hitRegion == REGION_ZOOM_BUTTON);
|
||||
case Decorator::REGION_ZOOM_BUTTON:
|
||||
decorator->SetZoom(hitRegion == fButton);
|
||||
break;
|
||||
|
||||
case REGION_MINIMIZE_BUTTON:
|
||||
decorator->SetMinimize(hitRegion == REGION_MINIMIZE_BUTTON);
|
||||
case Decorator::REGION_MINIMIZE_BUTTON:
|
||||
decorator->SetMinimize(hitRegion == fButton);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -598,7 +584,141 @@ private:
|
||||
}
|
||||
|
||||
protected:
|
||||
Region fButton;
|
||||
Decorator::Region fButton;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - ManageWindowState
|
||||
|
||||
|
||||
struct DefaultWindowBehaviour::ManageWindowState : State {
|
||||
ManageWindowState(DefaultWindowBehaviour& behavior, BPoint where)
|
||||
:
|
||||
State(behavior),
|
||||
fLastMousePosition(where),
|
||||
fHorizontal(NONE),
|
||||
fVertical(NONE)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void EnterState(State* previousState)
|
||||
{
|
||||
_UpdateBorders(fLastMousePosition);
|
||||
}
|
||||
|
||||
virtual void ExitState(State* nextState)
|
||||
{
|
||||
fBehavior._SetBorderHighlights(fHorizontal, fVertical, false);
|
||||
}
|
||||
|
||||
virtual bool MouseDown(BMessage* message, BPoint where, bool& _unhandled)
|
||||
{
|
||||
// We're only interested, if the secondary mouse button was pressed.
|
||||
// Othewise let the our caller handle the event.
|
||||
int32 buttons = message->FindInt32("buttons");
|
||||
if ((buttons & B_SECONDARY_MOUSE_BUTTON) == 0) {
|
||||
_unhandled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
fBehavior._NextState(new (std::nothrow) ResizeBorderState(fBehavior,
|
||||
where, fHorizontal, fVertical));
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void MouseMoved(BMessage* message, BPoint where, bool isFake)
|
||||
{
|
||||
// If the mouse is still over our window, update the borders. Otherwise
|
||||
// leave the state.
|
||||
if (fDesktop->WindowAt(where) == fWindow) {
|
||||
fLastMousePosition = where;
|
||||
_UpdateBorders(fLastMousePosition);
|
||||
} else
|
||||
fBehavior._NextState(NULL);
|
||||
}
|
||||
|
||||
virtual void ModifiersChanged(BPoint where, int32 modifiers)
|
||||
{
|
||||
if (!fBehavior._IsWindowModifier(modifiers))
|
||||
fBehavior._NextState(NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
void _UpdateBorders(BPoint where)
|
||||
{
|
||||
// Compute the window center relative location of where. We divide by
|
||||
// the width respective the height, so we compensate for the window's
|
||||
// aspect ratio.
|
||||
BRect frame(fWindow->Frame());
|
||||
if (frame.Width() + 1 == 0 || frame.Height() + 1 == 0)
|
||||
return;
|
||||
|
||||
float x = (where.x - (frame.left + frame.right) / 2)
|
||||
/ (frame.Width() + 1);
|
||||
float y = (where.y - (frame.top + frame.bottom) / 2)
|
||||
/ (frame.Height() + 1);
|
||||
|
||||
// compute the angle
|
||||
if (x == 0 && y == 0)
|
||||
return;
|
||||
|
||||
float angle = atan2f(y, x);
|
||||
|
||||
// rotate by 22.5 degree to align our sectors with 45 degree multiples
|
||||
angle += M_PI / 8;
|
||||
|
||||
// add 180 degree to the negative values, so we get a nice 0 to 360
|
||||
// degree range
|
||||
if (angle < 0)
|
||||
angle += M_PI * 2;
|
||||
|
||||
int8 horizontal = NONE;
|
||||
int8 vertical = NONE;
|
||||
switch (int(angle / M_PI_4)) {
|
||||
case 0:
|
||||
horizontal = RIGHT;
|
||||
break;
|
||||
case 1:
|
||||
horizontal = RIGHT;
|
||||
vertical = BOTTOM;
|
||||
break;
|
||||
case 2:
|
||||
vertical = BOTTOM;
|
||||
break;
|
||||
case 3:
|
||||
horizontal = LEFT;
|
||||
vertical = BOTTOM;
|
||||
break;
|
||||
case 4:
|
||||
horizontal = LEFT;
|
||||
break;
|
||||
case 5:
|
||||
horizontal = LEFT;
|
||||
vertical = TOP;
|
||||
break;
|
||||
case 6:
|
||||
vertical = TOP;
|
||||
break;
|
||||
case 7:
|
||||
default:
|
||||
horizontal = RIGHT;
|
||||
vertical = TOP;
|
||||
break;
|
||||
}
|
||||
|
||||
// update the highlight, if necessary
|
||||
if (horizontal != fHorizontal || vertical != fVertical) {
|
||||
fBehavior._SetBorderHighlights(fHorizontal, fVertical, false);
|
||||
fHorizontal = horizontal;
|
||||
fVertical = vertical;
|
||||
fBehavior._SetBorderHighlights(fHorizontal, fVertical, true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BPoint fLastMousePosition;
|
||||
int8 fHorizontal;
|
||||
int8 fVertical;
|
||||
};
|
||||
|
||||
|
||||
@@ -629,14 +749,19 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
|
||||
int32 buttons = message->FindInt32("buttons");
|
||||
|
||||
// if a state is active, let it do the job
|
||||
if (fState != NULL)
|
||||
return fState->MouseDown(message, where);
|
||||
if (fState != NULL) {
|
||||
bool unhandled = false;
|
||||
bool result = fState->MouseDown(message, where, unhandled);
|
||||
if (!unhandled)
|
||||
return result;
|
||||
}
|
||||
|
||||
// No state active yet -- determine the click region and decide what to do.
|
||||
// No state active yet, or it wants us to handle the event -- determine the
|
||||
// click region and decide what to do.
|
||||
|
||||
Decorator* decorator = fWindow->Decorator();
|
||||
|
||||
Region hitRegion = REGION_NONE;
|
||||
Decorator::Region hitRegion = Decorator::REGION_NONE;
|
||||
Action action = ACTION_NONE;
|
||||
|
||||
bool inBorderRegion = false;
|
||||
@@ -653,7 +778,7 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
|
||||
if (windowModifier) {
|
||||
// click with window modifier keys -- let the whole window behave
|
||||
// like the border
|
||||
hitRegion = REGION_BORDER;
|
||||
hitRegion = Decorator::REGION_LEFT_BORDER;
|
||||
} else {
|
||||
// click on the decorator -- get the exact region
|
||||
hitRegion = _RegionFor(message);
|
||||
@@ -665,10 +790,7 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
|
||||
if ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0) {
|
||||
// left mouse button
|
||||
switch (hitRegion) {
|
||||
case REGION_NONE:
|
||||
break;
|
||||
|
||||
case REGION_TAB:
|
||||
case Decorator::REGION_TAB:
|
||||
// tab sliding in any case if either shift key is held down
|
||||
// except sliding up-down by moving mouse left-right would
|
||||
// look strange
|
||||
@@ -677,46 +799,65 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
|
||||
action = ACTION_SLIDE_TAB;
|
||||
break;
|
||||
}
|
||||
// otherwise fall through -- same handling as for the
|
||||
// border...
|
||||
|
||||
case REGION_BORDER:
|
||||
action = ACTION_DRAG;
|
||||
break;
|
||||
|
||||
case REGION_CLOSE_BUTTON:
|
||||
case Decorator::REGION_LEFT_BORDER:
|
||||
case Decorator::REGION_RIGHT_BORDER:
|
||||
case Decorator::REGION_TOP_BORDER:
|
||||
case Decorator::REGION_BOTTOM_BORDER:
|
||||
action = ACTION_DRAG;
|
||||
break;
|
||||
|
||||
case Decorator::REGION_CLOSE_BUTTON:
|
||||
action = (flags & B_NOT_CLOSABLE) == 0
|
||||
? ACTION_CLOSE : ACTION_DRAG;
|
||||
break;
|
||||
|
||||
case REGION_ZOOM_BUTTON:
|
||||
case Decorator::REGION_ZOOM_BUTTON:
|
||||
action = (flags & B_NOT_ZOOMABLE) == 0
|
||||
? ACTION_ZOOM : ACTION_DRAG;
|
||||
break;
|
||||
|
||||
case REGION_MINIMIZE_BUTTON:
|
||||
case Decorator::REGION_MINIMIZE_BUTTON:
|
||||
action = (flags & B_NOT_MINIMIZABLE) == 0
|
||||
? ACTION_MINIMIZE : ACTION_DRAG;
|
||||
break;
|
||||
|
||||
case REGION_RESIZE_CORNER:
|
||||
case Decorator::REGION_LEFT_TOP_CORNER:
|
||||
case Decorator::REGION_LEFT_BOTTOM_CORNER:
|
||||
case Decorator::REGION_RIGHT_TOP_CORNER:
|
||||
// TODO: Handle correctly!
|
||||
action = ACTION_DRAG;
|
||||
break;
|
||||
|
||||
case Decorator::REGION_RIGHT_BOTTOM_CORNER:
|
||||
action = (flags & B_NOT_RESIZABLE) == 0
|
||||
? ACTION_RESIZE : ACTION_DRAG;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) {
|
||||
// right mouse button
|
||||
switch (hitRegion) {
|
||||
case REGION_NONE:
|
||||
case Decorator::REGION_TAB:
|
||||
case Decorator::REGION_LEFT_BORDER:
|
||||
case Decorator::REGION_RIGHT_BORDER:
|
||||
case Decorator::REGION_TOP_BORDER:
|
||||
case Decorator::REGION_BOTTOM_BORDER:
|
||||
case Decorator::REGION_CLOSE_BUTTON:
|
||||
case Decorator::REGION_ZOOM_BUTTON:
|
||||
case Decorator::REGION_MINIMIZE_BUTTON:
|
||||
case Decorator::REGION_LEFT_TOP_CORNER:
|
||||
case Decorator::REGION_LEFT_BOTTOM_CORNER:
|
||||
case Decorator::REGION_RIGHT_TOP_CORNER:
|
||||
case Decorator::REGION_RIGHT_BOTTOM_CORNER:
|
||||
action = ACTION_RESIZE_BORDER;
|
||||
break;
|
||||
|
||||
case REGION_TAB:
|
||||
case REGION_BORDER:
|
||||
case REGION_CLOSE_BUTTON:
|
||||
case REGION_ZOOM_BUTTON:
|
||||
case REGION_MINIMIZE_BUTTON:
|
||||
case REGION_RESIZE_CORNER:
|
||||
action = ACTION_RESIZE_BORDER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -783,7 +924,8 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
|
||||
break;
|
||||
|
||||
case ACTION_RESIZE_BORDER:
|
||||
_NextState(new (std::nothrow) ResizeBorderState(*this, where));
|
||||
_NextState(new (std::nothrow) ResizeBorderState(*this, where,
|
||||
hitRegion));
|
||||
STRACE_CLICK(("===> ACTION_RESIZE_BORDER\n"));
|
||||
break;
|
||||
|
||||
@@ -791,10 +933,6 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where,
|
||||
break;
|
||||
}
|
||||
|
||||
// If we have a state now, it surely wants all further mouse events.
|
||||
if (fState != NULL)
|
||||
fDesktop->SetMouseEventWindow(fWindow);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -808,10 +946,15 @@ DefaultWindowBehaviour::MouseUp(BMessage* message, BPoint where)
|
||||
|
||||
|
||||
void
|
||||
DefaultWindowBehaviour::MouseMoved(BMessage *message, BPoint where, bool isFake)
|
||||
DefaultWindowBehaviour::MouseMoved(BMessage* message, BPoint where, bool isFake)
|
||||
{
|
||||
if (fState != NULL)
|
||||
if (fState != NULL) {
|
||||
fState->MouseMoved(message, where, isFake);
|
||||
} else {
|
||||
// If the window modifiers are hold, enter the window management state.
|
||||
if (_IsWindowModifier(message->FindInt32("modifiers")))
|
||||
_NextState(new(std::nothrow) ManageWindowState(*this, where));
|
||||
}
|
||||
|
||||
// change focus in FFM mode
|
||||
DesktopSettings desktopSettings(fDesktop);
|
||||
@@ -828,6 +971,17 @@ DefaultWindowBehaviour::MouseMoved(BMessage *message, BPoint where, bool isFake)
|
||||
void
|
||||
DefaultWindowBehaviour::ModifiersChanged(int32 modifiers)
|
||||
{
|
||||
BPoint where;
|
||||
int32 buttons;
|
||||
fDesktop->GetLastMouseState(&where, &buttons);
|
||||
|
||||
if (fState != NULL) {
|
||||
fState->ModifiersChanged(where, modifiers);
|
||||
} else {
|
||||
// If the window modifiers are hold, enter the window management state.
|
||||
if (_IsWindowModifier(modifiers))
|
||||
_NextState(new(std::nothrow) ManageWindowState(*this, where));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -840,51 +994,94 @@ DefaultWindowBehaviour::_IsWindowModifier(int32 modifiers) const
|
||||
}
|
||||
|
||||
|
||||
DefaultWindowBehaviour::Region
|
||||
Decorator::Region
|
||||
DefaultWindowBehaviour::_RegionFor(const BMessage* message) const
|
||||
{
|
||||
Decorator* decorator = fWindow->Decorator();
|
||||
if (decorator == NULL)
|
||||
return REGION_NONE;
|
||||
return Decorator::REGION_NONE;
|
||||
|
||||
BPoint where;
|
||||
if (message->FindPoint("where", &where) != B_OK)
|
||||
return REGION_NONE;
|
||||
return Decorator::REGION_NONE;
|
||||
|
||||
// translate the tab region into a functional region
|
||||
switch (decorator->RegionAt(where)) {
|
||||
case Decorator::REGION_NONE:
|
||||
return REGION_NONE;
|
||||
return decorator->RegionAt(where);
|
||||
}
|
||||
|
||||
case Decorator::REGION_TAB:
|
||||
return REGION_TAB;
|
||||
|
||||
case Decorator::REGION_CLOSE_BUTTON:
|
||||
return REGION_CLOSE_BUTTON;
|
||||
void
|
||||
DefaultWindowBehaviour::_SetBorderHighlights(int8 horizontal, int8 vertical,
|
||||
bool active)
|
||||
{
|
||||
if (Decorator* decorator = fWindow->Decorator()) {
|
||||
uint8 highlight = active
|
||||
? Decorator::HIGHLIGHT_RESIZE_BORDER
|
||||
: Decorator::HIGHLIGHT_NONE;
|
||||
|
||||
case Decorator::REGION_ZOOM_BUTTON:
|
||||
return REGION_ZOOM_BUTTON;
|
||||
// set the highlights for the borders
|
||||
BRegion dirtyRegion;
|
||||
switch (horizontal) {
|
||||
case LEFT:
|
||||
decorator->SetRegionHighlight(Decorator::REGION_LEFT_BORDER,
|
||||
highlight, &dirtyRegion);
|
||||
break;
|
||||
case RIGHT:
|
||||
decorator->SetRegionHighlight(
|
||||
Decorator::REGION_RIGHT_BORDER, highlight,
|
||||
&dirtyRegion);
|
||||
break;
|
||||
}
|
||||
|
||||
case Decorator::REGION_MINIMIZE_BUTTON:
|
||||
return REGION_MINIMIZE_BUTTON;
|
||||
switch (vertical) {
|
||||
case TOP:
|
||||
decorator->SetRegionHighlight(Decorator::REGION_TOP_BORDER,
|
||||
highlight, &dirtyRegion);
|
||||
break;
|
||||
case BOTTOM:
|
||||
decorator->SetRegionHighlight(
|
||||
Decorator::REGION_BOTTOM_BORDER, highlight,
|
||||
&dirtyRegion);
|
||||
break;
|
||||
}
|
||||
|
||||
case Decorator::REGION_LEFT_BORDER:
|
||||
case Decorator::REGION_RIGHT_BORDER:
|
||||
case Decorator::REGION_TOP_BORDER:
|
||||
case Decorator::REGION_BOTTOM_BORDER:
|
||||
return REGION_BORDER;
|
||||
// set the highlights for the corners
|
||||
if (horizontal != NONE && vertical != NONE) {
|
||||
if (horizontal == LEFT) {
|
||||
if (vertical == TOP) {
|
||||
decorator->SetRegionHighlight(
|
||||
Decorator::REGION_LEFT_TOP_CORNER, highlight,
|
||||
&dirtyRegion);
|
||||
} else {
|
||||
decorator->SetRegionHighlight(
|
||||
Decorator::REGION_LEFT_BOTTOM_CORNER, highlight,
|
||||
&dirtyRegion);
|
||||
}
|
||||
} else {
|
||||
if (vertical == TOP) {
|
||||
decorator->SetRegionHighlight(
|
||||
Decorator::REGION_RIGHT_TOP_CORNER, highlight,
|
||||
&dirtyRegion);
|
||||
} else {
|
||||
decorator->SetRegionHighlight(
|
||||
Decorator::REGION_RIGHT_BOTTOM_CORNER, highlight,
|
||||
&dirtyRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case Decorator::REGION_LEFT_TOP_CORNER:
|
||||
case Decorator::REGION_LEFT_BOTTOM_CORNER:
|
||||
case Decorator::REGION_RIGHT_TOP_CORNER:
|
||||
// not supported yet
|
||||
return REGION_BORDER;
|
||||
// invalidate the affected regions
|
||||
dirtyRegion.IntersectWith(&fWindow->VisibleRegion());
|
||||
BRect dirtyRect(dirtyRegion.Frame());
|
||||
|
||||
case Decorator::REGION_RIGHT_BOTTOM_CORNER:
|
||||
return REGION_RESIZE_CORNER;
|
||||
if (dirtyRect.IsValid()) {
|
||||
DrawingEngine* engine = decorator->GetDrawingEngine();
|
||||
engine->LockParallelAccess();
|
||||
engine->ConstrainClippingRegion(&dirtyRegion);
|
||||
|
||||
default:
|
||||
return REGION_NONE;
|
||||
decorator->Draw(dirtyRect);
|
||||
|
||||
engine->UnlockParallelAccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -892,11 +1089,22 @@ DefaultWindowBehaviour::_RegionFor(const BMessage* message) const
|
||||
void
|
||||
DefaultWindowBehaviour::_NextState(State* state)
|
||||
{
|
||||
// exit the old state
|
||||
if (fState != NULL)
|
||||
fState->ExitState(state);
|
||||
|
||||
// set and enter the new state
|
||||
State* oldState = fState;
|
||||
fState = state;
|
||||
|
||||
if (fState != NULL)
|
||||
if (fState != NULL) {
|
||||
fState->EnterState(oldState);
|
||||
fDesktop->SetMouseEventWindow(fWindow);
|
||||
} else if (oldState != NULL) {
|
||||
// no state anymore -- reset the mouse event window, if it's still us
|
||||
if (fDesktop->MouseEventWindow() == fWindow)
|
||||
fDesktop->SetMouseEventWindow(NULL);
|
||||
}
|
||||
|
||||
delete oldState;
|
||||
}
|
||||
|
||||
@@ -39,19 +39,6 @@ public:
|
||||
virtual void ModifiersChanged(int32 modifiers);
|
||||
|
||||
private:
|
||||
enum Region {
|
||||
REGION_NONE = 0,
|
||||
|
||||
REGION_TAB,
|
||||
REGION_BORDER,
|
||||
|
||||
REGION_CLOSE_BUTTON,
|
||||
REGION_ZOOM_BUTTON,
|
||||
REGION_MINIMIZE_BUTTON,
|
||||
|
||||
REGION_RESIZE_CORNER
|
||||
};
|
||||
|
||||
enum Action {
|
||||
ACTION_NONE,
|
||||
ACTION_ZOOM,
|
||||
@@ -64,6 +51,17 @@ private:
|
||||
ACTION_RESIZE_BORDER
|
||||
};
|
||||
|
||||
enum {
|
||||
// 1 for the "natural" resize border, -1 for the opposite, so
|
||||
// multiplying the movement delta by that value results in the
|
||||
// size change.
|
||||
LEFT = -1,
|
||||
TOP = -1,
|
||||
NONE = 0,
|
||||
RIGHT = 1,
|
||||
BOTTOM = 1
|
||||
};
|
||||
|
||||
struct State;
|
||||
struct MouseTrackingState;
|
||||
struct DragState;
|
||||
@@ -71,6 +69,7 @@ private:
|
||||
struct SlideTabState;
|
||||
struct ResizeBorderState;
|
||||
struct DecoratorButtonState;
|
||||
struct ManageWindowState;
|
||||
|
||||
// to keep gcc 2 happy
|
||||
friend struct State;
|
||||
@@ -80,10 +79,14 @@ private:
|
||||
friend struct SlideTabState;
|
||||
friend struct ResizeBorderState;
|
||||
friend struct DecoratorButtonState;
|
||||
friend struct ManageWindowState;
|
||||
|
||||
private:
|
||||
bool _IsWindowModifier(int32 modifiers) const;
|
||||
Region _RegionFor(const BMessage* message) const;
|
||||
Decorator::Region _RegionFor(const BMessage* message) const;
|
||||
|
||||
void _SetBorderHighlights(int8 horizontal,
|
||||
int8 vertical, bool active);
|
||||
|
||||
void _NextState(State* state);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user