Added support for Layers capturing the mouse (Mouse events). Changed WinBorder to use mouse events.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@11946 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Adi Oanca
2005-03-21 20:29:24 +00:00
parent 642d7ca95e
commit 165177a105
9 changed files with 266 additions and 178 deletions
+4 -1
View File
@@ -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;
+5
View File
@@ -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;
+207 -59
View File
@@ -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<int32>(&evt.modifiers);
msg.Read<int32>(&evt.buttons);
msg.Read<int32>(&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<float>(&evt.where.y);
msg.Read<int32>(&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;
}
+27 -25
View File
@@ -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
+8 -1
View File
@@ -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<BRect>(&frame);
link.Read<uint32>(&resizeMask);
link.Read<uint32>(&eventMask);
link.Read<uint32>(&eventOptions);
link.Read<uint32>(&flags);
link.Read<bool>(&hidden);
link.Read<int32>(&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)
+1 -1
View File
@@ -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).
+2
View File
@@ -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
+8 -87
View File
@@ -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)
+4 -4
View File
@@ -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;