* Removed _GetWindowList()

* _WindowAt() and _CountWindows() now have an individual version of that
  code which should be magnitudes faster.
* _WindowQuitLoop() no longer handles hidden windows specially - instead,
  it now walks the window list in the correct direction which should fix
  the issues.
* Also, it now uses WindowAt() and thus has an up-to-date view of the
  window list (it will no longer ignore new windows).
* And finally, it will no longer dereference an unsafe pointer (for
  BWindow::IsFilePanel()).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21505 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-06-25 23:38:45 +00:00
parent 880e4292a1
commit b418398455
2 changed files with 126 additions and 146 deletions
-1
View File
@@ -141,7 +141,6 @@ private:
uint32 InitialWorkspace(); uint32 InitialWorkspace();
int32 _CountWindows(bool includeMenus) const; int32 _CountWindows(bool includeMenus) const;
BWindow* _WindowAt(uint32 index, bool includeMenus) const; BWindow* _WindowAt(uint32 index, bool includeMenus) const;
status_t _GetWindowList(BList* list, bool includeMenus) const;
static BResources* sAppResources; static BResources* sAppResources;
static BLocker sAppResourcesLock; static BLocker sAppResourcesLock;
+68 -87
View File
@@ -1066,57 +1066,62 @@ BApplication::ScriptReceived(BMessage *message, int32 index,
} else if (strcmp("Window", property) == 0) { } else if (strcmp("Window", property) == 0) {
switch (what) { switch (what) {
case B_INDEX_SPECIFIER: case B_INDEX_SPECIFIER:
case B_REVERSE_INDEX_SPECIFIER: { case B_REVERSE_INDEX_SPECIFIER:
int32 ind = -1; {
err = specifier->FindInt32("index", &ind); int32 index = -1;
err = specifier->FindInt32("index", &index);
if (err != B_OK) if (err != B_OK)
break; break;
if (what == B_REVERSE_INDEX_SPECIFIER) if (what == B_REVERSE_INDEX_SPECIFIER)
ind = CountWindows() - ind; index = CountWindows() - index;
err = B_BAD_INDEX; err = B_BAD_INDEX;
BWindow *win = WindowAt(ind); BWindow *win = WindowAt(index);
if (!win) if (!win)
break; break;
BMessenger messenger(win); BMessenger messenger(win);
err = reply.AddMessenger("result", messenger); err = reply.AddMessenger("result", messenger);
break; break;
} }
case B_NAME_SPECIFIER: { case B_NAME_SPECIFIER:
{
const char *name; const char *name;
err = specifier->FindString("name", &name); err = specifier->FindString("name", &name);
if (err != B_OK) if (err != B_OK)
break; break;
err = B_NAME_NOT_FOUND; err = B_NAME_NOT_FOUND;
for (int32 i = 0; i < CountWindows(); i++) { for (int32 i = 0; i < CountWindows(); i++) {
BWindow *win = WindowAt(i); BWindow* window = WindowAt(i);
if (win && win->Name() && strlen(win->Name()) == strlen(name) if (window && window->Name() != NULL
&& !strcmp(win->Name(), name)) { && !strcmp(window->Name(), name)) {
BMessenger messenger(win); BMessenger messenger(window);
err = reply.AddMessenger("result", messenger); err = reply.AddMessenger("result", messenger);
break; break;
} }
} }
break;
} }
} }
} else if (strcmp("Looper", property) == 0) { } else if (strcmp("Looper", property) == 0) {
switch (what) { switch (what) {
case B_INDEX_SPECIFIER: case B_INDEX_SPECIFIER:
case B_REVERSE_INDEX_SPECIFIER: { case B_REVERSE_INDEX_SPECIFIER:
int32 ind = -1; {
err = specifier->FindInt32("index", &ind); int32 index = -1;
err = specifier->FindInt32("index", &index);
if (err != B_OK) if (err != B_OK)
break; break;
if (what == B_REVERSE_INDEX_SPECIFIER) if (what == B_REVERSE_INDEX_SPECIFIER)
ind = CountLoopers() - ind; index = CountLoopers() - index;
err = B_BAD_INDEX; err = B_BAD_INDEX;
BLooper *looper = LooperAt(ind); BLooper *looper = LooperAt(index);
if (!looper) if (!looper)
break; break;
BMessenger messenger(looper); BMessenger messenger(looper);
err = reply.AddMessenger("result", messenger); err = reply.AddMessenger("result", messenger);
break; break;
} }
case B_NAME_SPECIFIER: { case B_NAME_SPECIFIER:
{
const char *name; const char *name;
err = specifier->FindString("name", &name); err = specifier->FindString("name", &name);
if (err != B_OK) if (err != B_OK)
@@ -1124,7 +1129,7 @@ BApplication::ScriptReceived(BMessage *message, int32 index,
err = B_NAME_NOT_FOUND; err = B_NAME_NOT_FOUND;
for (int32 i = 0; i < CountLoopers(); i++) { for (int32 i = 0; i < CountLoopers(); i++) {
BLooper *looper = LooperAt(i); BLooper *looper = LooperAt(i);
if (looper && looper->Name() && strlen(looper->Name()) == strlen(name) if (looper && looper->Name()
&& !strcmp(looper->Name(), name)) { && !strcmp(looper->Name(), name)) {
BMessenger messenger(looper); BMessenger messenger(looper);
err = reply.AddMessenger("result", messenger); err = reply.AddMessenger("result", messenger);
@@ -1133,8 +1138,10 @@ BApplication::ScriptReceived(BMessage *message, int32 index,
} }
break; break;
} }
case B_ID_SPECIFIER: { case B_ID_SPECIFIER:
{
// TODO // TODO
debug_printf("Looper's ID specifier used but not implemented.\n");
break; break;
} }
} }
@@ -1150,9 +1157,9 @@ BApplication::ScriptReceived(BMessage *message, int32 index,
} }
break; break;
} }
if (err == B_BAD_SCRIPT_SYNTAX) { if (err == B_BAD_SCRIPT_SYNTAX)
return false; return false;
}
if (err < B_OK) { if (err < B_OK) {
reply.what = B_MESSAGE_NOT_UNDERSTOOD; reply.what = B_MESSAGE_NOT_UNDERSTOOD;
reply.AddString("message", strerror(err)); reply.AddString("message", strerror(err));
@@ -1322,46 +1329,27 @@ BApplication::write_drag(_BSession_ *session, BMessage *message)
bool bool
BApplication::_WindowQuitLoop(bool quitFilePanels, bool force) BApplication::_WindowQuitLoop(bool quitFilePanels, bool force)
{ {
BList looperList; int32 index = 0;
{ while (true) {
AutoLocker<BLooperList> listLock(gLooperList); BWindow *window = WindowAt(index);
if (listLock.IsLocked()) { if (window == NULL)
gLooperList.GetLooperList(&looperList); break;
// Filter the list: We replace the BLooper pointers by BWindow
// pointers (dynamic_cast<>() on unlocked loopers is only safe as
// long as the looper list is locked!). Furthermore we filter out
// windows, that have not been run yet -- those belong to their
// creator yet (which also has a lock) and we must not try to
// delete them.
int32 count = looperList.CountItems();
for (int32 i = 0; i < count; i++) {
BWindow *window
= dynamic_cast<BWindow*>((BLooper*)looperList.ItemAt(i));
if (window && window->Thread() < 0)
window = NULL;
looperList.ReplaceItem(i, window);
}
}
}
for (int32 i = looperList.CountItems(); i-- > 0; ) {
BWindow *window = (BWindow*)looperList.ItemAt(i);
// don't quit file panels if we haven't been asked for it
// NOTE: the window pointer will be NULL if the looper was not
// a BWindow or if the thread wasn't running, see above
if (window == NULL || (!quitFilePanels && window->IsFilePanel()))
continue;
// NOTE: the window pointer might be stale, in case the looper // NOTE: the window pointer might be stale, in case the looper
// was already quit by quitting an earlier looper... but fortunately, // was already quit by quitting an earlier looper... but fortunately,
// we can still call Lock() on the invalid pointer, and it // we can still call Lock() on the invalid pointer, and it
// will return false... // will return false...
if (window->Lock()) { if (!window->Lock())
// never ask hidden windows if they want to quit, ignore continue;
// them if force == false, just quit them if force == true
if (!force && !window->IsHidden() && !window->QuitRequested() // don't quit file panels if we haven't been asked for it
if (!quitFilePanels && window->IsFilePanel()) {
window->Unlock();
index++;
continue;
}
if (!force && !window->QuitRequested()
&& !(quitFilePanels && window->IsFilePanel())) { && !(quitFilePanels && window->IsFilePanel())) {
// the window does not want to quit, so we don't either // the window does not want to quit, so we don't either
window->Unlock(); window->Unlock();
@@ -1373,7 +1361,10 @@ BApplication::_WindowQuitLoop(bool quitFilePanels, bool force)
// double-locking is harmless. // double-locking is harmless.
if (window->Lock()) if (window->Lock())
window->Quit(); window->Quit();
}
index = 0;
// we need to continue at the start of the list again - it
// might have changed
} }
return true; return true;
} }
@@ -1447,10 +1438,14 @@ BApplication::InitialWorkspace()
int32 int32
BApplication::_CountWindows(bool includeMenus) const BApplication::_CountWindows(bool includeMenus) const
{ {
int32 count = 0; uint32 count = 0;
BList windowList; for (int32 i = 0; i < gLooperList.CountLoopers(); i++) {
if (_GetWindowList(&windowList, includeMenus) == B_OK) BWindow* window = dynamic_cast<BWindow*>(gLooperList.LooperAt(i));
count = windowList.CountItems(); if (window == NULL || (!includeMenus
&& dynamic_cast<BMenuWindow *>(window) == NULL)) {
count++;
}
}
return count; return count;
} }
@@ -1459,38 +1454,24 @@ BApplication::_CountWindows(bool includeMenus) const
BWindow * BWindow *
BApplication::_WindowAt(uint32 index, bool includeMenus) const BApplication::_WindowAt(uint32 index, bool includeMenus) const
{ {
BList windowList; AutoLocker<BLooperList> listLock(gLooperList);
BWindow *window = NULL; if (!listLock.IsLocked())
if (_GetWindowList(&windowList, includeMenus) == B_OK) { return NULL;
if ((int32)index < windowList.CountItems())
window = static_cast<BWindow *>(windowList.ItemAt(index)); uint32 count = gLooperList.CountLoopers();
for (uint32 i = 0; i < count && index < count; i++) {
BWindow* window = dynamic_cast<BWindow*>(gLooperList.LooperAt(i));
if (window == NULL || (!includeMenus
&& dynamic_cast<BMenuWindow *>(window) == NULL)) {
index++;
continue;
} }
if (i == index)
return window; return window;
} }
return NULL;
status_t
BApplication::_GetWindowList(BList *list, bool includeMenus) const
{
ASSERT(list);
// Windows are BLoopers, so we can just check each BLooper to see if it's
// a BWindow (or BMenuWindow)
AutoLocker<BLooperList> listLock(gLooperList);
if (!listLock.IsLocked())
return B_ERROR;
BLooper *looper = NULL;
for (int32 i = 0; i < gLooperList.CountLoopers(); i++) {
looper = gLooperList.LooperAt(i);
if (dynamic_cast<BWindow *>(looper)) {
if (includeMenus || dynamic_cast<BMenuWindow *>(looper) == NULL)
list->AddItem(looper);
}
}
return B_OK;
} }