Fixed a big race condition in the server code:
* ServerApp was accessing ServerWindow::Window() (while having the app window lock held), but in fact, there was no guarantee it already existed, or was added to the Desktop. * Therefore, the Window() semantics have changed to only return a window in case the window exists *and* has been added to the desktop (the latter constraint might be lifted again, though). Therefore, it doesn't work for offscreen windows, and should not be used within ServerWindow code anymore. * This fixes bug #686 and maybe others as well. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17878 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4810cdcdbc
commit
3a44e6e37d
@ -2021,7 +2021,7 @@ Desktop::SetViewUnderMouse(const WindowLayer* window, int32 viewToken)
|
||||
int32
|
||||
Desktop::ViewUnderMouse(const WindowLayer* window)
|
||||
{
|
||||
if (fWindowUnderMouse == window)
|
||||
if (window != NULL && fWindowUnderMouse == window)
|
||||
return fViewUnderMouse;
|
||||
|
||||
return B_NULL_TOKEN;
|
||||
@ -2086,16 +2086,18 @@ Desktop::WindowAction(int32 windowToken, int32 action)
|
||||
LockAllWindows();
|
||||
|
||||
::ServerWindow* serverWindow;
|
||||
WindowLayer* window;
|
||||
if (BPrivate::gDefaultTokens.GetToken(windowToken,
|
||||
B_SERVER_TOKEN, (void**)&serverWindow) != B_OK) {
|
||||
B_SERVER_TOKEN, (void**)&serverWindow) != B_OK
|
||||
|| (window = serverWindow->Window()) == NULL) {
|
||||
UnlockAllWindows();
|
||||
return;
|
||||
}
|
||||
|
||||
if (action == B_BRING_TO_FRONT
|
||||
&& !serverWindow->Window()->IsMinimized()) {
|
||||
&& !window->IsMinimized()) {
|
||||
// the window is visible, we just need to make it the front window
|
||||
ActivateWindow(serverWindow->Window());
|
||||
ActivateWindow(window);
|
||||
} else
|
||||
serverWindow->NotifyMinimize(action == B_MINIMIZE_WINDOW);
|
||||
|
||||
|
@ -271,9 +271,9 @@ ServerApp::_HasWindowUnderMouse()
|
||||
BAutolock locker(fWindowListLock);
|
||||
|
||||
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
||||
ServerWindow* window = fWindowList.ItemAt(i);
|
||||
ServerWindow* serverWindow = fWindowList.ItemAt(i);
|
||||
|
||||
if (fDesktop->ViewUnderMouse(window->Window()) != B_NULL_TOKEN)
|
||||
if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN)
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -439,7 +439,10 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
if (fWindowListLock.Lock()) {
|
||||
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
||||
ServerWindow* serverWindow = fWindowList.ItemAt(i);
|
||||
|
||||
WindowLayer* window = serverWindow->Window();
|
||||
if (window == NULL || window->IsOffscreenWindow())
|
||||
continue;
|
||||
|
||||
if (window->Feel() == kWindowScreenFeel)
|
||||
fDesktop->SetWindowFeel(window, B_NORMAL_WINDOW_FEEL);
|
||||
@ -2479,12 +2482,15 @@ ServerApp::InWorkspace(int32 index) const
|
||||
// TODO: support initial application workspace!
|
||||
|
||||
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
||||
ServerWindow* window = fWindowList.ItemAt(i);
|
||||
const WindowLayer* layer = window->Window();
|
||||
ServerWindow* serverWindow = fWindowList.ItemAt(i);
|
||||
|
||||
const WindowLayer* window = serverWindow->Window();
|
||||
if (window == NULL || window->IsOffscreenWindow())
|
||||
continue;
|
||||
|
||||
// only normal and unhidden windows count
|
||||
|
||||
if (layer->IsNormal() && !layer->IsHidden() && layer->InWorkspace(index))
|
||||
if (window->IsNormal() && !window->IsHidden() && window->InWorkspace(index))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2503,13 +2509,16 @@ ServerApp::Workspaces() const
|
||||
// value everytime a window has closed or changed workspaces
|
||||
|
||||
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
||||
ServerWindow* window = fWindowList.ItemAt(i);
|
||||
const WindowLayer* layer = window->Window();
|
||||
ServerWindow* serverWindow = fWindowList.ItemAt(i);
|
||||
|
||||
const WindowLayer* window = serverWindow->Window();
|
||||
if (window == NULL || window->IsOffscreenWindow())
|
||||
continue;
|
||||
|
||||
// only normal and unhidden windows count
|
||||
|
||||
if (layer->IsNormal() && !layer->IsHidden())
|
||||
workspaces |= layer->Workspaces();
|
||||
if (window->IsNormal() && !window->IsHidden())
|
||||
workspaces |= window->Workspaces();
|
||||
}
|
||||
|
||||
// TODO: add initial application workspace!
|
||||
|
@ -151,6 +151,7 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app,
|
||||
fDesktop(app->GetDesktop()),
|
||||
fServerApp(app),
|
||||
fWindowLayer(NULL),
|
||||
fWindowAddedToDesktop(false),
|
||||
|
||||
fClientTeam(app->ClientTeam()),
|
||||
|
||||
@ -187,14 +188,16 @@ ServerWindow::~ServerWindow()
|
||||
{
|
||||
STRACE(("ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this));
|
||||
|
||||
if (!fWindowLayer->IsOffscreenWindow())
|
||||
if (!fWindowLayer->IsOffscreenWindow()) {
|
||||
fWindowAddedToDesktop = false;
|
||||
fDesktop->RemoveWindow(fWindowLayer);
|
||||
|
||||
delete fWindowLayer;
|
||||
}
|
||||
|
||||
if (App() != NULL)
|
||||
App()->RemoveWindow(this);
|
||||
|
||||
delete fWindowLayer;
|
||||
|
||||
free(fTitle);
|
||||
delete_port(fMessagePort);
|
||||
|
||||
@ -243,8 +246,10 @@ ServerWindow::Init(BRect frame, window_look look, window_feel feel,
|
||||
if (!fWindowLayer)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (!fWindowLayer->IsOffscreenWindow())
|
||||
if (!fWindowLayer->IsOffscreenWindow()) {
|
||||
fDesktop->AddWindow(fWindowLayer);
|
||||
fWindowAddedToDesktop = true;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -459,10 +464,19 @@ ServerWindow::GetInfo(window_info& info)
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns the ServerWindow's WindowLayer, if it exists and has been
|
||||
added to the Desktop already.
|
||||
In other words, you cannot assume this method will always give you
|
||||
a valid pointer.
|
||||
*/
|
||||
WindowLayer*
|
||||
ServerWindow::Window() const
|
||||
{
|
||||
// TODO: ensure desktop is locked!
|
||||
if (!fWindowAddedToDesktop)
|
||||
return NULL;
|
||||
|
||||
return fWindowLayer;
|
||||
}
|
||||
|
||||
@ -833,7 +847,7 @@ fDesktop->LockSingleWindow();
|
||||
STRACE(("ServerWindow %s: Message AS_WINDOW_RESIZE %.1f, %.1f\n",
|
||||
Title(), xResizeBy, yResizeBy));
|
||||
|
||||
if (Window()->IsResizing()) {
|
||||
if (fWindowLayer->IsResizing()) {
|
||||
// While the user resizes the window, we ignore
|
||||
// pragmatically set window bounds
|
||||
fLink.StartMessage(B_BUSY);
|
||||
@ -857,7 +871,7 @@ fDesktop->LockSingleWindow();
|
||||
STRACE(("ServerWindow %s: Message AS_WINDOW_MOVE: %.1f, %.1f\n",
|
||||
Title(), xMoveBy, yMoveBy));
|
||||
|
||||
if (Window()->IsDragging()) {
|
||||
if (fWindowLayer->IsDragging()) {
|
||||
// While the user moves the window, we ignore
|
||||
// pragmatically set window positions
|
||||
fLink.StartMessage(B_BUSY);
|
||||
|
@ -136,6 +136,7 @@ private:
|
||||
::Desktop* fDesktop;
|
||||
ServerApp* fServerApp;
|
||||
WindowLayer* fWindowLayer;
|
||||
bool fWindowAddedToDesktop;
|
||||
|
||||
team_id fClientTeam;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user