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
*/
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);
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
if (fVisible.Contains(pt))
return this;

View File

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

View File

@ -1145,67 +1145,11 @@ RootLayer::MouseEventHandler(int32 code, BPrivate::PortLink& msg)
if (fLastLayerUnderMouse == this)
break;
#ifdef NEW_INPUT_HANDLING
WinBorder* winBorderUnderMouse = fLastLayerUnderMouse->Owner() ?
fLastLayerUnderMouse->fOwner :
(WinBorder*)fLastLayerUnderMouse;
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);
// get the pointer for one of the first RootLayer's descendants
Layer *primaryTarget = LayerAt(evt.where, false);
primaryTarget->MouseDown(evt);
#else
// we are clicking a WinBorder
@ -2241,7 +2185,7 @@ RootLayer::draw_window_tab(WinBorder *exFocus)
}
#ifndef NEW_CLIPPING
inline void
void
RootLayer::empty_visible_regions(Layer *layer)
{
// TODO: optimize by avoiding recursion?
@ -2257,7 +2201,7 @@ RootLayer::empty_visible_regions(Layer *layer)
}
#endif
inline void
void
RootLayer::winborder_activation(WinBorder* exActive)
{
// 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)
{
if (fHaveWinBorderList || get_workspace_windows()) {

View File

@ -218,7 +218,7 @@ fInUpdateRegion.OffsetBy(x, y);
// ...and here we get really hacky...
fTopLayer->fFrame.OffsetTo(0.0, 0.0);
} else {
move_layer(x, y);
Layer::move_layer(x, y);
}
if (Window()) {
@ -448,62 +448,145 @@ WinBorder::GetSizeLimits(float* minWidth, float* maxWidth,
#ifdef NEW_INPUT_HANDLING
void
WinBorder::MouseDown(const PointerEvent& event)
WinBorder::MouseDown(const PointerEvent& evt)
{
if (fDecorator) {
click_type action = _ActionFor(event);
// 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;
DesktopSettings desktopSettings(gDesktop);
Workspace::State oldState, newState;
case DEC_DRAG:
fIsDragging = true;
#ifdef NEW_INPUT_HANDLING
GetRootLayer()->SetNotifyLayer(this, B_POINTER_EVENTS, 0UL);
GetRootLayer()->ActiveWorkspace()->GetState(&oldState);
// not in FFM mode?
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
fLastMousePosition = event.where;
STRACE_CLICK(("===> DEC_DRAG\n"));
break;
}
case DEC_RESIZE:
fIsResizing = true;
fLastMousePosition = event.where;
STRACE_CLICK(("===> DEC_RESIZE\n"));
break;
#ifndef NEW_CLIPPING
GetRootLayer()->invalidate_layer(this, fFull);
#else
GetRootLayer()->do_Invalidate(Bounds());
#endif
case DEC_SLIDETAB:
fIsSlidingTab = true;
fLastMousePosition = event.where;
STRACE_CLICK(("===> DEC_SLIDETAB\n"));
break;
default:
break;
// TODO: FINISH ABOVE.
}
}
// TODO: set dirty regions!
#ifndef NEW_CLIPPING
GetRootLayer()->invalidate_layer(this, VisibleRegion());
#else
do_Invalidate(VisibleRegion());
#endif
// in FFM mode
else {
Layer *target = LayerAt(evt.where);
// clicking a simple Layer; forward event.
if (target != this)
target->MouseDown(evt);
// clicking inside our visible area.
else
goto winBorderAreaHandle;
}
}
void

View File

@ -214,9 +214,16 @@ Workspace::Front() const
WinBorder *
Workspace::Active() const
{
// ToDo: for now!
return Focus();
//return fActiveItem ? fActiveItem->layerPtr: NULL;
// in case of a normal or modal window
if (fFrontItem && fFrontItem == fFocusItem)
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
@ -249,6 +256,14 @@ Workspace::AttemptToMoveToBack(WinBorder *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.
\param list The list of visible WinBorders found in this workspace.

View File

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