* added a way for the ServerWindow message loop to determine the required type
of locking before processing the message (single/all window lock) -> in most message cases, I could comment out the unlocking/locking which switched to the different lock, because the required lock is now already held, this removes some race conditions which were commented in the code already * EventDispatcher::SetDragMessage() didn't lock the object, this would have been bad if multiple windows tried to set a drag bitmap at once * the Desktop object keeps track of mouse position and pressed buttons, so that it doesn't need to lock the EventDispatcher for sending fake mouse moves to windows on show/hide of windows (solves some cases of possible dead locks with the new locking strategy) * the keyboard EventFilter switches the current workspace asynchrnously from the Desktop thread (another source of possible deadlocks) * the "reader is trying to become writer" check in MultiLocker is only used in DEBUG mode now As a summary: It would be nice if ServerWindow used a readlock for all messages it processes itself, and forwards all messages for which it needs a write lock to the Desktop thread. All cases where either the Desktop or the ServerWindow mess with the EventDispatcher are possible sources of deadlocks. This is solved right now by making sure that the lock is released before using the EventDispatcher. I have not observed any deadlocks while switching workspaces and launching many apps anymore, neither crashes. But I have not tested extensively except for in the test environment. That being said, I could reproduce the problems on first try before in Haiku. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22410 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2760c4cd73
commit
4d1c422802
@ -167,7 +167,7 @@ KeyboardFilter::Filter(BMessage* message, EventTarget** _target,
|
||||
{
|
||||
STRACE(("Set Workspace %ld\n", key - 1));
|
||||
|
||||
fDesktop->SetWorkspace(key - 2);
|
||||
fDesktop->SetWorkspaceAsync(key - 2);
|
||||
return B_SKIP_MESSAGE;
|
||||
}
|
||||
}
|
||||
@ -228,6 +228,10 @@ MouseFilter::Filter(BMessage* message, EventTarget** _target, int32* _viewToken,
|
||||
if (message->FindPoint("where", &where) != B_OK)
|
||||
return B_DISPATCH_MESSAGE;
|
||||
|
||||
int32 buttons;
|
||||
if (message->FindInt32("buttons", &buttons) != B_OK)
|
||||
buttons = 0;
|
||||
|
||||
if (!fDesktop->LockAllWindows())
|
||||
return B_DISPATCH_MESSAGE;
|
||||
|
||||
@ -271,6 +275,8 @@ MouseFilter::Filter(BMessage* message, EventTarget** _target, int32* _viewToken,
|
||||
*_target = NULL;
|
||||
}
|
||||
|
||||
fDesktop->SetLastMouseState(where, buttons);
|
||||
|
||||
fDesktop->UnlockAllWindows();
|
||||
|
||||
return B_DISPATCH_MESSAGE;
|
||||
@ -310,10 +316,17 @@ Desktop::Desktop(uid_t userID)
|
||||
fSubsetWindows(kSubsetList),
|
||||
fWorkspacesLayer(NULL),
|
||||
fActiveScreen(NULL),
|
||||
|
||||
fWindowLock("window lock"),
|
||||
|
||||
fFocusFollowsMouse(false),
|
||||
|
||||
fMouseEventWindow(NULL),
|
||||
fWindowUnderMouse(NULL),
|
||||
fViewUnderMouse(B_NULL_TOKEN),
|
||||
fLastMousePosition(B_ORIGIN),
|
||||
fLastMouseButtons(0),
|
||||
|
||||
fFocus(NULL),
|
||||
fFront(NULL),
|
||||
fBack(NULL)
|
||||
@ -605,6 +618,14 @@ Desktop::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
PostMessage(kMsgQuitLooper);
|
||||
break;
|
||||
|
||||
case AS_ACTIVATE_WORKSPACE: {
|
||||
int32 index;
|
||||
link.Read<int32>(&index);
|
||||
|
||||
SetWorkspace(index);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printf("Desktop %d:%s received unexpected code %ld\n", 0, "baron", code);
|
||||
|
||||
@ -660,11 +681,7 @@ Desktop::BroadcastToAllApps(int32 code)
|
||||
}
|
||||
|
||||
|
||||
ServerCursor*
|
||||
Desktop::Cursor() const
|
||||
{
|
||||
return HWInterface()->Cursor();
|
||||
}
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
@ -681,6 +698,32 @@ Desktop::SetCursor(ServerCursor* newCursor)
|
||||
}
|
||||
|
||||
|
||||
ServerCursor*
|
||||
Desktop::Cursor() const
|
||||
{
|
||||
return HWInterface()->Cursor();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Desktop::SetLastMouseState(const BPoint& position, int32 buttons)
|
||||
{
|
||||
fLastMousePosition = position;
|
||||
fLastMouseButtons = buttons;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Desktop::GetLastMouseState(BPoint* position, int32* buttons) const
|
||||
{
|
||||
*position = fLastMousePosition;
|
||||
*buttons = fLastMouseButtons;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
/*!
|
||||
\brief Redraws the background (ie. the desktop window, if any).
|
||||
*/
|
||||
@ -769,6 +812,20 @@ Desktop::SetWorkspacesCount(int32 newCount)
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Changes the current workspace to the one specified by \a index.
|
||||
You must not hold any window lock when calling this method.
|
||||
*/
|
||||
void
|
||||
Desktop::SetWorkspaceAsync(int32 index)
|
||||
{
|
||||
BPrivate::LinkSender link(MessagePort());
|
||||
link.StartMessage(AS_ACTIVATE_WORKSPACE);
|
||||
link.Attach<int32>(index);
|
||||
link.Flush();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Changes the current workspace to the one specified by \a index.
|
||||
You must not hold any window lock when calling this method.
|
||||
@ -1163,10 +1220,6 @@ Desktop::_WindowChanged(WindowLayer* window)
|
||||
void
|
||||
Desktop::_SendFakeMouseMoved(WindowLayer* window)
|
||||
{
|
||||
BPoint where;
|
||||
int32 buttons;
|
||||
EventDispatcher().GetMouse(where, buttons);
|
||||
|
||||
int32 viewToken = B_NULL_TOKEN;
|
||||
EventTarget* target = NULL;
|
||||
|
||||
@ -1175,11 +1228,11 @@ Desktop::_SendFakeMouseMoved(WindowLayer* window)
|
||||
if (window == NULL)
|
||||
window = MouseEventWindow();
|
||||
if (window == NULL)
|
||||
window = WindowAt(where);
|
||||
window = WindowAt(fLastMousePosition);
|
||||
|
||||
if (window != NULL) {
|
||||
BMessage message;
|
||||
window->MouseMoved(&message, where, &viewToken, true);
|
||||
window->MouseMoved(&message, fLastMousePosition, &viewToken, true);
|
||||
|
||||
if (viewToken != B_NULL_TOKEN)
|
||||
target = &window->EventTarget();
|
||||
|
@ -77,6 +77,15 @@ class Desktop : public MessageLooper, public ScreenOwner {
|
||||
|
||||
void SetCursor(ServerCursor* cursor);
|
||||
ServerCursor* Cursor() const;
|
||||
void SetLastMouseState(const BPoint& position,
|
||||
int32 buttons);
|
||||
// for use by the mouse filter only
|
||||
// both mouse position calls require
|
||||
// the Desktop object to be locked
|
||||
// already
|
||||
void GetLastMouseState(BPoint* position,
|
||||
int32* buttons) const;
|
||||
// for use by ServerWindow
|
||||
|
||||
void ScreenChanged(Screen* screen, bool makeDefault);
|
||||
|
||||
@ -92,6 +101,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
|
||||
|
||||
// Workspace methods
|
||||
|
||||
void SetWorkspaceAsync(int32 index);
|
||||
void SetWorkspace(int32 index);
|
||||
int32 CurrentWorkspace()
|
||||
{ return fCurrentWorkspace; }
|
||||
@ -263,6 +273,8 @@ class Desktop : public MessageLooper, public ScreenOwner {
|
||||
WindowLayer* fMouseEventWindow;
|
||||
const WindowLayer* fWindowUnderMouse;
|
||||
int32 fViewUnderMouse;
|
||||
BPoint fLastMousePosition;
|
||||
int32 fLastMouseButtons;
|
||||
|
||||
WindowLayer* fFocus;
|
||||
WindowLayer* fFront;
|
||||
|
@ -551,6 +551,8 @@ EventDispatcher::SetDragMessage(BMessage& message,
|
||||
{
|
||||
ETRACE(("EventDispatcher::SetDragMessage()\n"));
|
||||
|
||||
BAutolock _(this);
|
||||
|
||||
if (fDragBitmap != bitmap) {
|
||||
if (fDragBitmap)
|
||||
gBitmapManager->DeleteBitmap(fDragBitmap);
|
||||
|
@ -443,8 +443,10 @@ MultiLocker::WriteLock()
|
||||
locked = true;
|
||||
} else {
|
||||
// new writer acquiring the lock
|
||||
#if DEBUG
|
||||
if (IsReadLocked())
|
||||
debugger("Reader wants to become writer!");
|
||||
#endif
|
||||
|
||||
status_t status;
|
||||
do {
|
||||
|
@ -368,11 +368,16 @@ ServerWindow::_Show()
|
||||
if (fQuitting || !fWindowLayer->IsHidden() || fWindowLayer->IsOffscreenWindow())
|
||||
return;
|
||||
|
||||
// TODO: race condition? maybe we need to dispatch a message to the desktop to show/hide us
|
||||
// TODO: deadlock. Desktop::ShowWindow() will eventually lock the event thread,
|
||||
// which might be blocking on the all window lock with it's own lock already
|
||||
// head.
|
||||
// Maybe we need to dispatch a message to the desktop to show/hide us
|
||||
// instead of doing it from this thread.
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->UnlockAllWindows();
|
||||
fDesktop->ShowWindow(fWindowLayer);
|
||||
fDesktop->LockSingleWindow();
|
||||
fDesktop->LockAllWindows();
|
||||
//fDesktop->LockSingleWindow();
|
||||
|
||||
if (fDirectWindowData != NULL)
|
||||
HandleDirectConnection(B_DIRECT_START | B_BUFFER_RESET);
|
||||
@ -394,9 +399,7 @@ ServerWindow::_Hide()
|
||||
|
||||
// TODO: race condition? maybe we need to dispatch a message to the desktop to show/hide us
|
||||
// instead of doing it from this thread.
|
||||
fDesktop->UnlockSingleWindow();
|
||||
fDesktop->HideWindow(fWindowLayer);
|
||||
fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
|
||||
@ -436,9 +439,9 @@ ServerWindow::SetTitle(const char* newTitle)
|
||||
}
|
||||
|
||||
if (fWindowLayer != NULL) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->SetWindowTitle(fWindowLayer, newTitle);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -586,12 +589,18 @@ ServerWindow::_CreateLayerTree(BPrivate::LinkReceiver &link, ViewLayer **_parent
|
||||
newLayer->SetEventMask(eventMask, eventOptions);
|
||||
|
||||
if (eventMask != 0 || eventOptions != 0) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
// fDesktop->UnlockSingleWindow();
|
||||
// fDesktop->LockAllWindows();
|
||||
fDesktop->UnlockAllWindows();
|
||||
// TODO: possible deadlock
|
||||
fDesktop->EventDispatcher().AddListener(EventTarget(),
|
||||
newLayer->Token(), eventMask, eventOptions);
|
||||
fDesktop->LockSingleWindow();
|
||||
fDesktop->LockAllWindows();
|
||||
// fDesktop->UnlockAllWindows();
|
||||
// fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
// TODO: default fonts should be created and stored in the Application
|
||||
DesktopSettings settings(fDesktop);
|
||||
ServerFont font;
|
||||
settings.GetDefaultPlainFont(font);
|
||||
@ -661,12 +670,12 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
|
||||
link.Read<bool>(&activate);
|
||||
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
if (activate)
|
||||
fDesktop->ActivateWindow(fWindowLayer);
|
||||
else
|
||||
fDesktop->SendWindowBehind(fWindowLayer, NULL);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
break;
|
||||
}
|
||||
case AS_SEND_BEHIND:
|
||||
@ -681,10 +690,10 @@ fDesktop->LockSingleWindow();
|
||||
|
||||
WindowLayer *behindOf;
|
||||
if ((behindOf = fDesktop->FindWindowLayerByClientToken(token, teamID)) != NULL) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
// TODO: there is a big race condition when we unlock here (window could be gone by now)!
|
||||
fDesktop->SendWindowBehind(fWindowLayer, behindOf);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
status = B_OK;
|
||||
} else
|
||||
status = B_NAME_NOT_FOUND;
|
||||
@ -748,11 +757,11 @@ fDesktop->LockSingleWindow();
|
||||
|| windowLayer->Feel() != B_NORMAL_WINDOW_FEEL) {
|
||||
status = B_BAD_VALUE;
|
||||
} else {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
// TODO: there is a big race condition when we unlock here (window could be gone by now)!
|
||||
status = fDesktop->AddWindowToSubset(fWindowLayer, windowLayer)
|
||||
? B_OK : B_NO_MEMORY;
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,10 +779,10 @@ fDesktop->LockSingleWindow();
|
||||
WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken(
|
||||
token, App()->ClientTeam());
|
||||
if (windowLayer != NULL) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
// TODO: there is a big race condition when we unlock here (window could be gone by now)!
|
||||
fDesktop->RemoveWindowFromSubset(fWindowLayer, windowLayer);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
status = B_OK;
|
||||
} else
|
||||
status = B_BAD_VALUE;
|
||||
@ -797,9 +806,9 @@ fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->SetWindowLook(fWindowLayer, (window_look)look);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
fLink.StartMessage(status);
|
||||
@ -819,9 +828,9 @@ fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->SetWindowFeel(fWindowLayer, (window_feel)feel);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
fLink.StartMessage(status);
|
||||
@ -841,9 +850,9 @@ fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->SetWindowFlags(fWindowLayer, flags);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
fLink.StartMessage(status);
|
||||
@ -886,9 +895,9 @@ fDesktop->LockSingleWindow();
|
||||
STRACE(("ServerWindow %s: Message AS_SET_WORKSPACES %lx\n",
|
||||
Title(), newWorkspaces));
|
||||
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->SetWindowWorkspaces(fWindowLayer, newWorkspaces);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
break;
|
||||
}
|
||||
case AS_WINDOW_RESIZE:
|
||||
@ -907,9 +916,9 @@ fDesktop->LockSingleWindow();
|
||||
// pragmatically set window bounds
|
||||
fLink.StartMessage(B_BUSY);
|
||||
} else {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->ResizeWindowBy(fWindowLayer, xResizeBy, yResizeBy);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
fLink.StartMessage(B_OK);
|
||||
}
|
||||
fLink.Flush();
|
||||
@ -931,9 +940,9 @@ fDesktop->LockSingleWindow();
|
||||
// pragmatically set window positions
|
||||
fLink.StartMessage(B_BUSY);
|
||||
} else {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->MoveWindowBy(fWindowLayer, xMoveBy, yMoveBy);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
fLink.StartMessage(B_OK);
|
||||
}
|
||||
fLink.Flush();
|
||||
@ -960,7 +969,7 @@ fDesktop->LockSingleWindow();
|
||||
link.Read<int32>(&minHeight);
|
||||
link.Read<int32>(&maxHeight);
|
||||
*/
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
|
||||
if (fDesktop->LockAllWindows()) {
|
||||
fWindowLayer->SetSizeLimits(minWidth, maxWidth,
|
||||
@ -968,7 +977,7 @@ fDesktop->LockSingleWindow();
|
||||
fDesktop->UnlockAllWindows();
|
||||
}
|
||||
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
|
||||
// and now, sync the client to the limits that we were able to enforce
|
||||
fWindowLayer->GetSizeLimits(&minWidth, &maxWidth,
|
||||
@ -995,9 +1004,9 @@ fDesktop->LockSingleWindow();
|
||||
if (link.Read(buffer, size) == B_OK) {
|
||||
BMessage settings;
|
||||
if (settings.Unflatten(buffer) == B_OK) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->SetWindowDecoratorSettings(fWindowLayer, settings);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1058,15 +1067,15 @@ fDesktop->LockSingleWindow();
|
||||
{
|
||||
DTRACE(("ServerWindow %s: Message AS_GET_MOUSE\n", fTitle));
|
||||
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
// Returns
|
||||
// 1) BPoint mouse location
|
||||
// 2) int32 button state
|
||||
|
||||
BPoint where;
|
||||
int32 buttons;
|
||||
fDesktop->EventDispatcher().GetMouse(where, buttons);
|
||||
fDesktop->LockSingleWindow();
|
||||
fDesktop->GetLastMouseState(&where, &buttons);
|
||||
//fDesktop->LockSingleWindow();
|
||||
|
||||
fLink.StartMessage(B_OK);
|
||||
fLink.Attach<BPoint>(where);
|
||||
@ -1103,10 +1112,10 @@ fDesktop->LockSingleWindow();
|
||||
|
||||
status_t status = B_OK;
|
||||
if (!fWindowLayer->IsOffscreenWindow()) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
//fDesktop->UnlockSingleWindow();
|
||||
fDesktop->SetWindowFeel(fWindowLayer,
|
||||
enable ? kWindowScreenFeel : B_NORMAL_WINDOW_FEEL);
|
||||
fDesktop->LockSingleWindow();
|
||||
//fDesktop->LockSingleWindow();
|
||||
} else
|
||||
status = B_BAD_TYPE;
|
||||
|
||||
@ -1246,8 +1255,14 @@ ServerWindow::_DispatchViewMessage(int32 code,
|
||||
parent->RemoveChild(view);
|
||||
|
||||
if (view->EventMask() != 0) {
|
||||
fDesktop->EventDispatcher().RemoveListener(EventTarget(),
|
||||
token);
|
||||
// TODO: possible deadlock (event dispatcher already
|
||||
// locked itself, waits for Desktop write lock, but
|
||||
// we have it, now we are trying to lock the event
|
||||
// dispatcher -> deadlock)
|
||||
fDesktop->UnlockSingleWindow();
|
||||
fDesktop->EventDispatcher().RemoveListener(
|
||||
EventTarget(), token);
|
||||
fDesktop->LockSingleWindow();
|
||||
}
|
||||
if (fCurrentLayer == view)
|
||||
_SetCurrentLayer(parent);
|
||||
@ -1288,14 +1303,15 @@ ServerWindow::_DispatchViewMessage(int32 code,
|
||||
}
|
||||
case AS_LAYER_SET_EVENT_MASK:
|
||||
{
|
||||
STRACE(("ServerWindow %s: Message AS_LAYER_SET_MOUSE_EVENT_MASK: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
|
||||
STRACE(("ServerWindow %s: Message AS_LAYER_SET_EVENT_MASK: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
|
||||
uint32 eventMask, options;
|
||||
|
||||
link.Read<uint32>(&eventMask);
|
||||
if (link.Read<uint32>(&options) == B_OK) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
fCurrentLayer->SetEventMask(eventMask, options);
|
||||
|
||||
fDesktop->UnlockSingleWindow();
|
||||
// TODO: possible deadlock!
|
||||
if (eventMask != 0 || options != 0) {
|
||||
fDesktop->EventDispatcher().AddListener(EventTarget(),
|
||||
fCurrentLayer->Token(), eventMask, options);
|
||||
@ -1303,7 +1319,7 @@ ServerWindow::_DispatchViewMessage(int32 code,
|
||||
fDesktop->EventDispatcher().RemoveListener(EventTarget(),
|
||||
fCurrentLayer->Token());
|
||||
}
|
||||
fDesktop->LockSingleWindow();
|
||||
fDesktop->LockSingleWindow();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1314,7 +1330,8 @@ ServerWindow::_DispatchViewMessage(int32 code,
|
||||
|
||||
link.Read<uint32>(&eventMask);
|
||||
if (link.Read<uint32>(&options) == B_OK) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
fDesktop->UnlockSingleWindow();
|
||||
// TODO: possible deadlock
|
||||
if (eventMask != 0 || options != 0) {
|
||||
fDesktop->EventDispatcher().AddTemporaryListener(EventTarget(),
|
||||
fCurrentLayer->Token(), eventMask, options);
|
||||
@ -1322,7 +1339,7 @@ ServerWindow::_DispatchViewMessage(int32 code,
|
||||
fDesktop->EventDispatcher().RemoveTemporaryListener(EventTarget(),
|
||||
fCurrentLayer->Token());
|
||||
}
|
||||
fDesktop->LockSingleWindow();
|
||||
fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
// TODO: support B_LOCK_WINDOW_FOCUS option in Desktop
|
||||
@ -1896,8 +1913,11 @@ ServerWindow::_DispatchViewMessage(int32 code,
|
||||
if (link.Read(buffer, bufferSize) == B_OK
|
||||
&& dragMessage.Unflatten(buffer) == B_OK) {
|
||||
ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken);
|
||||
// TODO: possible deadlock
|
||||
fDesktop->UnlockSingleWindow();
|
||||
fDesktop->EventDispatcher().SetDragMessage(dragMessage,
|
||||
bitmap, offset);
|
||||
bitmap, offset);
|
||||
fDesktop->LockSingleWindow();
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
@ -1925,8 +1945,11 @@ ServerWindow::_DispatchViewMessage(int32 code,
|
||||
BMessage dragMessage;
|
||||
if (link.Read(buffer, bufferSize) == B_OK
|
||||
&& dragMessage.Unflatten(buffer) == B_OK) {
|
||||
// TODO: possible deadlock
|
||||
fDesktop->UnlockSingleWindow();
|
||||
fDesktop->EventDispatcher().SetDragMessage(dragMessage,
|
||||
NULL /* should be dragRect */, offset);
|
||||
fDesktop->LockSingleWindow();
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
@ -2857,6 +2880,7 @@ ServerWindow::_MessageLooper()
|
||||
|
||||
int32 messagesProcessed = 0;
|
||||
bool lockedDesktop = false;
|
||||
bool needsAllWindowsLocked = false;
|
||||
|
||||
while (true) {
|
||||
if (code == AS_DELETE_WINDOW || code == kMsgQuitLooper) {
|
||||
@ -2881,10 +2905,21 @@ ServerWindow::_MessageLooper()
|
||||
break;
|
||||
}
|
||||
|
||||
if (!lockedDesktop) {
|
||||
needsAllWindowsLocked = _MessageNeedsAllWindowsLocked(code);
|
||||
|
||||
if (!lockedDesktop && !needsAllWindowsLocked) {
|
||||
// only lock it once
|
||||
fDesktop->LockSingleWindow();
|
||||
lockedDesktop = true;
|
||||
} else if (lockedDesktop && !needsAllWindowsLocked) {
|
||||
// nothing to do
|
||||
} else if (needsAllWindowsLocked) {
|
||||
if (lockedDesktop) {
|
||||
// unlock single before locking all
|
||||
fDesktop->UnlockSingleWindow();
|
||||
lockedDesktop = false;
|
||||
}
|
||||
fDesktop->LockAllWindows();
|
||||
}
|
||||
|
||||
if (atomic_and(&fRedrawRequested, 0) != 0) {
|
||||
@ -2902,7 +2937,6 @@ ServerWindow::_MessageLooper()
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef PROFILE_MESSAGE_LOOP
|
||||
@ -2924,9 +2958,13 @@ ServerWindow::_MessageLooper()
|
||||
}
|
||||
#endif
|
||||
|
||||
if (needsAllWindowsLocked)
|
||||
fDesktop->UnlockAllWindows();
|
||||
|
||||
// only process up to 70 waiting messages at once (we have the Desktop locked)
|
||||
if (!receiver.HasMessages() || ++messagesProcessed > 70) {
|
||||
fDesktop->UnlockSingleWindow();
|
||||
if (lockedDesktop)
|
||||
fDesktop->UnlockSingleWindow();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2935,7 +2973,8 @@ ServerWindow::_MessageLooper()
|
||||
if (status < B_OK) {
|
||||
// that shouldn't happen, it's our port
|
||||
printf("Someone deleted our message port!\n");
|
||||
fDesktop->UnlockSingleWindow();
|
||||
if (lockedDesktop)
|
||||
fDesktop->UnlockSingleWindow();
|
||||
|
||||
// try to let our client die happily
|
||||
NotifyQuitRequested();
|
||||
@ -3152,6 +3191,39 @@ ServerWindow::_UpdateDrawState(ViewLayer* layer)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ServerWindow::_MessageNeedsAllWindowsLocked(uint32 code) const
|
||||
{
|
||||
switch (code) {
|
||||
case AS_SHOW_WINDOW:
|
||||
case AS_HIDE_WINDOW:
|
||||
case AS_MINIMIZE_WINDOW:
|
||||
case AS_ACTIVATE_WINDOW:
|
||||
case AS_SET_WINDOW_TITLE:
|
||||
case AS_ADD_TO_SUBSET:
|
||||
case AS_REMOVE_FROM_SUBSET:
|
||||
case AS_LAYER_CREATE_ROOT:
|
||||
case AS_LAYER_CREATE:
|
||||
case AS_SEND_BEHIND:
|
||||
case AS_SET_LOOK:
|
||||
case AS_SET_FEEL:
|
||||
case AS_SET_FLAGS:
|
||||
case AS_SET_WORKSPACES:
|
||||
case AS_WINDOW_MOVE:
|
||||
case AS_WINDOW_RESIZE:
|
||||
case AS_SET_SIZE_LIMITS:
|
||||
case AS_SET_DECORATOR_SETTINGS:
|
||||
case AS_GET_MOUSE:
|
||||
case AS_DIRECT_WINDOW_SET_FULLSCREEN:
|
||||
// case AS_LAYER_SET_EVENT_MASK:
|
||||
// case AS_LAYER_SET_MOUSE_EVENT_MASK:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerWindow::PictureToRegion(ServerPicture *picture, BRegion ®ion,
|
||||
bool inverse, BPoint where)
|
||||
|
@ -127,6 +127,8 @@ private:
|
||||
void _SetCurrentLayer(ViewLayer* view);
|
||||
void _UpdateDrawState(ViewLayer* view);
|
||||
|
||||
bool _MessageNeedsAllWindowsLocked(uint32 code) const;
|
||||
|
||||
// TODO: Move me elsewhere
|
||||
status_t PictureToRegion(ServerPicture *picture,
|
||||
BRegion &,
|
||||
@ -158,7 +160,7 @@ private:
|
||||
ViewLayer* fCurrentLayer;
|
||||
BRegion fCurrentDrawingRegion;
|
||||
bool fCurrentDrawingRegionValid;
|
||||
|
||||
|
||||
direct_window_data* fDirectWindowData;
|
||||
};
|
||||
|
||||
|
@ -1289,6 +1289,9 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
ViewLayer::MouseDown(BMessage* message, BPoint where)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user