diff --git a/src/servers/app/server/Layer.cpp b/src/servers/app/server/Layer.cpp index 25a6e45b2e..158883db6a 100644 --- a/src/servers/app/server/Layer.cpp +++ b/src/servers/app/server/Layer.cpp @@ -84,6 +84,7 @@ Layer::Layer(BRect frame, const char *name, int32 token, uint32 resize, fDriver = driver; // Layer does not start out as a part of the tree + fOwner = NULL; fParent = NULL; fUpperSibling = NULL; fLowerSibling = NULL; @@ -98,8 +99,10 @@ Layer::Layer(BRect frame, const char *name, int32 token, uint32 resize, fClassID = AS_LAYER_CLASS; fFrameAction = B_LAYER_ACTION_NONE; fResizeMode = resize; - fHidden = false; + fHidden = false; + fEventMask = 0UL; + fEventOptions = 0UL; fInUpdate = false; fIsTopLayer = false; fLevel = -100; diff --git a/src/servers/app/server/Layer.h b/src/servers/app/server/Layer.h index dd0fa30c1f..9478e11191 100644 --- a/src/servers/app/server/Layer.h +++ b/src/servers/app/server/Layer.h @@ -131,6 +131,8 @@ public: virtual bool HasClient(void) { return true; } bool IsServerLayer() const; int32 Level() const { return fLevel; } + uint32 EventMask(void) const { return fEventMask; } + uint32 EventOptions(void) const { return fEventOptions; } void PruneTree(void); @@ -163,6 +165,7 @@ protected: BRect fFrame; BPoint fBoundsLeftTop; + WinBorder *fOwner; Layer *fParent; Layer *fUpperSibling; Layer *fLowerSibling; @@ -186,6 +189,8 @@ protected: int32 fLevel; uint32 fFlags; uint32 fResizeMode; + uint32 fEventMask; + uint32 fEventOptions; bool fHidden; bool fInUpdate; bool fIsTopLayer; diff --git a/src/servers/app/server/RootLayer.cpp b/src/servers/app/server/RootLayer.cpp index eff18862c9..ce8b7a0730 100644 --- a/src/servers/app/server/RootLayer.cpp +++ b/src/servers/app/server/RootLayer.cpp @@ -79,7 +79,9 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount, fMovingWindow = false; fResizingWindow = false; - fMouseTarget = NULL; + fLastMouseMoved = this; + fViewAction = B_ENTERED_VIEW; + fEventMaskLayer = NULL; fDragMessage = NULL; fScreenShotIndex = 1; @@ -905,53 +907,83 @@ void RootLayer::MouseEventHandler(int32 code, BPortLink& msg) msg.Read(&evt.modifiers); msg.Read(&evt.buttons); msg.Read(&evt.clicks); + + if (fLastMousePossition.x != evt.where.x || fLastMousePossition.y != evt.where.y) + debugger("RootLayer: MouseDown position not the same as last mouse position.\n"); - WinBorder *target = WinBorderAt(evt.where); - if (target) - { - click_type action; - bool invalidate; - bool sendMessage = true; - WinBorder *exFocus = FocusWinBorder(); + if (fLastMouseMoved == NULL) + debugger("RootLayer: fLastMouseMoved is null!\n"); - action = target->TellWhat(evt); + if (fLastMouseMoved == this) + break; - if (action == DEC_MOVETOBACK) - invalidate = ActiveWorkspace()->MoveToBack(target); - else - invalidate = ActiveWorkspace()->MoveToFront(target); + // we are clicking a WinBorder + + click_type action; + bool invalidate; + bool sendMessage = true; + WinBorder *exFocus = FocusWinBorder(); + WinBorder *target = fLastMouseMoved->fOwner? + fLastMouseMoved->fOwner: + (WinBorder*)fLastMouseMoved; + + action = target->TellWhat(evt); + + if (action == DEC_MOVETOBACK) + invalidate = ActiveWorkspace()->MoveToBack(target); + else + invalidate = ActiveWorkspace()->MoveToFront(target); - if (invalidate) - { - get_workspace_windows(); + if (invalidate) + { + get_workspace_windows(); - // TODO: should it be improved by calling with region of hidden windows - // plus the full regions of new windows??? - invalidate_layer(this, fFull); - } + // TODO: should it be improved by calling with region of hidden windows + // plus the full regions of new windows??? + invalidate_layer(this, fFull); + } - draw_window_tab(exFocus, FocusWinBorder()); + draw_window_tab(exFocus, FocusWinBorder()); - if (action == DEC_DRAG) + if (action == DEC_DRAG) + { + fMovingWindow = true; + } + else if (action == DEC_RESIZE) + { + fResizingWindow = true; + } + else if (action != DEC_NONE) + { + target->MouseDown(action); + } + else + { + // we are inside WinBorder + + if (target != FocusWinBorder()) + sendMessage = false; + else if (exFocus != FocusWinBorder() + && !(target->Window()->Flags() & B_WILL_ACCEPT_FIRST_CLICK)) + sendMessage = false; + + if (sendMessage && fLastMouseMoved != target->fTopLayer) { - fMovingWindow = true; - } - else if (action == DEC_RESIZE) - { - fResizingWindow = true; - } - else - { - if (target != FocusWinBorder()) - sendMessage = false; - else if (exFocus != FocusWinBorder() - && !(target->Window()->Flags() & B_WILL_ACCEPT_FIRST_CLICK)) - sendMessage = false; + BMessage msg; + msg.what = B_MOUSE_DOWN; + msg.AddInt64("when", evt.when); + msg.AddPoint("where", evt.where); + msg.AddInt32("modifiers", evt.modifiers); + msg.AddInt32("buttons", evt.buttons); + msg.AddInt32("clicks", evt.clicks); - target->MouseDown(evt, sendMessage); + Window()->SendMessageToClient(&msg, target->fViewToken, false); } + } - fMouseTarget = target; + if (fLastMouseMoved->EventMask() & B_POINTER_EVENTS) + { + fEventMaskLayer = target; } // We'll need this so that GetMouse can query for which buttons @@ -975,12 +1007,45 @@ void RootLayer::MouseEventHandler(int32 code, BPortLink& msg) msg.Read(&evt.where.y); msg.Read(&evt.modifiers); - // currently mouse up goes to the same window which received mouse down - if (fMouseTarget) + // TODO: what if 'fEventMaskLayer' is deleted in the mean time. + if (fEventMaskLayer) { - if (fMouseTarget == FocusWinBorder()) - fMouseTarget->MouseUp(evt); - fMouseTarget = NULL; + // if this is a regular Layer, sent message to counterpart BView. + if (fEventMaskLayer->fOwner) + { + BMessage upmsg(B_MOUSE_UP); + upmsg.AddInt64("when",evt.when); + upmsg.AddPoint("where",evt.where); + upmsg.AddInt32("modifiers",evt.modifiers); + + fEventMaskLayer->Window()->SendMessageToClient(&upmsg, fEventMaskLayer->fViewToken, false); + } + // this surely is a WinBorder + else + { + ((WinBorder*)fEventMaskLayer)->MouseUp(((WinBorder*)fEventMaskLayer)->TellWhat(evt)); + } + + fEventMaskLayer = NULL; + } + else + { + if (fLastMouseMoved->fOwner && fLastMouseMoved->fOwner == FocusWinBorder()) + { + // send B_MOUSE_UP for regular Layers/BViews + BMessage upmsg(B_MOUSE_UP); + upmsg.AddInt64("when",evt.when); + upmsg.AddPoint("where",evt.where); + upmsg.AddInt32("modifiers",evt.modifiers); + + fLastMouseMoved->Window()->SendMessageToClient(&upmsg, fLastMouseMoved->fViewToken, false); + } + else + { + // WinBorders don't need _UP_ messages unless they received _DOWN_ messages, + // and that case is threated above - WinBorders use Layer::fEventMask to + // capture the mouse. + } } fMovingWindow = false; @@ -1007,40 +1072,123 @@ void RootLayer::MouseEventHandler(int32 code, BPortLink& msg) GetDisplayDriver()->MoveCursorTo(evt.where.x, evt.where.y); - if (fMouseTarget) +// TODO: lock here! + Layer *target = LayerAt(evt.where); + if (target == NULL) + debugger("RooLayer::MouseEventHandler: 'target' can't be null.\n"); + WinBorder *winBorderUnder = NULL; + + // fEventMaskLayer is always != this + if (fEventMaskLayer) + { + if (fEventMaskLayer == target) + { + if (target == fLastMouseMoved) + { + fViewAction = B_INSIDE_VIEW; + } + else + { + fViewAction = B_ENTERED_VIEW; + } + } + else if (fEventMaskLayer == fLastMouseMoved) + { + fViewAction = B_EXITED_VIEW; + } + else + { + fViewAction = B_OUTSIDE_VIEW; + } + + if (fEventMaskLayer->fOwner) + { + // top layer does not have B_POINTER_EVENTS in its event mask + BMessage movemsg(B_MOUSE_MOVED); + movemsg.AddInt64("when",evt.when); + movemsg.AddPoint("where",evt.where); + movemsg.AddInt32("buttons",evt.buttons); + movemsg.AddInt32("transit", fViewAction); + + fEventMaskLayer->Window()->SendMessageToClient(&movemsg, fEventMaskLayer->fViewToken, false); + } + else + { + winBorderUnder = (WinBorder*)fEventMaskLayer; + } + } + else + { + if (fLastMouseMoved != target) + { + fViewAction = B_EXITED_VIEW; + if (fLastMouseMoved->fOwner) + { + if (fLastMouseMoved != fLastMouseMoved->fOwner->fTopLayer) + { + BMessage movemsg(B_MOUSE_MOVED); + movemsg.AddInt64("when",evt.when); + movemsg.AddPoint("where",evt.where); + movemsg.AddInt32("buttons",evt.buttons); + movemsg.AddInt32("transit",fViewAction); + fLastMouseMoved->Window()->SendMessageToClient(&movemsg, fLastMouseMoved->fViewToken, false); + } + } + else if (fLastMouseMoved != this) + ((WinBorder*)fLastMouseMoved)->MouseMoved(DEC_NONE); + + fViewAction = B_ENTERED_VIEW; + } + else + { + fViewAction = B_INSIDE_VIEW; + } + + if (target->fOwner) + { + if (target != target->fOwner->fTopLayer) + { + BMessage movemsg(B_MOUSE_MOVED); + movemsg.AddInt64("when",evt.when); + movemsg.AddPoint("where",evt.where); + movemsg.AddInt32("buttons",evt.buttons); + movemsg.AddInt32("transit",fViewAction); + target->Window()->SendMessageToClient(&movemsg, target->fViewToken, false); + } + } + else if (target != this) + { + winBorderUnder = (WinBorder*)target; + } + } + + if (winBorderUnder) { BPoint pt = evt.where; pt -= fLastMousePossition; if (fMovingWindow) { - if(fMouseTarget->fDecorator) - fMouseTarget->fDecorator->MoveBy(pt.x, pt.y); + if(winBorderUnder->fDecorator) + winBorderUnder->fDecorator->MoveBy(pt.x, pt.y); - fMouseTarget->move_layer(pt.x, pt.y); + winBorderUnder->move_layer(pt.x, pt.y); } else if (fResizingWindow) { - if(fMouseTarget->fDecorator) - fMouseTarget->fDecorator->ResizeBy(pt.x, pt.y); + if(winBorderUnder->fDecorator) + winBorderUnder->fDecorator->ResizeBy(pt.x, pt.y); - fMouseTarget->resize_layer(pt.x, pt.y); + winBorderUnder->resize_layer(pt.x, pt.y); } else { - fMouseTarget->MouseMoved(evt); - } - } - else - { - WinBorder *target = WinBorderAt(evt.where); - if (target) - { - target->MouseMoved(evt); + winBorderUnder->MouseMoved(winBorderUnder->TellWhat(evt)); } } - fLastMousePossition = evt.where; + fLastMouseMoved = target; + fLastMousePossition = evt.where; break; } diff --git a/src/servers/app/server/RootLayer.h b/src/servers/app/server/RootLayer.h index 0ca6f15964..34e4aea282 100644 --- a/src/servers/app/server/RootLayer.h +++ b/src/servers/app/server/RootLayer.h @@ -143,37 +143,39 @@ friend class Desktop; void MouseEventHandler(int32 code, BPortLink& link); void KeyboardEventHandler(int32 code, BPortLink& link); - Desktop *fDesktop; - BMessage *fDragMessage; - WinBorder *fMouseTarget; - CursorManager fCursorManager; - BLocker fAllRegionsLock; + Desktop *fDesktop; + BMessage *fDragMessage; + Layer *fLastMouseMoved; + int32 fViewAction; + Layer *fEventMaskLayer; + CursorManager fCursorManager; + BLocker fAllRegionsLock; - thread_id fThreadID; - port_id fListenPort; + thread_id fThreadID; + port_id fListenPort; - BList fScreenPtrList; - int32 fRows; - int32 fColumns; - int32 fScreenXResolution; - int32 fScreenYResolution; - uint32 fColorSpace; - int32 fButtons; - BPoint fLastMousePossition; - bool fMovingWindow; - bool fResizingWindow; + BList fScreenPtrList; + int32 fRows; + int32 fColumns; + int32 fScreenXResolution; + int32 fScreenYResolution; + uint32 fColorSpace; + int32 fButtons; + BPoint fLastMousePossition; + bool fMovingWindow; + bool fResizingWindow; - int32 fActiveWksIndex; - int32 fWsCount; - Workspace* fWorkspace[32]; - WinBorder** fWinBorderList2; - WinBorder** fWinBorderList; - int32 fWinBorderCount; + int32 fActiveWksIndex; + int32 fWsCount; + Workspace* fWorkspace[32]; + WinBorder** fWinBorderList2; + WinBorder** fWinBorderList; + int32 fWinBorderCount; mutable int32 fWinBorderIndex; int32 fWinBorderListLength; - int32 fScreenShotIndex; - bool fQuiting; + int32 fScreenShotIndex; + bool fQuiting; }; #endif diff --git a/src/servers/app/server/ServerWindow.cpp b/src/servers/app/server/ServerWindow.cpp index ae1118b1fb..fb5b9a8678 100644 --- a/src/servers/app/server/ServerWindow.cpp +++ b/src/servers/app/server/ServerWindow.cpp @@ -566,6 +566,8 @@ Layer * ServerWindow::CreateLayerTree(Layer *localRoot, LinkMsgReader &link) int32 token; BRect frame; uint32 resizeMask; + uint32 eventMask; + uint32 eventOptions; uint32 flags; bool hidden; int32 childCount; @@ -575,6 +577,8 @@ Layer * ServerWindow::CreateLayerTree(Layer *localRoot, LinkMsgReader &link) link.ReadString(&name); link.Read(&frame); link.Read(&resizeMask); + link.Read(&eventMask); + link.Read(&eventOptions); link.Read(&flags); link.Read(&hidden); link.Read(&childCount); @@ -588,7 +592,10 @@ Layer * ServerWindow::CreateLayerTree(Layer *localRoot, LinkMsgReader &link) free(name); // there is no way of setting this, other than manually :-) - newLayer->fHidden = hidden; + newLayer->fHidden = hidden; + newLayer->fEventMask = eventMask; + newLayer->fEventOptions = eventOptions; + newLayer->fOwner = fWinBorder; // add the new Layer to the tree structure. if(localRoot) diff --git a/src/servers/app/server/ServerWindow.h b/src/servers/app/server/ServerWindow.h index 422990d29f..497fcb36fa 100644 --- a/src/servers/app/server/ServerWindow.h +++ b/src/servers/app/server/ServerWindow.h @@ -109,7 +109,7 @@ public: // to who we belong. who do we own. our title. ServerApp *App(void) const { return fServerApp; } - WinBorder *GetWinBorder(void) const { return fWinBorder; } + const WinBorder *GetWinBorder(void) const { return fWinBorder; } const char *Title(void) const { return fTitle.String(); } // related thread/team_id(s). diff --git a/src/servers/app/server/ViewDriver.cpp b/src/servers/app/server/ViewDriver.cpp index 3996f0b7f0..f7687b5a58 100644 --- a/src/servers/app/server/ViewDriver.cpp +++ b/src/servers/app/server/ViewDriver.cpp @@ -178,6 +178,8 @@ void VDView::MouseDown(BPoint pt) void VDView::MouseMoved(BPoint pt, uint32 transit, const BMessage *msg) { + if (!(transit == B_ENTERED_VIEW || transit == B_INSIDE_VIEW)) + return; #ifdef ENABLE_INPUT_SERVER_EMULATION // Attach data: // 1) int64 - time of mouse click diff --git a/src/servers/app/server/WinBorder.cpp b/src/servers/app/server/WinBorder.cpp index 2db690af78..8d03dfa0d5 100644 --- a/src/servers/app/server/WinBorder.cpp +++ b/src/servers/app/server/WinBorder.cpp @@ -92,6 +92,7 @@ WinBorder::WinBorder(const BRect &r, const char *name, const int32 look, const i fTopLayer = NULL; fAdFlags = fAdFlags | B_LAYER_CHILDREN_DEPENDANT; fFlags = B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE; + fEventMask = B_POINTER_EVENTS; fIsClosing = false; fIsMinimizing = false; @@ -161,15 +162,9 @@ click_type WinBorder::TellWhat(PointerEvent& evt) const or frame. If it is not, the message is passed on to the appropriate view in the client BWindow. If the WinBorder is the target, then the proper action flag is set. */ -void WinBorder::MouseDown(PointerEvent& evt, bool sendMessage) +void WinBorder::MouseDown(click_type action) { - // user clicked on WinBorder's full visible region, - // find out if the user clicked the decorator. - - click_type action; - // find out where user clicked in Decorator - action = fDecorator->Clicked(evt.where, evt.buttons, evt.modifiers); switch(action) { case DEC_CLOSE: @@ -196,42 +191,12 @@ void WinBorder::MouseDown(PointerEvent& evt, bool sendMessage) STRACE_CLICK(("===> DEC_MINIMIZE\n")); break; } - case DEC_RESIZE: - case DEC_DRAG: - case DEC_MOVETOBACK: - { - // do nothing - RootLayer takes care of that - STRACE_CLICK(("===> DEC_RESIZE || DEC_DRAG || DEC_MOVETOBACK \n")); - break; - } - case DEC_NONE: - { - Window()->Lock(); - // TODO: you can improve performance by doing this search client-side! - Layer *target = LayerAt(evt.where); - if (sendMessage && target && target != fTopLayer) - { - BMessage msg; - msg.what = B_MOUSE_DOWN; - msg.AddInt64("when", evt.when); - msg.AddPoint("where", evt.where); - msg.AddInt32("modifiers", evt.modifiers); - msg.AddInt32("buttons", evt.buttons); - msg.AddInt32("clicks", evt.clicks); - - Window()->SendMessageToClient(&msg, target->fViewToken, false); - } - Window()->Unlock(); - break; - } default: { - debugger("WinBorder::MouseDown - Decorator returned UNKNOWN code\n"); + debugger("WinBorder::MouseDown - default case - not allowed!\n"); break; } } - - fLastMousePosition = evt.where; } /*! @@ -242,47 +207,25 @@ void WinBorder::MouseDown(PointerEvent& evt, bool sendMessage) or check to see if the user clicked on a tab button (close, zoom, etc.) and then moused away to prevent the operation from occurring */ -void WinBorder::MouseMoved(PointerEvent& evt) +void WinBorder::MouseMoved(click_type action) { - // Do a click test only if we have to, which would be now. :) - click_type location=fDecorator->Clicked(evt.where, evt.buttons,fKeyModifiers); - - if (fIsZooming && location!=DEC_ZOOM) + if (fIsZooming && action!=DEC_ZOOM) { fDecorator->SetZoom(false); fDecorator->DrawZoom(); } else - if (fIsClosing && location!=DEC_CLOSE) + if (fIsClosing && action!=DEC_CLOSE) { fDecorator->SetClose(false); fDecorator->DrawClose(); } else - if(fIsMinimizing && location!=DEC_MINIMIZE) + if(fIsMinimizing && action!=DEC_MINIMIZE) { fDecorator->SetMinimize(false); fDecorator->DrawMinimize(); } - - if (fTopLayer->fFullVisible.Contains(evt.where)) - { - Window()->Lock(); - // TODO: you can improve performance by doing this search client-side! - Layer *target = LayerAt(evt.where); - if (target) - { - BMessage movemsg(B_MOUSE_MOVED); - movemsg.AddInt64("when",evt.when); - movemsg.AddPoint("where",evt.where); - movemsg.AddInt32("buttons",evt.buttons); - - Window()->SendMessageToClient(&movemsg); - } - Window()->Unlock(); - } - - fLastMousePosition = evt.where; } /*! @@ -293,13 +236,8 @@ void WinBorder::MouseMoved(PointerEvent& evt) button click flag, takes the appropriate action (i.e. clearing the close button flag also takes steps to close the window). */ -void WinBorder::MouseUp(PointerEvent& evt) +void WinBorder::MouseUp(click_type action) { - click_type action; - - // find out where user clicked in Decorator - action = fDecorator->Clicked(evt.where, evt.buttons, evt.modifiers); - if (fIsZooming) { fIsZooming = false; @@ -328,23 +266,6 @@ void WinBorder::MouseUp(PointerEvent& evt) Window()->Minimize(true); return; } - - if (action == DEC_NONE) - { - Window()->Lock(); - // TODO: you can improve performance by doing this search client-side! - Layer *target = LayerAt(evt.where); - if (target && target != fTopLayer) - { - BMessage upmsg(B_MOUSE_UP); - upmsg.AddInt64("when",evt.when); - upmsg.AddPoint("where",evt.where); - upmsg.AddInt32("modifiers",evt.modifiers); - - Window()->SendMessageToClient(&upmsg, target->fViewToken, false); - } - Window()->Unlock(); - } } void WinBorder::MouseWheel(PointerEvent& evt, BPoint& ptWhere) diff --git a/src/servers/app/server/WinBorder.h b/src/servers/app/server/WinBorder.h index 403791b1d3..699239d10c 100644 --- a/src/servers/app/server/WinBorder.h +++ b/src/servers/app/server/WinBorder.h @@ -82,9 +82,9 @@ public: void SetSizeLimits(float minwidth, float maxwidth, float minheight, float maxheight); click_type TellWhat(PointerEvent& evt) const; - void MouseDown(PointerEvent& evt, bool sendMessage); - void MouseMoved(PointerEvent& evt); - void MouseUp(PointerEvent& evt); + void MouseDown(click_type action); + void MouseMoved(click_type action); + void MouseUp(click_type action); void MouseWheel(PointerEvent& evt, BPoint& ptWhere); void UpdateColors(void); @@ -94,7 +94,7 @@ public: virtual bool HasClient(void) { return false; } Decorator *GetDecorator(void) const { return fDecorator; } - + void HighlightDecorator(const bool &active); bool HasPoint(const BPoint &pt) const;