* 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;
+126 -145
View File
@@ -1065,78 +1065,85 @@ 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;
if (err != B_OK) err = specifier->FindInt32("index", &index);
break; if (err != B_OK)
if (what == B_REVERSE_INDEX_SPECIFIER)
ind = CountWindows() - ind;
err = B_BAD_INDEX;
BWindow *win = WindowAt(ind);
if (!win)
break;
BMessenger messenger(win);
err = reply.AddMessenger("result", messenger);
break;
}
case B_NAME_SPECIFIER: {
const char *name;
err = specifier->FindString("name", &name);
if (err != B_OK)
break;
err = B_NAME_NOT_FOUND;
for (int32 i=0; i<CountWindows(); i++) {
BWindow *win = WindowAt(i);
if (win && win->Name() && strlen(win->Name()) == strlen(name)
&& !strcmp(win->Name(), name)) {
BMessenger messenger(win);
err = reply.AddMessenger("result", messenger);
break; break;
} if (what == B_REVERSE_INDEX_SPECIFIER)
index = CountWindows() - index;
err = B_BAD_INDEX;
BWindow *win = WindowAt(index);
if (!win)
break;
BMessenger messenger(win);
err = reply.AddMessenger("result", messenger);
break;
}
case B_NAME_SPECIFIER:
{
const char *name;
err = specifier->FindString("name", &name);
if (err != B_OK)
break;
err = B_NAME_NOT_FOUND;
for (int32 i = 0; i < CountWindows(); i++) {
BWindow* window = WindowAt(i);
if (window && window->Name() != NULL
&& !strcmp(window->Name(), name)) {
BMessenger messenger(window);
err = reply.AddMessenger("result", messenger);
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;
if (err != B_OK) err = specifier->FindInt32("index", &index);
break; if (err != B_OK)
if (what == B_REVERSE_INDEX_SPECIFIER)
ind = CountLoopers() - ind;
err = B_BAD_INDEX;
BLooper *looper = LooperAt(ind);
if (!looper)
break;
BMessenger messenger(looper);
err = reply.AddMessenger("result", messenger);
break;
}
case B_NAME_SPECIFIER: {
const char *name;
err = specifier->FindString("name", &name);
if (err != B_OK)
break;
err = B_NAME_NOT_FOUND;
for (int32 i=0; i<CountLoopers(); i++) {
BLooper *looper = LooperAt(i);
if (looper && looper->Name() && strlen(looper->Name()) == strlen(name)
&& !strcmp(looper->Name(), name)) {
BMessenger messenger(looper);
err = reply.AddMessenger("result", messenger);
break; break;
} if (what == B_REVERSE_INDEX_SPECIFIER)
index = CountLoopers() - index;
err = B_BAD_INDEX;
BLooper *looper = LooperAt(index);
if (!looper)
break;
BMessenger messenger(looper);
err = reply.AddMessenger("result", messenger);
break;
}
case B_NAME_SPECIFIER:
{
const char *name;
err = specifier->FindString("name", &name);
if (err != B_OK)
break;
err = B_NAME_NOT_FOUND;
for (int32 i = 0; i < CountLoopers(); i++) {
BLooper *looper = LooperAt(i);
if (looper && looper->Name()
&& !strcmp(looper->Name(), name)) {
BMessenger messenger(looper);
err = reply.AddMessenger("result", messenger);
break;
}
}
break;
}
case B_ID_SPECIFIER:
{
// TODO
debug_printf("Looper's ID specifier used but not implemented.\n");
break;
} }
break;
}
case B_ID_SPECIFIER: {
// TODO
break;
}
} }
} else if (strcmp("Name", property) == 0) { } else if (strcmp("Name", property) == 0) {
err = reply.AddString("result", Name()); err = reply.AddString("result", Name());
@@ -1150,13 +1157,13 @@ 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));
} }
reply.AddInt32("error", err); reply.AddInt32("error", err);
message->SendReply(&reply); message->SendReply(&reply);
return true; return true;
@@ -1322,58 +1329,42 @@ 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()
&& !(quitFilePanels && window->IsFilePanel())) {
// the window does not want to quit, so we don't either
window->Unlock();
return false;
}
// Re-lock, just to make sure that the user hasn't done nasty // don't quit file panels if we haven't been asked for it
// things in QuitRequested(). Quit() unlocks fully, thus if (!quitFilePanels && window->IsFilePanel()) {
// double-locking is harmless. window->Unlock();
if (window->Lock()) index++;
window->Quit(); continue;
} }
if (!force && !window->QuitRequested()
&& !(quitFilePanels && window->IsFilePanel())) {
// the window does not want to quit, so we don't either
window->Unlock();
return false;
}
// Re-lock, just to make sure that the user hasn't done nasty
// things in QuitRequested(). Quit() unlocks fully, thus
// double-locking is harmless.
if (window->Lock())
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;
BWindow *window = NULL;
if (_GetWindowList(&windowList, includeMenus) == B_OK) {
if ((int32)index < windowList.CountItems())
window = static_cast<BWindow *>(windowList.ItemAt(index));
}
return window;
}
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); AutoLocker<BLooperList> listLock(gLooperList);
if (!listLock.IsLocked()) if (!listLock.IsLocked())
return B_ERROR; return NULL;
BLooper *looper = NULL; uint32 count = gLooperList.CountLoopers();
for (int32 i = 0; i < gLooperList.CountLoopers(); i++) { for (uint32 i = 0; i < count && index < count; i++) {
looper = gLooperList.LooperAt(i); BWindow* window = dynamic_cast<BWindow*>(gLooperList.LooperAt(i));
if (dynamic_cast<BWindow *>(looper)) { if (window == NULL || (!includeMenus
if (includeMenus || dynamic_cast<BMenuWindow *>(looper) == NULL) && dynamic_cast<BMenuWindow *>(window) == NULL)) {
list->AddItem(looper); index++;
continue;
} }
if (i == index)
return window;
} }
return B_OK; return NULL;
} }