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
|
int32
|
||||||
Desktop::ViewUnderMouse(const WindowLayer* window)
|
Desktop::ViewUnderMouse(const WindowLayer* window)
|
||||||
{
|
{
|
||||||
if (fWindowUnderMouse == window)
|
if (window != NULL && fWindowUnderMouse == window)
|
||||||
return fViewUnderMouse;
|
return fViewUnderMouse;
|
||||||
|
|
||||||
return B_NULL_TOKEN;
|
return B_NULL_TOKEN;
|
||||||
@ -2086,16 +2086,18 @@ Desktop::WindowAction(int32 windowToken, int32 action)
|
|||||||
LockAllWindows();
|
LockAllWindows();
|
||||||
|
|
||||||
::ServerWindow* serverWindow;
|
::ServerWindow* serverWindow;
|
||||||
|
WindowLayer* window;
|
||||||
if (BPrivate::gDefaultTokens.GetToken(windowToken,
|
if (BPrivate::gDefaultTokens.GetToken(windowToken,
|
||||||
B_SERVER_TOKEN, (void**)&serverWindow) != B_OK) {
|
B_SERVER_TOKEN, (void**)&serverWindow) != B_OK
|
||||||
|
|| (window = serverWindow->Window()) == NULL) {
|
||||||
UnlockAllWindows();
|
UnlockAllWindows();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == B_BRING_TO_FRONT
|
if (action == B_BRING_TO_FRONT
|
||||||
&& !serverWindow->Window()->IsMinimized()) {
|
&& !window->IsMinimized()) {
|
||||||
// the window is visible, we just need to make it the front window
|
// the window is visible, we just need to make it the front window
|
||||||
ActivateWindow(serverWindow->Window());
|
ActivateWindow(window);
|
||||||
} else
|
} else
|
||||||
serverWindow->NotifyMinimize(action == B_MINIMIZE_WINDOW);
|
serverWindow->NotifyMinimize(action == B_MINIMIZE_WINDOW);
|
||||||
|
|
||||||
|
@ -271,9 +271,9 @@ ServerApp::_HasWindowUnderMouse()
|
|||||||
BAutolock locker(fWindowListLock);
|
BAutolock locker(fWindowListLock);
|
||||||
|
|
||||||
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +439,10 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
|||||||
if (fWindowListLock.Lock()) {
|
if (fWindowListLock.Lock()) {
|
||||||
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
||||||
ServerWindow* serverWindow = fWindowList.ItemAt(i);
|
ServerWindow* serverWindow = fWindowList.ItemAt(i);
|
||||||
|
|
||||||
WindowLayer* window = serverWindow->Window();
|
WindowLayer* window = serverWindow->Window();
|
||||||
|
if (window == NULL || window->IsOffscreenWindow())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (window->Feel() == kWindowScreenFeel)
|
if (window->Feel() == kWindowScreenFeel)
|
||||||
fDesktop->SetWindowFeel(window, B_NORMAL_WINDOW_FEEL);
|
fDesktop->SetWindowFeel(window, B_NORMAL_WINDOW_FEEL);
|
||||||
@ -2479,12 +2482,15 @@ ServerApp::InWorkspace(int32 index) const
|
|||||||
// TODO: support initial application workspace!
|
// TODO: support initial application workspace!
|
||||||
|
|
||||||
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
||||||
ServerWindow* window = fWindowList.ItemAt(i);
|
ServerWindow* serverWindow = fWindowList.ItemAt(i);
|
||||||
const WindowLayer* layer = window->Window();
|
|
||||||
|
const WindowLayer* window = serverWindow->Window();
|
||||||
|
if (window == NULL || window->IsOffscreenWindow())
|
||||||
|
continue;
|
||||||
|
|
||||||
// only normal and unhidden windows count
|
// only normal and unhidden windows count
|
||||||
|
|
||||||
if (layer->IsNormal() && !layer->IsHidden() && layer->InWorkspace(index))
|
if (window->IsNormal() && !window->IsHidden() && window->InWorkspace(index))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2503,13 +2509,16 @@ ServerApp::Workspaces() const
|
|||||||
// value everytime a window has closed or changed workspaces
|
// value everytime a window has closed or changed workspaces
|
||||||
|
|
||||||
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
|
||||||
ServerWindow* window = fWindowList.ItemAt(i);
|
ServerWindow* serverWindow = fWindowList.ItemAt(i);
|
||||||
const WindowLayer* layer = window->Window();
|
|
||||||
|
const WindowLayer* window = serverWindow->Window();
|
||||||
|
if (window == NULL || window->IsOffscreenWindow())
|
||||||
|
continue;
|
||||||
|
|
||||||
// only normal and unhidden windows count
|
// only normal and unhidden windows count
|
||||||
|
|
||||||
if (layer->IsNormal() && !layer->IsHidden())
|
if (window->IsNormal() && !window->IsHidden())
|
||||||
workspaces |= layer->Workspaces();
|
workspaces |= window->Workspaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add initial application workspace!
|
// TODO: add initial application workspace!
|
||||||
|
@ -151,6 +151,7 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app,
|
|||||||
fDesktop(app->GetDesktop()),
|
fDesktop(app->GetDesktop()),
|
||||||
fServerApp(app),
|
fServerApp(app),
|
||||||
fWindowLayer(NULL),
|
fWindowLayer(NULL),
|
||||||
|
fWindowAddedToDesktop(false),
|
||||||
|
|
||||||
fClientTeam(app->ClientTeam()),
|
fClientTeam(app->ClientTeam()),
|
||||||
|
|
||||||
@ -187,14 +188,16 @@ ServerWindow::~ServerWindow()
|
|||||||
{
|
{
|
||||||
STRACE(("ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this));
|
STRACE(("ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this));
|
||||||
|
|
||||||
if (!fWindowLayer->IsOffscreenWindow())
|
if (!fWindowLayer->IsOffscreenWindow()) {
|
||||||
|
fWindowAddedToDesktop = false;
|
||||||
fDesktop->RemoveWindow(fWindowLayer);
|
fDesktop->RemoveWindow(fWindowLayer);
|
||||||
|
}
|
||||||
delete fWindowLayer;
|
|
||||||
|
|
||||||
if (App() != NULL)
|
if (App() != NULL)
|
||||||
App()->RemoveWindow(this);
|
App()->RemoveWindow(this);
|
||||||
|
|
||||||
|
delete fWindowLayer;
|
||||||
|
|
||||||
free(fTitle);
|
free(fTitle);
|
||||||
delete_port(fMessagePort);
|
delete_port(fMessagePort);
|
||||||
|
|
||||||
@ -243,8 +246,10 @@ ServerWindow::Init(BRect frame, window_look look, window_feel feel,
|
|||||||
if (!fWindowLayer)
|
if (!fWindowLayer)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
if (!fWindowLayer->IsOffscreenWindow())
|
if (!fWindowLayer->IsOffscreenWindow()) {
|
||||||
fDesktop->AddWindow(fWindowLayer);
|
fDesktop->AddWindow(fWindowLayer);
|
||||||
|
fWindowAddedToDesktop = true;
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
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*
|
WindowLayer*
|
||||||
ServerWindow::Window() const
|
ServerWindow::Window() const
|
||||||
{
|
{
|
||||||
// TODO: ensure desktop is locked!
|
// TODO: ensure desktop is locked!
|
||||||
|
if (!fWindowAddedToDesktop)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return fWindowLayer;
|
return fWindowLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,7 +847,7 @@ fDesktop->LockSingleWindow();
|
|||||||
STRACE(("ServerWindow %s: Message AS_WINDOW_RESIZE %.1f, %.1f\n",
|
STRACE(("ServerWindow %s: Message AS_WINDOW_RESIZE %.1f, %.1f\n",
|
||||||
Title(), xResizeBy, yResizeBy));
|
Title(), xResizeBy, yResizeBy));
|
||||||
|
|
||||||
if (Window()->IsResizing()) {
|
if (fWindowLayer->IsResizing()) {
|
||||||
// While the user resizes the window, we ignore
|
// While the user resizes the window, we ignore
|
||||||
// pragmatically set window bounds
|
// pragmatically set window bounds
|
||||||
fLink.StartMessage(B_BUSY);
|
fLink.StartMessage(B_BUSY);
|
||||||
@ -857,7 +871,7 @@ fDesktop->LockSingleWindow();
|
|||||||
STRACE(("ServerWindow %s: Message AS_WINDOW_MOVE: %.1f, %.1f\n",
|
STRACE(("ServerWindow %s: Message AS_WINDOW_MOVE: %.1f, %.1f\n",
|
||||||
Title(), xMoveBy, yMoveBy));
|
Title(), xMoveBy, yMoveBy));
|
||||||
|
|
||||||
if (Window()->IsDragging()) {
|
if (fWindowLayer->IsDragging()) {
|
||||||
// While the user moves the window, we ignore
|
// While the user moves the window, we ignore
|
||||||
// pragmatically set window positions
|
// pragmatically set window positions
|
||||||
fLink.StartMessage(B_BUSY);
|
fLink.StartMessage(B_BUSY);
|
||||||
|
@ -136,6 +136,7 @@ private:
|
|||||||
::Desktop* fDesktop;
|
::Desktop* fDesktop;
|
||||||
ServerApp* fServerApp;
|
ServerApp* fServerApp;
|
||||||
WindowLayer* fWindowLayer;
|
WindowLayer* fWindowLayer;
|
||||||
|
bool fWindowAddedToDesktop;
|
||||||
|
|
||||||
team_id fClientTeam;
|
team_id fClientTeam;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user