From 21b40edd7531466fad9daa80dc440583492dec08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Mon, 3 Nov 2008 19:34:13 +0000 Subject: [PATCH] Implemented respecting B_LOCK_WINDOW_FOCUS that a view can set using SetMouseEventMask() from within it's mouse hooks. Among other things, scroll bars won't stop scrolling in FFM mode now if you accidentally leave the window with the mouse, something which is very likely. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28481 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/Desktop.cpp | 37 ++++++++++++++++++++++++++++---- src/servers/app/Desktop.h | 4 +++- src/servers/app/ServerWindow.cpp | 2 ++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 593bb52e8d..261dd9b5d2 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -262,7 +262,7 @@ MouseFilter::Filter(BMessage* message, EventTarget** _target, int32* _viewToken, *_target = NULL; } - fDesktop->SetLastMouseState(where, buttons); + fDesktop->SetLastMouseState(where, buttons, window); fDesktop->UnlockAllWindows(); @@ -311,6 +311,7 @@ Desktop::Desktop(uid_t userID) fMouseEventWindow(NULL), fWindowUnderMouse(NULL), + fLockedFocusWindow(NULL), fViewUnderMouse(B_NULL_TOKEN), fLastMousePosition(B_ORIGIN), fLastMouseButtons(0), @@ -750,10 +751,17 @@ Desktop::Cursor() const void -Desktop::SetLastMouseState(const BPoint& position, int32 buttons) +Desktop::SetLastMouseState(const BPoint& position, int32 buttons, + Window* windowUnderMouse) { + // The all-window-lock is write-locked. fLastMousePosition = position; fLastMouseButtons = buttons; + + if (fLastMouseButtons == 0 && fLockedFocusWindow) { + fLockedFocusWindow = NULL; + SetFocusWindow(windowUnderMouse); + } } @@ -1375,9 +1383,13 @@ Desktop::SetFocusWindow(Window* focus) if (!LockAllWindows()) return; - bool hasModal = _WindowHasModal(focus); + // test for B_LOCK_WINDOW_FOCUS + if (fLockedFocusWindow && focus != fLockedFocusWindow) { + UnlockAllWindows(); + return; + } - // TODO: test for B_LOCK_WINDOW_FOCUS + bool hasModal = _WindowHasModal(focus); if (focus == fFocus && focus != NULL && !focus->IsHidden() && (focus->Flags() & B_AVOID_FOCUS) == 0 && !hasModal) { @@ -1461,6 +1473,23 @@ Desktop::SetFocusWindow(Window* focus) } +void +Desktop::SetFocusLocked(const Window* window) +{ + AutoWriteLocker _(fWindowLock); + + if (window != NULL) { + // Don't allow this to be set when no mouse buttons + // are pressed. (BView::SetMouseEventMask() should only be called + // from mouse hooks.) + if (fLastMouseButtons == 0) + return; + } + + fLockedFocusWindow = window; +} + + void Desktop::_BringWindowsToFront(WindowList& windows, int32 list, bool wereVisible) diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index 710bdda189..21f9a550e8 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -82,7 +82,7 @@ class Desktop : public MessageLooper, public ScreenOwner { void SetCursor(ServerCursor* cursor); ServerCursorReference Cursor() const; void SetLastMouseState(const BPoint& position, - int32 buttons); + int32 buttons, Window* windowUnderMouse); // for use by the mouse filter only // both mouse position calls require // the Desktop object to be locked @@ -164,6 +164,7 @@ class Desktop : public MessageLooper, public ScreenOwner { void SetFocusWindow(Window* window = NULL); EventTarget* KeyboardEventTarget(); + void SetFocusLocked(const Window* window); Window* FindWindowByClientToken(int32 token, team_id teamID); @@ -303,6 +304,7 @@ class Desktop : public MessageLooper, public ScreenOwner { Window* fMouseEventWindow; const Window* fWindowUnderMouse; + const Window* fLockedFocusWindow; int32 fViewUnderMouse; BPoint fLastMousePosition; int32 fLastMouseButtons; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 615247d926..c5f4f192a5 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -1343,6 +1343,8 @@ fDesktop->LockSingleWindow(); fDesktop->UnlockSingleWindow(); // TODO: possible deadlock if (eventMask != 0 || options != 0) { + if (options & B_LOCK_WINDOW_FOCUS) + fDesktop->SetFocusLocked(fWindow); fDesktop->EventDispatcher().AddTemporaryListener(EventTarget(), fCurrentView->Token(), eventMask, options); } else {