TeamMonitor: Group teams.

Programs like Iceweasel and Falkon/QTWebEngine spawn lots of processes
that clog up Team monitor. To reduce the clutter, group teams under the BApplication that spawned them.

Groups are collapsed by default, and the tree only goes one level deep.
If a BApp spawns other BApps with the same executable, they are grouped
under it.

Also, fix bug where opening Team monitor before be_roster has info for a
BApp (immediately after launch) can sometimes cause the 'Quit' button to
be incorrectly disabled.

Also, update BOutlineListView::RemoveItem documentation; neither the
BeBook nor the HaikuBook mentioned that these will both remove *and
delete* child items (BeBook mentions removing, HaikuBook mentions
neither), which cost me some time debugging . . .

(a previous version of this patch grouped solely by name)

Change-Id: I29c627fbc905da5b5dc7145589f8da21ae8ba6fe
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8770
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
PawanYr
2025-01-10 03:53:34 +00:00
committed by waddlesplash
parent 44cc18e1c4
commit 372d066f2f
5 changed files with 88 additions and 49 deletions
+5 -3
View File
@@ -301,7 +301,7 @@
/*! /*!
\fn bool BOutlineListView::RemoveItem(BListItem* item) \fn bool BOutlineListView::RemoveItem(BListItem* item)
\brief Removes the \a item from the list. \brief Removes the \a item from the list. Subitems will be removed and deleted.
\param item The \a item to remove. \param item The \a item to remove.
@@ -313,7 +313,8 @@
/*! /*!
\fn BListItem* BOutlineListView::RemoveItem(int32 fullListIndex) \fn BListItem* BOutlineListView::RemoveItem(int32 fullListIndex)
\brief Removes the \a item located at \a fullListIndex from the list. \brief Removes the \a item located at \a fullListIndex from the list. Subitems will be removed
and deleted.
\return A pointer to the BListItem removed. \return A pointer to the BListItem removed.
@@ -323,7 +324,8 @@
/*! /*!
\fn bool BOutlineListView::RemoveItems(int32 fullListIndex, int32 count) \fn bool BOutlineListView::RemoveItems(int32 fullListIndex, int32 count)
\brief Removes \a count items starting at \a fullListIndex from the list. \brief Removes \a count items starting at \a fullListIndex from the list. Subitems will be
removed and deleted.
\return \c true if the items were removed, \c false otherwise. \return \c true if the items were removed, \c false otherwise.
@@ -28,7 +28,8 @@ TeamListItem::TeamListItem(team_info &teamInfo)
fMiniIcon(BRect(BPoint(0, 0), be_control_look->ComposeIconSize(B_MINI_ICON)), B_RGBA32), fMiniIcon(BRect(BPoint(0, 0), be_control_look->ComposeIconSize(B_MINI_ICON)), B_RGBA32),
fLargeIcon(BRect(BPoint(0, 0), be_control_look->ComposeIconSize(B_LARGE_ICON)), B_RGBA32), fLargeIcon(BRect(BPoint(0, 0), be_control_look->ComposeIconSize(B_LARGE_ICON)), B_RGBA32),
fFound(false), fFound(false),
fRefusingToQuit(false) fRefusingToQuit(false),
fIsParent(false)
{ {
int32 cookie = 0; int32 cookie = 0;
image_info info; image_info info;
@@ -40,8 +41,7 @@ TeamListItem::TeamListItem(team_info &teamInfo)
nodeInfo.GetTrackerIcon(&fLargeIcon, (icon_size)-1); nodeInfo.GetTrackerIcon(&fLargeIcon, (icon_size)-1);
} }
if (be_roster->GetRunningAppInfo(fTeamInfo.team, &fAppInfo) != B_OK) fIsApplication = be_roster->GetRunningAppInfo(fTeamInfo.team, &fAppInfo) == B_OK;
fAppInfo.signature[0] = '\0';
CacheLocalizedName(); CacheLocalizedName();
} }
@@ -181,13 +181,6 @@ TeamListItem::IsSystemServer()
} }
bool
TeamListItem::IsApplication() const
{
return fAppInfo.signature[0] != '\0';
}
void void
TeamListItem::SetRefusingToQuit(bool refusing) TeamListItem::SetRefusingToQuit(bool refusing)
{ {
@@ -36,11 +36,14 @@ public:
const char* AppSignature() { return fAppInfo.signature; }; const char* AppSignature() { return fAppInfo.signature; };
bool IsSystemServer(); bool IsSystemServer();
bool IsApplication() const; bool IsApplication() const { return fIsApplication; }
bool Found() const { return fFound; } bool Found() const { return fFound; }
void SetFound(bool found) { fFound = found; } void SetFound(bool found) { fFound = found; }
bool IsParent() const { return fIsParent; }
void SetIsParent(bool isParent) { fIsParent = isParent; }
void SetRefusingToQuit(bool refusing); void SetRefusingToQuit(bool refusing);
bool IsRefusingToQuit(); bool IsRefusingToQuit();
@@ -55,6 +58,8 @@ private:
BString fLocalizedName; BString fLocalizedName;
bool fFound; bool fFound;
bool fRefusingToQuit; bool fRefusingToQuit;
bool fIsParent;
bool fIsApplication;
}; };
@@ -5,12 +5,14 @@
* Authors: * Authors:
* Jérôme Duval * Jérôme Duval
* Axel Doerfler, [email protected] * Axel Doerfler, [email protected]
* Pawan Yerramilli, [email protected]
*/ */
//! Keyboard input server addon //! Keyboard input server addon
#include "TeamMonitorWindow.h" #include "TeamMonitorWindow.h"
#include <set>
#include <stdio.h> #include <stdio.h>
#include <Application.h> #include <Application.h>
@@ -31,6 +33,7 @@
#include <StringView.h> #include <StringView.h>
#include <syscalls.h> #include <syscalls.h>
#include <syscall_process_info.h>
#include <tracker_private.h> #include <tracker_private.h>
#include "KeyboardInputDevice.h" #include "KeyboardInputDevice.h"
@@ -164,7 +167,7 @@ TeamMonitorWindow::TeamMonitorWindow()
layout->View()->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); layout->View()->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
fListView = new BListView("teams"); fListView = new BOutlineListView("teams");
fListView->SetSelectionMessage(new BMessage(TM_SELECTED_TEAM)); fListView->SetSelectionMessage(new BMessage(TM_SELECTED_TEAM));
BScrollView* scrollView = new BScrollView("scroll_teams", fListView, BScrollView* scrollView = new BScrollView("scroll_teams", fListView,
@@ -285,8 +288,8 @@ TeamMonitorWindow::MessageReceived(BMessage* msg)
case TM_KILL_APPLICATION: case TM_KILL_APPLICATION:
{ {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt( TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(
fListView->CurrentSelection())); fListView->FullListCurrentSelection()));
if (item != NULL) { if (item != NULL) {
kill_team(item->GetInfo()->team); kill_team(item->GetInfo()->team);
_UpdateList(); _UpdateList();
@@ -295,11 +298,10 @@ TeamMonitorWindow::MessageReceived(BMessage* msg)
} }
case TM_QUIT_APPLICATION: case TM_QUIT_APPLICATION:
{ {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt( TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(
fListView->CurrentSelection())); fListView->FullListCurrentSelection()));
if (item != NULL) { if (item != NULL)
QuitTeam(item); QuitTeam(item);
}
break; break;
} }
case kMsgQuitFailed: case kMsgQuitFailed:
@@ -318,9 +320,9 @@ TeamMonitorWindow::MessageReceived(BMessage* msg)
} }
case TM_SELECTED_TEAM: case TM_SELECTED_TEAM:
{ {
fKillButton->SetEnabled(fListView->CurrentSelection() >= 0); fKillButton->SetEnabled(fListView->FullListCurrentSelection() >= 0);
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt( TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(
fListView->CurrentSelection())); fListView->FullListCurrentSelection()));
fDescriptionView->SetItem(item); fDescriptionView->SetItem(item);
fQuitButton->SetEnabled(item != NULL && item->IsApplication()); fQuitButton->SetEnabled(item != NULL && item->IsApplication());
break; break;
@@ -380,8 +382,8 @@ TeamMonitorWindow::Disable()
fUpdateRunner = NULL; fUpdateRunner = NULL;
Hide(); Hide();
fListView->DeselectAll(); fListView->DeselectAll();
for (int32 i = 0; i < fListView->CountItems(); i++) { for (int32 i = 0; i < fListView->FullListCountItems(); i++) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt(i)); TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL) if (item != NULL)
item->SetRefusingToQuit(false); item->SetRefusingToQuit(false);
} }
@@ -395,9 +397,9 @@ TeamMonitorWindow::LocaleChanged()
gLocalizedNamePreferred gLocalizedNamePreferred
= BLocaleRoster::Default()->IsFilesystemTranslationPreferred(); = BLocaleRoster::Default()->IsFilesystemTranslationPreferred();
for (int32 i = 0; i < fListView->CountItems(); i++) { for (int32 i = 0; i < fListView->FullListCountItems(); i++) {
TeamListItem* item TeamListItem* item
= dynamic_cast<TeamListItem*>(fListView->ItemAt(i)); = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL) if (item != NULL)
item->CacheLocalizedName(); item->CacheLocalizedName();
} }
@@ -445,9 +447,9 @@ TeamMonitorWindow::MarkUnquittableTeam(BMessage* message)
reinterpret_cast<void**>(&teamQuitter)) != B_OK) reinterpret_cast<void**>(&teamQuitter)) != B_OK)
return; return;
for (int32 i = 0; i < fListView->CountItems(); i++) { for (int32 i = 0; i < fListView->FullListCountItems(); i++) {
TeamListItem* item TeamListItem* item
= dynamic_cast<TeamListItem*>(fListView->ItemAt(i)); = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL && item->GetInfo()->team == teamQuitter->team) { if (item != NULL && item->GetInfo()->team == teamQuitter->team) {
item->SetRefusingToQuit(true); item->SetRefusingToQuit(true);
fListView->Select(i); fListView->Select(i);
@@ -509,40 +511,64 @@ TeamMonitorWindow::_UpdateList()
{ {
bool changed = false; bool changed = false;
for (int32 i = 0; i < fListView->CountItems(); i++) { for (int32 i = 0; i < fListView->FullListCountItems(); i++) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt(i)); TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL) if (item != NULL)
item->SetFound(false); item->SetFound(false);
} }
std::set<BString> paths;
int32 cookie = 0; int32 cookie = 0;
team_info info; team_info info;
while (get_next_team_info(&cookie, &info) == B_OK) { while (get_next_team_info(&cookie, &info) == B_OK) {
if (info.team <=16) if (info.team <=16)
continue; continue;
bool found = false; app_info ai;
for (int32 i = 0; i < fListView->CountItems(); i++) { bool isApp = be_roster->GetRunningAppInfo(info.team, &ai) == B_OK;
TeamListItem* item
= dynamic_cast<TeamListItem*>(fListView->ItemAt(i)); TeamListItem* item = fItemMap.Get(info.team);
if (item != NULL && item->GetInfo()->team == info.team) { if (item != NULL && isApp == item->IsApplication()) {
item->SetFound(true); item->SetFound(true);
found = true; paths.insert(BString(item->Path()->Path()));
continue;
}
item = new TeamListItem(info);
item->SetFound(true);
TeamListItem* insertUnder = NULL;
if (!isApp || paths.count(item->Path()->Path()) > 0) {
int32 spawner_id = _kern_process_info(info.team, PARENT_ID);
insertUnder = fItemMap.Get(spawner_id);
while (insertUnder != NULL && !insertUnder->IsParent())
insertUnder = dynamic_cast<TeamListItem*>(fListView->Superitem(insertUnder));
if (insertUnder != NULL) {
if (isApp && *insertUnder->Path() != *item->Path())
insertUnder = NULL;
else if (!insertUnder->Found())
insertUnder = NULL;
} }
} }
if (!found) { if (insertUnder != NULL)
TeamListItem* item = new TeamListItem(info); fListView->AddUnder(item, insertUnder);
else {
item->SetIsParent(true);
fListView->AddItem(item, fListView->AddItem(item,
item->IsSystemServer() ? fListView->CountItems() : 0); item->IsSystemServer() ? fListView->FullListCountItems() : 0);
item->SetFound(true); fListView->Collapse(item);
}
fItemMap.Put(info.team, item);
paths.insert(BString(item->Path()->Path()));
changed = true; changed = true;
} }
}
for (int32 i = fListView->CountItems() - 1; i >= 0; i--) { for (int32 i = fListView->FullListCountItems() - 1; i >= 0; i--) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt(i)); TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL && !item->Found()) { if (item != NULL && !item->Found()) {
if (item == fDescriptionView->Item()) { if (item == fDescriptionView->Item()) {
fDescriptionView->SetItem(NULL); fDescriptionView->SetItem(NULL);
@@ -550,6 +576,17 @@ TeamMonitorWindow::_UpdateList()
fQuitButton->SetEnabled(false); fQuitButton->SetEnabled(false);
} }
if (item->IsParent()) {
for (int32 j = 0; j < fListView->CountItemsUnder(item, true); j++) {
TeamListItem* child = dynamic_cast<TeamListItem*>(
fListView->ItemUnderAt(item, true, j));
if (child != NULL && !fItemMap.Get(child->GetInfo()->team)->Found())
fItemMap.Remove(child->GetInfo()->team);
}
}
if (!fItemMap.Get(item->GetInfo()->team)->Found())
fItemMap.Remove(item->GetInfo()->team);
delete fListView->RemoveItem(i); delete fListView->RemoveItem(i);
changed = true; changed = true;
} }
@@ -12,8 +12,9 @@
#include <Box.h> #include <Box.h>
#include <Button.h> #include <Button.h>
#include <ListView.h> #include <HashMap.h>
#include <MessageFilter.h> #include <MessageFilter.h>
#include <OutlineListView.h>
#include <Window.h> #include <Window.h>
#include "TeamListItem.h" #include "TeamListItem.h"
@@ -42,13 +43,14 @@ private:
bool fQuitting; bool fQuitting;
BMessageRunner* fUpdateRunner; BMessageRunner* fUpdateRunner;
BListView* fListView; BOutlineListView* fListView;
BButton* fCancelButton; BButton* fCancelButton;
BButton* fKillButton; BButton* fKillButton;
BButton* fQuitButton; BButton* fQuitButton;
BButton* fRestartButton; BButton* fRestartButton;
TeamDescriptionView* fDescriptionView; TeamDescriptionView* fDescriptionView;
BList fTeamQuitterList; BList fTeamQuitterList;
HashMap<HashKey32<int32>, TeamListItem*> fItemMap;
}; };
static const uint32 kMsgCtrlAltDelPressed = 'TMcp'; static const uint32 kMsgCtrlAltDelPressed = 'TMcp';