diff --git a/src/servers/app/RootLayer.cpp b/src/servers/app/RootLayer.cpp index 1cdfd306cf..992b6ee7c0 100644 --- a/src/servers/app/RootLayer.cpp +++ b/src/servers/app/RootLayer.cpp @@ -1118,21 +1118,6 @@ RootLayer::ShowWinBorder(WinBorder* winBorder) } -WinBorder * -RootLayer::WinBorderAt(const BPoint& pt) const -{ -#ifndef NEW_INPUT_HANDLING - for (int32 i = 0; i < fWinBorderCount; i++) - { -#ifndef NEW_CLIPPING - if (fWinBorderList[i]->fFullVisible.Contains(pt)) - return fWinBorderList[i]; -#endif - } -#endif - return NULL; -} - #ifdef NEW_INPUT_HANDLING void RootLayer::RevealNewWMState(Workspace::State &oldWMState) @@ -1233,6 +1218,13 @@ RootLayer::RevealNewWMState(Workspace::State &oldWMState) #endif } } + +bool +RootLayer::SetActive(WinBorder* newActive) +{ +// TODO: properly implement + return ActiveWorkspace()->AttemptToActivate(newActive); +} #endif //--------------------------------------------------------------------------- // Workspace related methods @@ -1258,7 +1250,7 @@ RootLayer::_ProcessMouseMovedEvent(PointerEvent &evt) // TODO: Focus should be a RootLayer option/feature, NOT a Workspace one!!! WinBorder* exFocus = Focus(); if (ds.MouseMode() != B_NORMAL_MOUSE && exFocus != winBorderTarget) { - ActiveWorkspace()->SetFocus(winBorderTarget); + ActiveWorkspace()->AttemptToSetFocus(winBorderTarget); // Workspace::SetFocus() *attempts* to set a new focus WinBorder, it may not succeed if (exFocus != Focus()) { // TODO: invalidate border area and send message to client for the widgets to light up @@ -2239,7 +2231,7 @@ RootLayer::show_winBorder(WinBorder *winBorder) invalid = fWorkspace[i]->ShowWinBorder(winBorder); // ToDo: this won't work with FFM - fWorkspace[i]->SetFocus(winBorder); + fWorkspace[i]->AttemptToSetFocus(winBorder); } if (fActiveWksIndex == i) { diff --git a/src/servers/app/RootLayer.h b/src/servers/app/RootLayer.h index 0578295d06..cf37c0352b 100644 --- a/src/servers/app/RootLayer.h +++ b/src/servers/app/RootLayer.h @@ -86,13 +86,13 @@ public: void SetWinBorderWorskpaces(WinBorder *winBorder, uint32 oldIndex, uint32 newIndex); - WinBorder* WinBorderAt(const BPoint& pt) const; #ifdef NEW_INPUT_HANDLING void RevealNewWMState(Workspace::State &oldWMState); // TODO: we need to replace Winborder* with Layer* inline WinBorder* Focus() const { return fWMState.Focus; } inline WinBorder* Front() const { return fWMState.Front; } inline WinBorder* Active() const { return fWMState.Active; } + bool SetActive(WinBorder* newActive); #else inline WinBorder* Focus() const { return ActiveWorkspace()->Focus(); } inline WinBorder* Front() const { return ActiveWorkspace()->Front(); } diff --git a/src/servers/app/WinBorder.cpp b/src/servers/app/WinBorder.cpp index 21b751cc5b..918c712023 100644 --- a/src/servers/app/WinBorder.cpp +++ b/src/servers/app/WinBorder.cpp @@ -530,11 +530,10 @@ WinBorder::MouseDown(const PointerEvent& evt) GetRootLayer()->ActiveWorkspace()->MoveToBack(this); } else { - if (action == DEC_DRAG || action == DEC_RESIZE || action == DEC_SLIDETAB) - GetRootLayer()->SetNotifyLayer(this, B_POINTER_EVENTS, 0UL); + GetRootLayer()->SetNotifyLayer(this, B_POINTER_EVENTS, 0UL); activateWindow: - GetRootLayer()->ActiveWorkspace()->AttemptToActivate(this); + GetRootLayer()->SetActive(this); } GetRootLayer()->RevealNewWMState(oldWMState); @@ -555,47 +554,53 @@ WinBorder::MouseDown(const PointerEvent& evt) void WinBorder::MouseUp(const PointerEvent& event) { + bool invalidate = false; if (fDecorator) { click_type action = _ActionFor(event); - +// TODO: present behavior is not fine! +// Decorator's Set*() methods _actualy draw_! on screen, not +// taking into account if that region is visible or not! +// Decorator redraw code should follow the same path as Layer's +// one! if (fIsZooming) { fIsZooming = false; fDecorator->SetZoom(false); - if (action == DEC_ZOOM) + if (action == DEC_ZOOM) { + invalidate = true; Window()->NotifyZoom(); - return; + } } if (fIsClosing) { fIsClosing = false; fDecorator->SetClose(false); - if (action == DEC_CLOSE) + if (action == DEC_CLOSE) { + invalidate = true; Window()->NotifyQuitRequested(); - return; + } } if (fIsMinimizing) { fIsMinimizing = false; fDecorator->SetMinimize(false); - if (action == DEC_MINIMIZE) + if (action == DEC_MINIMIZE) { + invalidate = true; Window()->NotifyMinimize(true); - return; + } } } fIsDragging = false; fIsResizing = false; fIsSlidingTab = false; - - // TODO: set dirty regions! -#ifndef NEW_CLIPPING - GetRootLayer()->invalidate_layer(GetRootLayer(), VisibleRegion()); -#else - do_Invalidate(VisibleRegion()); -#endif } void WinBorder::MouseMoved(const PointerEvent& event, uint32 transit) { if (fDecorator) { +// TODO: present behavior is not fine! +// Decorator's Set*() methods _actualy draw_! on screen, not +// taking into account if that region is visible or not! +// Decorator redraw code should follow the same path as Layer's +// one! if (fIsZooming) { fDecorator->SetZoom(_ActionFor(event) == DEC_ZOOM); } else if (fIsClosing) { @@ -604,6 +609,7 @@ WinBorder::MouseMoved(const PointerEvent& event, uint32 transit) fDecorator->SetMinimize(_ActionFor(event) == DEC_MINIMIZE); } } + if (fIsDragging) { BPoint delta = event.where - fLastMousePosition; #ifndef NEW_CLIPPING @@ -623,6 +629,7 @@ WinBorder::MouseMoved(const PointerEvent& event, uint32 transit) if (fIsSlidingTab) { // TODO: implement } + fLastMousePosition = event.where; } diff --git a/src/servers/app/Workspace.cpp b/src/servers/app/Workspace.cpp index 015b5632b8..628f415ba3 100644 --- a/src/servers/app/Workspace.cpp +++ b/src/servers/app/Workspace.cpp @@ -246,10 +246,12 @@ Workspace::AttemptToSetFront(WinBorder *newFront) return MoveToFront(newFront); } -bool +int32 Workspace::AttemptToSetFocus(WinBorder *newFocus) { - return SetFocus(newFocus); + ListData* newFocusItem = HasItem(newFocus); + + return _SetFocus(newFocusItem); } bool @@ -262,7 +264,7 @@ bool Workspace::AttemptToActivate(WinBorder *toActivate) { MoveToFront(toActivate); - SetFocus(toActivate); + AttemptToSetFocus(toActivate); return Active() == toActivate; } /* @@ -305,26 +307,71 @@ Workspace::GetWinBorderList(void **list, int32 *itemCount ) const return true; } +/*! + \brief Makes the specified WinBorder the focus one. + \param newFocus WinBorder which will try to take focus state. + \return 0 - setting focus failed, focus did not change. + 1 - the new focus WinBorder is \a winBorder + 2 - focus changed but not to \a winBorder because in front of it there + are other modal windows. -bool -Workspace::SetFocus(WinBorder* newFocus) + Set a new focus WinBorder if possible. +*/ + +int32 +Workspace::_SetFocus(ListData *newFocusItem) { - // in case this normal window is the front window, - // BUT it does not have focus. - ListData* newFocusItem = HasItem(newFocus); + if (!newFocusItem || newFocusItem == fFocusItem + || (newFocusItem && !newFocusItem->layerPtr->IsHidden() + && newFocusItem->layerPtr->WindowFlags() & B_AVOID_FOCUS)) + return 0L; - if (newFocusItem && fFocusItem != newFocusItem - && !(newFocus->WindowFlags() & B_AVOID_FOCUS)) { - // ToDo: for now, the focus item is always the active item... - // (it will be changed later on, and fixed with the refactoring) - fFocusItem = newFocusItem; - fActiveItem = newFocusItem; - return true; + WinBorder *newFocus = newFocusItem->layerPtr; + bool rv = 1; + + switch(newFocus->Level()) { + case B_MODAL_APP: + case B_NORMAL: { + ListData *item = newFocusItem->upperItem; + while ( item && + !item->layerPtr->IsHidden() && + ((item->layerPtr->Level() == B_MODAL_APP && + item->layerPtr->App()->ClientTeam() == newFocus->App()->ClientTeam()) || + item->layerPtr->Level() >= B_MODAL_ALL)) + { + if (item->layerPtr->WindowFlags() & B_AVOID_FOCUS) + newFocusItem = NULL; + else + newFocusItem = item; + rv = 2; + } + } + break; + + case B_SYSTEM_FIRST: + case B_MODAL_ALL: { + ListData *item = newFocusItem->upperItem; + while ( item && + !item->layerPtr->IsHidden() && + item->layerPtr->Level() >= newFocus->Level()) + { + if (item->layerPtr->WindowFlags() & B_AVOID_FOCUS) + newFocusItem = NULL; + else + newFocusItem = item; + rv = 2; + } + } + break; + + default: + break; } - return false; -} + fFocusItem = newFocusItem; + return rv; +} /*! \brief Makes the specified WinBorder the front one. @@ -584,8 +631,8 @@ Workspace::HideWinBorder(WinBorder *winBorder) case B_NORMAL: { - if (Focus() == winBorder) - saveFloatingWindows(fFocusItem); + if (fFrontItem && fFrontItem->layerPtr == winBorder) + saveFloatingWindows(fFrontItem); // remove B_MODAL_SUBSET windows present before this window. ListData* itemThis = HasItem(winBorder); @@ -677,7 +724,6 @@ Workspace::HideWinBorder(WinBorder *winBorder) } fFocusItem = nextFocus; - fActiveItem = nextFocus; } return returnValue; @@ -1282,9 +1328,6 @@ Workspace::RemoveItem(ListData *item) if (fFrontItem == item) fFrontItem = NULL; - - if (fActiveItem == item) - fActiveItem = NULL; } diff --git a/src/servers/app/Workspace.h b/src/servers/app/Workspace.h index 6f12838fe3..f4d84a569f 100644 --- a/src/servers/app/Workspace.h +++ b/src/servers/app/Workspace.h @@ -73,13 +73,12 @@ class Workspace { WinBorder* Active() const; void GetState(Workspace::State *state) const; bool AttemptToSetFront(WinBorder *newFront); - bool AttemptToSetFocus(WinBorder *newFocus); + int32 AttemptToSetFocus(WinBorder *newFocus); bool AttemptToMoveToBack(WinBorder *newBack); bool AttemptToActivate(WinBorder *toActivate); bool GetWinBorderList(void **list, int32 *itemCount ) const; - bool SetFocus(WinBorder* newFocus); bool MoveToBack(WinBorder *newLast); bool MoveToFront(WinBorder *newFront, bool doNotDisturb = false); @@ -113,6 +112,8 @@ private: bool placeToBack(ListData *newLast); void placeInFront(ListData *item, const bool userBusy); + int32 _SetFocus(ListData *newFocusItem); + bool removeAndPlaceBefore(const WinBorder *wb, ListData *beforeItem); bool removeAndPlaceBefore(ListData *item, ListData *beforeItem); @@ -154,7 +155,6 @@ private: // pointer for which "big" actions are intended ListData *fFrontItem; - ListData* fActiveItem; // settings for each workspace -- example taken from R5's app_server_settings file display_timing fDisplayTiming;