hrev45197 adds 1 changeset to branch 'master' old head: e5de7e2102c59d0f6464378522d46dab0bb3f5b2 new head: 3071859cc6842d96fa086771c9463085ea0f2246 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=3071859+%5Ee5de7e2 ---------------------------------------------------------------------------- 3071859: Update ctrl+alt window management functionality. * Use double-headed resize arrows instead of single headed. * Remove border highlighting, it is replaced by mouse cursor. * Don't enter drag state if window is not movable. * Make Ctrl+LMB resize window border like RMB. * Define other 3 corners in default decorator and resize by them as well * Update mouse cursor to show arrows when over borders and control is held. * Set the move cursor on ctrl+alt if the window is movable. * Set cursor to not allowed on ctrl+alt if window is not movable. * Set the cursor to appropriate resize arrow on ctrl+alt+RMB. * Set the cursor to not allowed on ctrl+alt+RMB if not resizable. * Make window go to back when you right-click or ctrl+click on the tab. It doesn't lose focus though unlike BeOS R5. [ John Scipione <jscipione@xxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev45197 Commit: 3071859cc6842d96fa086771c9463085ea0f2246 URL: http://cgit.haiku-os.org/haiku/commit/?id=3071859 Author: John Scipione <jscipione@xxxxxxxxx> Date: Thu Jan 17 00:58:25 2013 UTC ---------------------------------------------------------------------------- 3 files changed, 383 insertions(+), 208 deletions(-) src/servers/app/decorator/DefaultDecorator.cpp | 28 +- .../app/decorator/DefaultWindowBehaviour.cpp | 551 ++++++++++++------- .../app/decorator/DefaultWindowBehaviour.h | 12 +- ---------------------------------------------------------------------------- diff --git a/src/servers/app/decorator/DefaultDecorator.cpp b/src/servers/app/decorator/DefaultDecorator.cpp index 4e1b245..c669b3e 100644 --- a/src/servers/app/decorator/DefaultDecorator.cpp +++ b/src/servers/app/decorator/DefaultDecorator.cpp @@ -218,7 +218,33 @@ DefaultDecorator::RegionAt(BPoint where, int32& tab) const if (region != REGION_NONE) return region; - // check the resize corner + // check the left top corner + BRect leftTopLeft(fLeftBorder.left, fLeftBorder.top, + fLeftBorder.right, fLeftBorder.top + kBorderResizeLength); + BRect leftTopTop(fTopBorder.left, fTopBorder.top, + fTopBorder.left + kBorderResizeLength, fTopBorder.bottom); + if (leftTopLeft.Contains(where) || leftTopTop.Contains(where)) + return REGION_LEFT_TOP_CORNER; + + // check the left bottom corner + BRect leftBottomLeft(fLeftBorder.left, + fLeftBorder.bottom - kBorderResizeLength, + fLeftBorder.right, fLeftBorder.bottom); + BRect leftBottomBottom(fBottomBorder.left, + fBottomBorder.top, fBottomBorder.left + kBorderResizeLength, + fBottomBorder.bottom); + if (leftBottomLeft.Contains(where) || leftBottomBottom.Contains(where)) + return REGION_LEFT_BOTTOM_CORNER; + + // check the right top corner + BRect rightTopRight(fRightBorder.left, fRightBorder.top, + fRightBorder.right, fRightBorder.top + kBorderResizeLength); + BRect rightTopTop(fTopBorder.right - kBorderResizeLength, fTopBorder.top, + fTopBorder.right, fTopBorder.bottom); + if (rightTopRight.Contains(where) || rightTopTop.Contains(where)) + return REGION_RIGHT_TOP_CORNER; + + // check the right bottom resize corner if (fTopTab->look == B_DOCUMENT_WINDOW_LOOK && fResizeRect.Contains(where)) return REGION_RIGHT_BOTTOM_CORNER; diff --git a/src/servers/app/decorator/DefaultWindowBehaviour.cpp b/src/servers/app/decorator/DefaultWindowBehaviour.cpp index d6650d0..585d305 100644 --- a/src/servers/app/decorator/DefaultWindowBehaviour.cpp +++ b/src/servers/app/decorator/DefaultWindowBehaviour.cpp @@ -86,6 +86,31 @@ protected: }; +// #pragma mark - ManageWindowState Definition + + +struct DefaultWindowBehaviour::ManageWindowState : State { + ManageWindowState(DefaultWindowBehaviour& behavior, + BPoint where); + ManageWindowState(DefaultWindowBehaviour& behavior, + BPoint where, int8 horizontal, int8 vertical); + virtual void EnterState(State* previousState); + virtual void ExitState(State* nextState); + virtual bool MouseDown(BMessage* message, BPoint where, + bool& _unhandled); + virtual void MouseMoved(BMessage* message, BPoint where, bool isFake); + virtual void ModifiersChanged(BPoint where, int32 modifiers); + +private: + void _UpdateResizeArrows(BPoint where); + +private: + BPoint fLastMousePosition; + int8 fHorizontal; + int8 fVertical; +}; + + // #pragma mark - MouseTrackingState @@ -215,6 +240,14 @@ struct DefaultWindowBehaviour::DragState : MouseTrackingState { { } + virtual void EnterState(State* previousState) + { + } + + virtual void ExitState(State* nextState) + { + } + virtual bool MouseDown(BMessage* message, BPoint where, bool& _unhandled) { // right-click while dragging shall bring the window to front @@ -230,6 +263,25 @@ struct DefaultWindowBehaviour::DragState : MouseTrackingState { return MouseTrackingState::MouseDown(message, where, _unhandled); } + virtual void MouseUp(BMessage* message, BPoint where) + { + if (fBehavior._IsWindowModifier(message->FindInt32("modifiers"))) { + // If the window modifiers are held return to the window + // management state. + fBehavior._NextState(new(std::nothrow) ManageWindowState( + fBehavior, where)); + } else + fBehavior._NextState(NULL); + } + + virtual void ModifiersChanged(BPoint where, int32 modifiers) + { + // Exit if user lifted window management modifiers + fBehavior.fLastModifiers = modifiers; + if (!fBehavior._IsWindowModifier(modifiers)) + fBehavior._NextState(NULL); + } + virtual void MouseMovedAction(BPoint& delta, bigtime_t now) { if (!(fWindow->Flags() & B_NOT_MOVABLE)) { @@ -356,7 +408,8 @@ struct DefaultWindowBehaviour::ResizeBorderState : MouseTrackingState { { switch (region) { case Decorator::REGION_TAB: - // TODO: Handle like the border it is attached to (top/left)? + fHorizontal = NONE; + fVertical = NONE; break; case Decorator::REGION_LEFT_BORDER: fHorizontal = LEFT; @@ -403,21 +456,30 @@ struct DefaultWindowBehaviour::ResizeBorderState : MouseTrackingState { virtual void EnterState(State* previousState) { - if ((fWindow->Flags() & B_NOT_RESIZABLE) != 0) - fHorizontal = fVertical = NONE; - else { - if ((fWindow->Flags() & B_NOT_H_RESIZABLE) != 0) - fHorizontal = NONE; - - if ((fWindow->Flags() & B_NOT_V_RESIZABLE) != 0) - fVertical = NONE; - } fBehavior._SetResizeCursor(fHorizontal, fVertical); } virtual void ExitState(State* nextState) { - fBehavior._ResetResizeCursor(); + } + + virtual void MouseUp(BMessage* message, BPoint where) + { + if (fBehavior._IsWindowModifier(message->FindInt32("modifiers"))) { + // If the window modifiers are still held return to window + // management state. + fBehavior._NextState(new(std::nothrow) ManageWindowState( + fBehavior, where, fHorizontal, fVertical)); + } else + fBehavior._NextState(NULL); + } + + virtual void ModifiersChanged(BPoint where, int32 modifiers) + { + // Exit if user lifted window management modifiers + fBehavior.fLastModifiers = modifiers; + if (!fBehavior._IsWindowModifier(modifiers)) + fBehavior._NextState(NULL); } virtual void MouseMovedAction(BPoint& delta, bigtime_t now) @@ -580,100 +642,138 @@ protected: // #pragma mark - ManageWindowState -struct DefaultWindowBehaviour::ManageWindowState : State { - ManageWindowState(DefaultWindowBehaviour& behavior, BPoint where) - : - State(behavior), - fLastMousePosition(where), - fHorizontal(NONE), - fVertical(NONE) - { - } +DefaultWindowBehaviour::ManageWindowState::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); - } +DefaultWindowBehaviour::ManageWindowState::ManageWindowState( + DefaultWindowBehaviour& behavior, BPoint where, int8 horizontal, + int8 vertical) + : + State(behavior), + fLastMousePosition(where), + fHorizontal(horizontal), + fVertical(vertical) +{ +} - 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; - } +void +DefaultWindowBehaviour::ManageWindowState::EnterState(State* previousState) +{ + // Update the mouse cursor + if ((fWindow->Flags() & B_NOT_MOVABLE) == 0) + fBehavior._SetMoveCursor(); + else + fBehavior._SetNowAllowedCursor(); - 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); + _UpdateResizeArrows(fLastMousePosition); +} + + +void +DefaultWindowBehaviour::ManageWindowState::ExitState(State* nextState) +{ +} + + +bool +DefaultWindowBehaviour::ManageWindowState::MouseDown(BMessage* message, + BPoint where, bool& _unhandled) +{ + int32 buttons = message->FindInt32("buttons"); + if ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0) { + if ((fWindow->Flags() & B_NOT_MOVABLE) == 0) { + fBehavior._SetMoveCursor(); + fBehavior._NextState(new (std::nothrow) DragState(fBehavior, + where, false, false)); + } + } else if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) { + if ((fWindow->Flags() & B_NOT_RESIZABLE) == 0) { + fBehavior._NextState(new (std::nothrow) ResizeBorderState( + fBehavior, where, fHorizontal, fVertical)); } else - fBehavior._NextState(NULL); + fBehavior._SetNowAllowedCursor(); } - virtual void ModifiersChanged(BPoint where, int32 modifiers) - { - if (!fBehavior._IsWindowModifier(modifiers)) - fBehavior._NextState(NULL); - } + return true; +} -private: - void _UpdateBorders(BPoint where) - { - if ((fWindow->Flags() & B_NOT_RESIZABLE) != 0) - return; - // 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; +void +DefaultWindowBehaviour::ManageWindowState::MouseMoved(BMessage* message, + BPoint where, bool isFake) +{ + // Update the mouse cursor + if ((fDesktop->WindowAt(where)->Flags() & B_NOT_RESIZABLE) != 0 + && (message->FindInt32("buttons") & B_SECONDARY_MOUSE_BUTTON) != 0) { + fBehavior._SetNowAllowedCursor(); + } else if ((fDesktop->WindowAt(where)->Flags() & B_NOT_MOVABLE) == 0) + fBehavior._SetMoveCursor(); + else + fBehavior._SetNowAllowedCursor(); + + // If the cursor is still over our window, update the borders. + // Otherwise leave the state. + if (fDesktop->WindowAt(where) == fWindow) { + fLastMousePosition = where; + _UpdateResizeArrows(fLastMousePosition); + } else + fBehavior._NextState(NULL); +} - 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 resize direction - int8 horizontal; - int8 vertical; - _ComputeResizeDirection(x, y, horizontal, vertical); - - if ((fWindow->Flags() & B_NOT_H_RESIZABLE) != 0) - horizontal = NONE; - if ((fWindow->Flags() & B_NOT_V_RESIZABLE) != 0) - vertical = NONE; - - // update the highlight, if necessary - if (horizontal != fHorizontal || vertical != fVertical) { - fBehavior._SetBorderHighlights(fHorizontal, fVertical, false); - fHorizontal = horizontal; - fVertical = vertical; - fBehavior._SetBorderHighlights(fHorizontal, fVertical, true); - } + +void +DefaultWindowBehaviour::ManageWindowState::ModifiersChanged(BPoint where, + int32 modifiers) +{ + fBehavior.fLastModifiers = modifiers; + if (!fBehavior._IsWindowModifier(modifiers)) { + if ((fWindow->Flags() & B_NOT_RESIZABLE) == 0 + && fBehavior._IsControlModifier(modifiers)) { + fBehavior._SetBorderResizeCursor(where); + } else + fBehavior._ResetCursor(); + + fBehavior._NextState(NULL); } +} -private: - BPoint fLastMousePosition; - int8 fHorizontal; - int8 fVertical; -}; + +void +DefaultWindowBehaviour::ManageWindowState::_UpdateResizeArrows(BPoint where) +{ + if ((fWindow->Flags() & B_NOT_RESIZABLE) != 0) + return; + + // 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 resize direction + _ComputeResizeDirection(x, y, fHorizontal, fVertical); + + // set resize direction to NONE if not resizable + if ((fWindow->Flags() & B_NOT_H_RESIZABLE) != 0) + fHorizontal = NONE; + if ((fWindow->Flags() & B_NOT_V_RESIZABLE) != 0) + fVertical = NONE; +} // #pragma mark - DefaultWindowBehaviour @@ -742,7 +842,34 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where, // translate the region into an action uint32 flags = fWindow->Flags(); - if ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0) { + if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0 + || _IsControlModifier(fLastModifiers) + && (buttons & B_PRIMARY_MOUSE_BUTTON) != 0) { + // right mouse button or control + left mouse button + switch (hitRegion) { + case Decorator::REGION_TAB: + case Decorator::REGION_CLOSE_BUTTON: + case Decorator::REGION_ZOOM_BUTTON: + case Decorator::REGION_MINIMIZE_BUTTON: + // Right clicking on the window tab sends it behind + fDesktop->SendWindowBehind(fWindow); + break; + case Decorator::REGION_LEFT_BORDER: + case Decorator::REGION_RIGHT_BORDER: + case Decorator::REGION_TOP_BORDER: + case Decorator::REGION_BOTTOM_BORDER: + 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 = (flags & B_NOT_RESIZABLE) == 0 + ? ACTION_RESIZE_BORDER : ACTION_DRAG; + break; + + default: + break; + } + } else if ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0) { // left mouse button switch (hitRegion) { case Decorator::REGION_TAB: { @@ -795,27 +922,6 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where, default: break; } - } else if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) { - // right mouse button - switch (hitRegion) { - 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; - - default: - break; - } } } @@ -894,22 +1000,20 @@ DefaultWindowBehaviour::MouseDown(BMessage* message, BPoint where, void -DefaultWindowBehaviour::MouseUp(BMessage* message, BPoint where) -{ - if (fState != NULL) - fState->MouseUp(message, where); -} - - -void -DefaultWindowBehaviour::MouseMoved(BMessage* message, BPoint where, bool isFake) +DefaultWindowBehaviour::MouseMoved(BMessage* message, BPoint where, + bool isFake) { 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"))) + if (_IsWindowModifier(message->FindInt32("modifiers"))) { + // Enter the window management state. _NextState(new(std::nothrow) ManageWindowState(*this, where)); + } else if ((fWindow->Flags() & B_NOT_RESIZABLE) == 0 + && _IsControlModifier(message->FindInt32("modifiers"))) { + _SetBorderResizeCursor(where); + } else + _ResetCursor(); } // change focus in FFM mode @@ -925,6 +1029,14 @@ DefaultWindowBehaviour::MouseMoved(BMessage* message, BPoint where, bool isFake) void +DefaultWindowBehaviour::MouseUp(BMessage* message, BPoint where) +{ + if (fState != NULL) + fState->MouseUp(message, where); +} + + +void DefaultWindowBehaviour::ModifiersChanged(int32 modifiers) { BPoint where; @@ -934,9 +1046,14 @@ DefaultWindowBehaviour::ModifiersChanged(int32 modifiers) if (fState != NULL) { fState->ModifiersChanged(where, modifiers); } else { - // If the window modifiers are hold, enter the window management state. - if (_IsWindowModifier(modifiers)) + if (_IsWindowModifier(modifiers)) { + // Enter the window management state. _NextState(new(std::nothrow) ManageWindowState(*this, where)); + } else if ((fWindow->Flags() & B_NOT_RESIZABLE) == 0 + && _IsControlModifier(modifiers)) { + _SetBorderResizeCursor(where); + } else + _ResetCursor(); } } @@ -954,7 +1071,16 @@ DefaultWindowBehaviour::_IsWindowModifier(int32 modifiers) const { return (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); + | B_SHIFT_KEY)) == (B_COMMAND_KEY | B_CONTROL_KEY); +} + + +bool +DefaultWindowBehaviour::_IsControlModifier(int32 modifiers) const +{ + return (fWindow->Flags() & B_NO_SERVER_SIDE_WINDOW_MODIFIERS) == 0 + && (modifiers & (B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY + | B_SHIFT_KEY)) == B_CONTROL_KEY; } @@ -973,72 +1099,6 @@ DefaultWindowBehaviour::_RegionFor(const BMessage* message, int32& tab) const } -void -DefaultWindowBehaviour::_SetBorderHighlights(int8 horizontal, int8 vertical, - bool active) -{ - if (Decorator* decorator = fWindow->Decorator()) { - uint8 highlight = active - ? Decorator::HIGHLIGHT_RESIZE_BORDER - : Decorator::HIGHLIGHT_NONE; - - // 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; - } - - switch (vertical) { - case TOP: - decorator->SetRegionHighlight(Decorator::REGION_TOP_BORDER, - highlight, &dirtyRegion); - break; - case BOTTOM: - decorator->SetRegionHighlight( - Decorator::REGION_BOTTOM_BORDER, highlight, - &dirtyRegion); - break; - } - - // 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); - } - } - } - - // invalidate the affected regions - fWindow->ProcessDirtyRegion(dirtyRegion); - } -} - - ServerCursor* DefaultWindowBehaviour::_ResizeCursorFor(int8 horizontal, int8 vertical) { @@ -1047,23 +1107,23 @@ DefaultWindowBehaviour::_ResizeCursorFor(int8 horizontal, int8 vertical) if (horizontal == LEFT) { if (vertical == TOP) - cursorID = B_CURSOR_ID_RESIZE_NORTH_WEST; + cursorID = B_CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST; else if (vertical == BOTTOM) - cursorID = B_CURSOR_ID_RESIZE_SOUTH_WEST; + cursorID = B_CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST; else - cursorID = B_CURSOR_ID_RESIZE_WEST; + cursorID = B_CURSOR_ID_RESIZE_EAST_WEST; } else if (horizontal == RIGHT) { if (vertical == TOP) - cursorID = B_CURSOR_ID_RESIZE_NORTH_EAST; + cursorID = B_CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST; else if (vertical == BOTTOM) - cursorID = B_CURSOR_ID_RESIZE_SOUTH_EAST; + cursorID = B_CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST; else - cursorID = B_CURSOR_ID_RESIZE_EAST; + cursorID = B_CURSOR_ID_RESIZE_EAST_WEST; } else { if (vertical == TOP) - cursorID = B_CURSOR_ID_RESIZE_NORTH; + cursorID = B_CURSOR_ID_RESIZE_NORTH_SOUTH; else if (vertical == BOTTOM) - cursorID = B_CURSOR_ID_RESIZE_SOUTH; + cursorID = B_CURSOR_ID_RESIZE_NORTH_SOUTH; } return fDesktop->GetCursorManager().GetCursor(cursorID); @@ -1071,6 +1131,22 @@ DefaultWindowBehaviour::_ResizeCursorFor(int8 horizontal, int8 vertical) void +DefaultWindowBehaviour::_SetMoveCursor() +{ + fDesktop->SetManagementCursor( + fDesktop->GetCursorManager().GetCursor(B_CURSOR_ID_MOVE)); +} + + +void +DefaultWindowBehaviour::_SetNowAllowedCursor() +{ + fDesktop->SetManagementCursor( + fDesktop->GetCursorManager().GetCursor(B_CURSOR_ID_NOT_ALLOWED)); +} + + +void DefaultWindowBehaviour::_SetResizeCursor(int8 horizontal, int8 vertical) { fDesktop->SetManagementCursor(_ResizeCursorFor(horizontal, vertical)); @@ -1078,7 +1154,76 @@ DefaultWindowBehaviour::_SetResizeCursor(int8 horizontal, int8 vertical) void -DefaultWindowBehaviour::_ResetResizeCursor() +DefaultWindowBehaviour::_SetBorderResizeCursor(BPoint where) +{ + Decorator* decorator = fWindow->Decorator(); + if (!decorator->GetFootprint().Contains(where)) { + // not over window + _ResetCursor(); + return; + } + + Decorator::Region hitRegion = Decorator::REGION_NONE; + int32 tab = -1; + + BMessage* message = new BMessage(); + message->AddPoint("where", where); + hitRegion = _RegionFor(message, tab); + delete message; + + int8 horizontal = NONE; + int8 vertical = NONE; + + switch (hitRegion) { + case Decorator::REGION_TAB: + break; + case Decorator::REGION_LEFT_BORDER: + horizontal = LEFT; + break; + case Decorator::REGION_RIGHT_BORDER: + horizontal = RIGHT; + break; + case Decorator::REGION_TOP_BORDER: + vertical = TOP; + break; + case Decorator::REGION_BOTTOM_BORDER: + vertical = BOTTOM; + break; + case Decorator::REGION_CLOSE_BUTTON: + case Decorator::REGION_ZOOM_BUTTON: + case Decorator::REGION_MINIMIZE_BUTTON: + break; + case Decorator::REGION_LEFT_TOP_CORNER: + horizontal = LEFT; + vertical = TOP; + break; + case Decorator::REGION_LEFT_BOTTOM_CORNER: + horizontal = LEFT; + vertical = BOTTOM; + break; + case Decorator::REGION_RIGHT_TOP_CORNER: + horizontal = RIGHT; + vertical = TOP; + break; + case Decorator::REGION_RIGHT_BOTTOM_CORNER: + horizontal = RIGHT; + vertical = BOTTOM; + break; + default: + break; + } + + if ((fWindow->Flags() & B_NOT_H_RESIZABLE) != 0) + horizontal = NONE; + if ((fWindow->Flags() & B_NOT_V_RESIZABLE) != 0) + vertical = NONE; + + _SetResizeCursor(horizontal, vertical); +} + + +void +DefaultWindowBehaviour::_ResetCursor() { fDesktop->SetManagementCursor(NULL); } diff --git a/src/servers/app/decorator/DefaultWindowBehaviour.h b/src/servers/app/decorator/DefaultWindowBehaviour.h index 3ad3f9f..7021a0b 100644 --- a/src/servers/app/decorator/DefaultWindowBehaviour.h +++ b/src/servers/app/decorator/DefaultWindowBehaviour.h @@ -87,18 +87,22 @@ private: friend struct ManageWindowState; private: + bool _IsControlModifier(int32 modifiers) const; bool _IsWindowModifier(int32 modifiers) const; Decorator::Region _RegionFor(const BMessage* message, int32& tab) const; - void _SetBorderHighlights(int8 horizontal, - int8 vertical, bool active); - ServerCursor* _ResizeCursorFor(int8 horizontal, int8 vertical); + + void _SetMoveCursor(); + void _SetNowAllowedCursor(); void _SetResizeCursor(int8 horizontal, int8 vertical); - void _ResetResizeCursor(); + void _SetBorderResizeCursor(BPoint where); + void _ResetCursor(); + + void _UpdateResizeArrows(BPoint where); static void _ComputeResizeDirection(float x, float y, int8& _horizontal, int8& _vertical);