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)
\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.
@@ -313,7 +313,8 @@
/*!
\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.
@@ -323,7 +324,8 @@
/*!
\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.
@@ -28,7 +28,8 @@ TeamListItem::TeamListItem(team_info &teamInfo)
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),
fFound(false),
fRefusingToQuit(false)
fRefusingToQuit(false),
fIsParent(false)
{
int32 cookie = 0;
image_info info;
@@ -40,8 +41,7 @@ TeamListItem::TeamListItem(team_info &teamInfo)
nodeInfo.GetTrackerIcon(&fLargeIcon, (icon_size)-1);
}
if (be_roster->GetRunningAppInfo(fTeamInfo.team, &fAppInfo) != B_OK)
fAppInfo.signature[0] = '\0';
fIsApplication = be_roster->GetRunningAppInfo(fTeamInfo.team, &fAppInfo) == B_OK;
CacheLocalizedName();
}
@@ -181,13 +181,6 @@ TeamListItem::IsSystemServer()
}
bool
TeamListItem::IsApplication() const
{
return fAppInfo.signature[0] != '\0';
}
void
TeamListItem::SetRefusingToQuit(bool refusing)
{
@@ -36,11 +36,14 @@ public:
const char* AppSignature() { return fAppInfo.signature; };
bool IsSystemServer();
bool IsApplication() const;
bool IsApplication() const { return fIsApplication; }
bool Found() const { return fFound; }
void SetFound(bool found) { fFound = found; }
bool IsParent() const { return fIsParent; }
void SetIsParent(bool isParent) { fIsParent = isParent; }
void SetRefusingToQuit(bool refusing);
bool IsRefusingToQuit();
@@ -55,6 +58,8 @@ private:
BString fLocalizedName;
bool fFound;
bool fRefusingToQuit;
bool fIsParent;
bool fIsApplication;
};
@@ -5,12 +5,14 @@
* Authors:
* Jérôme Duval
* Axel Doerfler, [email protected]
* Pawan Yerramilli, [email protected]
*/
//! Keyboard input server addon
#include "TeamMonitorWindow.h"
#include <set>
#include <stdio.h>
#include <Application.h>
@@ -31,6 +33,7 @@
#include <StringView.h>
#include <syscalls.h>
#include <syscall_process_info.h>
#include <tracker_private.h>
#include "KeyboardInputDevice.h"
@@ -164,7 +167,7 @@ TeamMonitorWindow::TeamMonitorWindow()
layout->View()->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
fListView = new BListView("teams");
fListView = new BOutlineListView("teams");
fListView->SetSelectionMessage(new BMessage(TM_SELECTED_TEAM));
BScrollView* scrollView = new BScrollView("scroll_teams", fListView,
@@ -285,8 +288,8 @@ TeamMonitorWindow::MessageReceived(BMessage* msg)
case TM_KILL_APPLICATION:
{
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt(
fListView->CurrentSelection()));
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(
fListView->FullListCurrentSelection()));
if (item != NULL) {
kill_team(item->GetInfo()->team);
_UpdateList();
@@ -295,11 +298,10 @@ TeamMonitorWindow::MessageReceived(BMessage* msg)
}
case TM_QUIT_APPLICATION:
{
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt(
fListView->CurrentSelection()));
if (item != NULL) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(
fListView->FullListCurrentSelection()));
if (item != NULL)
QuitTeam(item);
}
break;
}
case kMsgQuitFailed:
@@ -318,9 +320,9 @@ TeamMonitorWindow::MessageReceived(BMessage* msg)
}
case TM_SELECTED_TEAM:
{
fKillButton->SetEnabled(fListView->CurrentSelection() >= 0);
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt(
fListView->CurrentSelection()));
fKillButton->SetEnabled(fListView->FullListCurrentSelection() >= 0);
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(
fListView->FullListCurrentSelection()));
fDescriptionView->SetItem(item);
fQuitButton->SetEnabled(item != NULL && item->IsApplication());
break;
@@ -380,8 +382,8 @@ TeamMonitorWindow::Disable()
fUpdateRunner = NULL;
Hide();
fListView->DeselectAll();
for (int32 i = 0; i < fListView->CountItems(); i++) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt(i));
for (int32 i = 0; i < fListView->FullListCountItems(); i++) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL)
item->SetRefusingToQuit(false);
}
@@ -395,9 +397,9 @@ TeamMonitorWindow::LocaleChanged()
gLocalizedNamePreferred
= BLocaleRoster::Default()->IsFilesystemTranslationPreferred();
for (int32 i = 0; i < fListView->CountItems(); i++) {
for (int32 i = 0; i < fListView->FullListCountItems(); i++) {
TeamListItem* item
= dynamic_cast<TeamListItem*>(fListView->ItemAt(i));
= dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL)
item->CacheLocalizedName();
}
@@ -445,9 +447,9 @@ TeamMonitorWindow::MarkUnquittableTeam(BMessage* message)
reinterpret_cast<void**>(&teamQuitter)) != B_OK)
return;
for (int32 i = 0; i < fListView->CountItems(); i++) {
for (int32 i = 0; i < fListView->FullListCountItems(); i++) {
TeamListItem* item
= dynamic_cast<TeamListItem*>(fListView->ItemAt(i));
= dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL && item->GetInfo()->team == teamQuitter->team) {
item->SetRefusingToQuit(true);
fListView->Select(i);
@@ -509,40 +511,64 @@ TeamMonitorWindow::_UpdateList()
{
bool changed = false;
for (int32 i = 0; i < fListView->CountItems(); i++) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt(i));
for (int32 i = 0; i < fListView->FullListCountItems(); i++) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL)
item->SetFound(false);
}
std::set<BString> paths;
int32 cookie = 0;
team_info info;
while (get_next_team_info(&cookie, &info) == B_OK) {
if (info.team <=16)
continue;
bool found = false;
for (int32 i = 0; i < fListView->CountItems(); i++) {
TeamListItem* item
= dynamic_cast<TeamListItem*>(fListView->ItemAt(i));
if (item != NULL && item->GetInfo()->team == info.team) {
item->SetFound(true);
found = true;
app_info ai;
bool isApp = be_roster->GetRunningAppInfo(info.team, &ai) == B_OK;
TeamListItem* item = fItemMap.Get(info.team);
if (item != NULL && isApp == item->IsApplication()) {
item->SetFound(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) {
TeamListItem* item = new TeamListItem(info);
if (insertUnder != NULL)
fListView->AddUnder(item, insertUnder);
else {
item->SetIsParent(true);
fListView->AddItem(item,
item->IsSystemServer() ? fListView->CountItems() : 0);
item->SetFound(true);
changed = true;
item->IsSystemServer() ? fListView->FullListCountItems() : 0);
fListView->Collapse(item);
}
fItemMap.Put(info.team, item);
paths.insert(BString(item->Path()->Path()));
changed = true;
}
for (int32 i = fListView->CountItems() - 1; i >= 0; i--) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->ItemAt(i));
for (int32 i = fListView->FullListCountItems() - 1; i >= 0; i--) {
TeamListItem* item = dynamic_cast<TeamListItem*>(fListView->FullListItemAt(i));
if (item != NULL && !item->Found()) {
if (item == fDescriptionView->Item()) {
fDescriptionView->SetItem(NULL);
@@ -550,6 +576,17 @@ TeamMonitorWindow::_UpdateList()
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);
changed = true;
}
@@ -12,8 +12,9 @@
#include <Box.h>
#include <Button.h>
#include <ListView.h>
#include <HashMap.h>
#include <MessageFilter.h>
#include <OutlineListView.h>
#include <Window.h>
#include "TeamListItem.h"
@@ -42,13 +43,14 @@ private:
bool fQuitting;
BMessageRunner* fUpdateRunner;
BListView* fListView;
BOutlineListView* fListView;
BButton* fCancelButton;
BButton* fKillButton;
BButton* fQuitButton;
BButton* fRestartButton;
TeamDescriptionView* fDescriptionView;
BList fTeamQuitterList;
HashMap<HashKey32<int32>, TeamListItem*> fItemMap;
};
static const uint32 kMsgCtrlAltDelPressed = 'TMcp';