more work on the input handling. I let Layer/WinBorder handle the MouseDown/Moved/Up instead of doing this in RootLayer::MouseEventHandler(). I did this because I felt it's more clean and in the near future RootLayer may have other children than WinBorders, for example simple Layers representing tooltips/bubbles/etc.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14198 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Adi Oanca 2005-09-18 22:43:31 +00:00
parent c5233d297e
commit 1b65556d66
6 changed files with 171 additions and 117 deletions

View File

@ -404,9 +404,20 @@ Layer::FindLayer(const int32 token)
\return The layer containing the point or NULL if no layer found \return The layer containing the point or NULL if no layer found
*/ */
Layer* Layer*
Layer::LayerAt(const BPoint &pt) Layer::LayerAt(const BPoint &pt, bool recursive)
{ {
//printf("%p:%s:LayerAt(x = %g, y = %g)\n", this, Name(), pt.x, pt.y); //printf("%p:%s:LayerAt(x = %g, y = %g)\n", this, Name(), pt.x, pt.y);
if (!recursive) {
if (VisibleRegion().Contains(pt))
return this;
for (Layer* child = LastChild(); child; child = PreviousChild())
if (child->FullVisible().Contains(pt))
return child;
return NULL;
}
#ifndef NEW_CLIPPING #ifndef NEW_CLIPPING
if (fVisible.Contains(pt)) if (fVisible.Contains(pt))
return this; return this;

View File

@ -108,7 +108,7 @@ class Layer {
uint32 CountChildren() const; uint32 CountChildren() const;
Layer* FindLayer(const int32 token); Layer* FindLayer(const int32 token);
Layer* LayerAt(const BPoint &pt); Layer* LayerAt(const BPoint &pt, bool recursive = true);
virtual Layer* FirstChild() const; virtual Layer* FirstChild() const;
virtual Layer* NextChild() const; virtual Layer* NextChild() const;

View File

@ -1145,67 +1145,11 @@ RootLayer::MouseEventHandler(int32 code, BPrivate::PortLink& msg)
if (fLastLayerUnderMouse == this) if (fLastLayerUnderMouse == this)
break; break;
#ifdef NEW_INPUT_HANDLING #ifdef NEW_INPUT_HANDLING
WinBorder* winBorderUnderMouse = fLastLayerUnderMouse->Owner() ? // get the pointer for one of the first RootLayer's descendants
fLastLayerUnderMouse->fOwner : Layer *primaryTarget = LayerAt(evt.where, false);
(WinBorder*)fLastLayerUnderMouse; primaryTarget->MouseDown(evt);
DesktopSettings ds(gDesktop);
Workspace::State oldState, newState;
click_type action = winBorderUnderMouse->ActionFor(evt);
ActiveWorkspace()->GetState(&oldState);
if (action == DEC_MOVETOBACK) {
ActiveWorkspace()->AttemptToMoveToBack(winBorderUnderMouse);
}
// in FFM, only bring in front if clicking on WinBorder's(decorator's) area
else if (dynamic_cast<WinBorder*>(fLastLayerUnderMouse) || ds.MouseMode() == B_NORMAL_MOUSE) {
ActiveWorkspace()->AttemptToSetFront(winBorderUnderMouse);
}
ActiveWorkspace()->AttemptToSetFocus(winBorderUnderMouse);
ActiveWorkspace()->GetState(&newState);
// send window activation messages
// NOTE !!! ATM we're sending B_WINDOW_ACTIVATED to front windows only!
// This means floating windows do not have their BWindow::WindowActivated()
// hook function called.
if (oldState.Front != newState.Front) {
if (oldState.Front && oldState.Front->Window()) {
BMessage msg(B_WINDOW_ACTIVATED);
msg.AddBool("active", false);
oldState.Front->Window()->SendMessageToClient(&msg, B_NULL_TOKEN, false);
}
if (newState.Front && newState.Front->Window()) {
BMessage msg(B_WINDOW_ACTIVATED);
msg.AddBool("active", true);
newState.Front->Window()->SendMessageToClient(&msg, B_NULL_TOKEN, false);
}
}
// calculate the region that must be invalidated/redrawn
// first, if the focus window changed, make sure the decorators reflect this state.
BRegion dirtyRegion;
if (oldState.Focus != newState.Focus) {
dirtyRegion.Include(&oldState.Focus->VisibleRegion());
dirtyRegion.Include(&newState.Focus->VisibleRegion());
}
#ifndef NEW_CLIPPING
invalidate_layer(this, dirtyRegion);
#else
do_Invalidate(dirtyRegion);
#endif
#ifndef NEW_CLIPPING
invalidate_layer(this, fFull);
#else
do_Invalidate(Bounds());
#endif
// TODO: DO NOT ALWAYS SEND THE FIRST MOUSE DOWN!!!
// TODO: if B_WILL_ACCEPT_FIRST_CLICK, DO NOT ACTIVATE THE CLICKED WINDOW!!!
fLastLayerUnderMouse->MouseDown(evt);
#else #else
// we are clicking a WinBorder // we are clicking a WinBorder
@ -2241,7 +2185,7 @@ RootLayer::draw_window_tab(WinBorder *exFocus)
} }
#ifndef NEW_CLIPPING #ifndef NEW_CLIPPING
inline void void
RootLayer::empty_visible_regions(Layer *layer) RootLayer::empty_visible_regions(Layer *layer)
{ {
// TODO: optimize by avoiding recursion? // TODO: optimize by avoiding recursion?
@ -2257,7 +2201,7 @@ RootLayer::empty_visible_regions(Layer *layer)
} }
#endif #endif
inline void void
RootLayer::winborder_activation(WinBorder* exActive) RootLayer::winborder_activation(WinBorder* exActive)
{ {
// ToDo: not sure if this is correct - do floating windows get WindowActivated() events? // ToDo: not sure if this is correct - do floating windows get WindowActivated() events?
@ -2274,7 +2218,7 @@ RootLayer::winborder_activation(WinBorder* exActive)
} }
inline void void
RootLayer::show_final_scene(WinBorder *exFocus, WinBorder *exActive) RootLayer::show_final_scene(WinBorder *exFocus, WinBorder *exActive)
{ {
if (fHaveWinBorderList || get_workspace_windows()) { if (fHaveWinBorderList || get_workspace_windows()) {

View File

@ -218,7 +218,7 @@ fInUpdateRegion.OffsetBy(x, y);
// ...and here we get really hacky... // ...and here we get really hacky...
fTopLayer->fFrame.OffsetTo(0.0, 0.0); fTopLayer->fFrame.OffsetTo(0.0, 0.0);
} else { } else {
move_layer(x, y); Layer::move_layer(x, y);
} }
if (Window()) { if (Window()) {
@ -448,62 +448,145 @@ WinBorder::GetSizeLimits(float* minWidth, float* maxWidth,
#ifdef NEW_INPUT_HANDLING #ifdef NEW_INPUT_HANDLING
void void
WinBorder::MouseDown(const PointerEvent& event) WinBorder::MouseDown(const PointerEvent& evt)
{ {
if (fDecorator) { DesktopSettings desktopSettings(gDesktop);
click_type action = _ActionFor(event); Workspace::State oldState, newState;
// find out where user clicked in Decorator
switch(action) {
case DEC_CLOSE:
fIsClosing = true;
fDecorator->SetClose(true);
STRACE_CLICK(("===> DEC_CLOSE\n"));
break;
case DEC_ZOOM:
fIsZooming = true;
fDecorator->SetZoom(true);
STRACE_CLICK(("===> DEC_ZOOM\n"));
break;
case DEC_MINIMIZE:
fIsMinimizing = true;
fDecorator->SetMinimize(true);
STRACE_CLICK(("===> DEC_MINIMIZE\n"));
break;
case DEC_DRAG: GetRootLayer()->ActiveWorkspace()->GetState(&oldState);
fIsDragging = true;
#ifdef NEW_INPUT_HANDLING // not in FFM mode?
GetRootLayer()->SetNotifyLayer(this, B_POINTER_EVENTS, 0UL); if (desktopSettings.MouseMode() == B_NORMAL_MOUSE) {
// default action is to drag the WinBorder
click_type action = DEC_DRAG;
Layer *target = LayerAt(evt.where);
// clicking a simple Layer.
if (target != this) {
if (GetRootLayer()->ActiveWorkspace()->Active() == this) {
target->MouseDown(evt);
}
else {
if (WindowFlags() & B_WILL_ACCEPT_FIRST_CLICK)
target->MouseDown(evt);
else
goto activateWindow;
}
// TODO: send mouse down to event registered BViews!!!
}
// clicking WinBorder visible area
else {
winBorderAreaHandle:
if (fDecorator)
action = _ActionFor(evt);
// set decorator internals
switch(action) {
case DEC_CLOSE:
fIsClosing = true;
fDecorator->SetClose(true);
STRACE_CLICK(("===> DEC_CLOSE\n"));
break;
case DEC_ZOOM:
fIsZooming = true;
fDecorator->SetZoom(true);
STRACE_CLICK(("===> DEC_ZOOM\n"));
break;
case DEC_MINIMIZE:
fIsMinimizing = true;
fDecorator->SetMinimize(true);
STRACE_CLICK(("===> DEC_MINIMIZE\n"));
break;
case DEC_DRAG:
fIsDragging = true;
fLastMousePosition = evt.where;
STRACE_CLICK(("===> DEC_DRAG\n"));
break;
case DEC_RESIZE:
fIsResizing = true;
fLastMousePosition = evt.where;
STRACE_CLICK(("===> DEC_RESIZE\n"));
break;
case DEC_SLIDETAB:
fIsSlidingTab = true;
fLastMousePosition = evt.where;
STRACE_CLICK(("===> DEC_SLIDETAB\n"));
break;
default:
break;
}
// based on what the Decorator returned, properly place this window.
if (action == DEC_MOVETOBACK) {
GetRootLayer()->ActiveWorkspace()->MoveToBack(this);
}
else if (action == DEC_DRAG) {
GetRootLayer()->SetNotifyLayer(this, B_POINTER_EVENTS, 0UL);
activateWindow:
GetRootLayer()->ActiveWorkspace()->AttemptToActivate(this);
}
GetRootLayer()->ActiveWorkspace()->GetState(&newState);
//--------------------------
// BOOKMARK!
// send window activation messages
// NOTE !!! ATM we're sending B_WINDOW_ACTIVATED to front windows only!
// This means floating windows do not have their BWindow::WindowActivated()
// hook function called.
if (oldState.Front != newState.Front) {
if (oldState.Front && oldState.Front->Window()) {
BMessage msg(B_WINDOW_ACTIVATED);
msg.AddBool("active", false);
oldState.Front->Window()->SendMessageToClient(&msg, B_NULL_TOKEN, false);
}
if (newState.Front && newState.Front->Window()) {
BMessage msg(B_WINDOW_ACTIVATED);
msg.AddBool("active", true);
newState.Front->Window()->SendMessageToClient(&msg, B_NULL_TOKEN, false);
}
}
// calculate the region that must be invalidated/redrawn
// first, if the focus window changed, make sure the decorators reflect this state.
BRegion dirtyRegion;
if (oldState.Focus != newState.Focus) {
dirtyRegion.Include(&oldState.Focus->VisibleRegion());
dirtyRegion.Include(&newState.Focus->VisibleRegion());
#ifndef NEW_CLIPPING
GetRootLayer()->fRedrawReg.Include(&dirtyRegion);
#else
// TODO: code for new clipping engine!
#endif #endif
fLastMousePosition = event.where; }
STRACE_CLICK(("===> DEC_DRAG\n"));
break;
case DEC_RESIZE: #ifndef NEW_CLIPPING
fIsResizing = true; GetRootLayer()->invalidate_layer(this, fFull);
fLastMousePosition = event.where; #else
STRACE_CLICK(("===> DEC_RESIZE\n")); GetRootLayer()->do_Invalidate(Bounds());
break; #endif
case DEC_SLIDETAB:
fIsSlidingTab = true;
fLastMousePosition = event.where;
STRACE_CLICK(("===> DEC_SLIDETAB\n"));
break;
default: // TODO: FINISH ABOVE.
break;
} }
} }
// in FFM mode
// TODO: set dirty regions! else {
#ifndef NEW_CLIPPING Layer *target = LayerAt(evt.where);
GetRootLayer()->invalidate_layer(this, VisibleRegion()); // clicking a simple Layer; forward event.
#else if (target != this)
do_Invalidate(VisibleRegion()); target->MouseDown(evt);
#endif // clicking inside our visible area.
else
goto winBorderAreaHandle;
}
} }
void void

View File

@ -214,9 +214,16 @@ Workspace::Front() const
WinBorder * WinBorder *
Workspace::Active() const Workspace::Active() const
{ {
// ToDo: for now! // in case of a normal or modal window
return Focus(); if (fFrontItem && fFrontItem == fFocusItem)
//return fActiveItem ? fActiveItem->layerPtr: NULL; return fFrontItem->layerPtr;
// a floating window is considered active if it has focus.
if (fFocusItem && (fFocusItem->layerPtr->Level() == B_FLOATING_APP ||
fFocusItem->layerPtr->Level() == B_FLOATING_ALL))
return fFocusItem->layerPtr;
return NULL;
} }
void void
@ -249,6 +256,14 @@ Workspace::AttemptToMoveToBack(WinBorder *newBack)
{ {
return MoveToBack(newBack); return MoveToBack(newBack);
} }
bool
Workspace::AttemptToActivate(WinBorder *toActivate)
{
MoveToFront(toActivate);
SetFocus(toActivate);
return Active() == toActivate;
}
/* /*
\brief This method provides you the list of visible windows in this workspace. \brief This method provides you the list of visible windows in this workspace.
\param list The list of visible WinBorders found in this workspace. \param list The list of visible WinBorders found in this workspace.

View File

@ -74,6 +74,7 @@ class Workspace {
bool AttemptToSetFront(WinBorder *newFront); bool AttemptToSetFront(WinBorder *newFront);
bool AttemptToSetFocus(WinBorder *newFocus); bool AttemptToSetFocus(WinBorder *newFocus);
bool AttemptToMoveToBack(WinBorder *newBack); bool AttemptToMoveToBack(WinBorder *newBack);
bool AttemptToActivate(WinBorder *toActivate);
bool GetWinBorderList(void **list, int32 *itemCount ) const; bool GetWinBorderList(void **list, int32 *itemCount ) const;