void TWindowMenu::AttachedToWindow() { SetFont(be_plain_font); RemoveItems(0, CountItems(), true); int32 miniCount = 0; bool dragging = false; TBarView* barview =(static_cast<TBarApp*>(be_app))->BarView(); if (barview && barview->LockLooper()) { // 'dragging' mode set in BarView::CacheDragData // invoke in MouseEnter in ExpandoMenuBar dragging = barview->Dragging(); if (dragging) { // We don't want to show the menu when dragging, but it's not // possible to remove a submenu once it exists, so we simply hide it // Don't call BMenu::Hide(), it causes the menu to pop up every now // and then. Window()->Hide(); // if in expando (horizontal or vertical) if (barview->Expando()) { SetTrackingHook(barview->MenuTrackingHook, barview->GetTrackingHookData()); } barview->DragStart(); } barview->UnlockLooper(); } int32 parentMenuItems = 0; int32 numTeams = fTeam->CountItems(); for (int32 i = 0; i < numTeams; i++) { team_id theTeam = (team_id)fTeam->ItemAt(i); int32 count = 0; int32* tokens = get_token_list(theTeam, &count); for (int32 j = 0; j < count; j++) { client_window_info* wInfo = get_window_info(tokens[j]); if (wInfo == NULL) continue; if (WindowShouldBeListed(wInfo->feel) && (wInfo->show_hide_level <= 0 || wInfo->is_mini)) { // Don't add new items if we're expanded. We've already done // this, they've just been moved. int32 numItems = CountItems(); int32 addIndex = 0; for (; addIndex < numItems; addIndex++) if (strcasecmp(ItemAt(addIndex)->Label(), wInfo->name) > 0) break; if (!fExpanded) { TWindowMenuItem* item = new TWindowMenuItem(wInfo->name, wInfo->server_token, wInfo->is_mini, ((1 << current_workspace()) & wInfo->workspaces) != 0, dragging); // disable app's window dropping for now if (dragging) item->SetEnabled(false); AddItem(item, TWindowMenuItem::InsertIndexFor(this, 0, item)); } else { TTeamMenuItem* parentItem = static_cast<TTeamMenuItem*>(Superitem()); if (parentItem->ExpandedWindowItem(wInfo->server_token)) { TWindowMenuItem* item = parentItem->ExpandedWindowItem( wInfo->server_token); if (item == NULL) continue; item->SetTo(wInfo->name, wInfo->server_token, wInfo->is_mini, ((1 << current_workspace()) & wInfo->workspaces) != 0, dragging); parentMenuItems++; } } if (wInfo->is_mini) miniCount++; } free(wInfo); } free(tokens); } int32 itemCount = CountItems() + parentMenuItems; if (itemCount < 1) { TWindowMenuItem* noWindowsItem = new TWindowMenuItem("No windows", -1, false, false); noWindowsItem->SetEnabled(false); AddItem(noWindowsItem); // if an application has no windows, this feature makes it easy to quit // it. (but we only add this option if the application is not Tracker.) if (fApplicationSignature.ICompare(kTrackerSignature) != 0) { AddSeparatorItem(); AddItem(new TShowHideMenuItem("Quit application", fTeam, B_QUIT_REQUESTED)); } } else { // if we are in drag mode, then don't add the window controls // to the menu if (!dragging) { TShowHideMenuItem* hide = new TShowHideMenuItem("Hide all", fTeam, B_MINIMIZE_WINDOW); TShowHideMenuItem* show = new TShowHideMenuItem("Show all", fTeam, B_BRING_TO_FRONT); TShowHideMenuItem* close = new TShowHideMenuItem("Close all", fTeam, B_QUIT_REQUESTED); if (miniCount == itemCount) hide->SetEnabled(false); else if (miniCount == 0) show->SetEnabled(false); if (!parentMenuItems) AddSeparatorItem(); AddItem(hide); AddItem(show); AddItem(close); } } BMenu::AttachedToWindow(); }
int32 TExpandoMenuBar::monitor_team_windows(void *arg) { TExpandoMenuBar *teamMenu = (TExpandoMenuBar *)arg; int32 totalItems = 0; bool itemModified = false; TWindowMenuItem *item = NULL; TTeamMenuItem *teamItem = NULL; int32 *tokens = NULL; while (teamMenu->sDoMonitor) { totalItems = teamMenu->CountItems(); // Set all WindowMenuItems to require an update. item = NULL; for (int32 i = 0; i < totalItems; i++) { if (!teamMenu->SubmenuAt(i)){ item = static_cast<TWindowMenuItem *>(teamMenu->ItemAt(i)); item->SetRequireUpdate(); } } // Perform SetTo() on all the items that still exist as well as add new items. itemModified = false; teamItem = NULL; for (int32 i = 0; i < totalItems; i++) { if (teamMenu->SubmenuAt(i)){ teamItem = static_cast<TTeamMenuItem *>(teamMenu->ItemAt(i)); if (teamItem->IsExpanded()) { int32 teamCount = teamItem->Teams()->CountItems(); for (int32 j = 0; j < teamCount; j++) { // The following code is almost a copy/paste from // WindowMenu.cpp team_id theTeam = (team_id)teamItem->Teams()->ItemAt(j); int32 count = 0; tokens = get_token_list(theTeam, &count); for (int32 k = 0; k < count; k++) { window_info *wInfo = get_window_info(tokens[k]); if (wInfo == NULL) continue; if (TWindowMenu::WindowShouldBeListed(wInfo->w_type) && (wInfo->show_hide_level <= 0 || wInfo->is_mini)) { // Check if we have a matching window item... item = teamItem->ExpandedWindowItem(wInfo->id); if (item) { // Lock the window, changing workspaces will fry this. item->SetTo(wInfo->name, wInfo->id, wInfo->is_mini, ((1 << current_workspace()) & wInfo->workspaces) != 0); if (strcmp(wInfo->name, item->Label()) != 0) item->SetLabel(wInfo->name); if (item->ChangedState()) itemModified = true; } else if (teamItem->IsExpanded()) { // Add the item item = new TWindowMenuItem(wInfo->name, wInfo->id, wInfo->is_mini, ((1 << current_workspace()) & wInfo->workspaces) != 0, false); item->ExpandedItem(true); teamMenu->AddItem(item, i + 1); itemModified = true; teamMenu->Window()->Lock(); teamMenu->SizeWindow(); teamMenu->Window()->Unlock(); } } free(wInfo); } free(tokens); } } } } // Remove any remaining items which require an update. for (int32 i = 0; i < totalItems; i++) { if (!teamMenu->SubmenuAt(i)){ item = static_cast<TWindowMenuItem *>(teamMenu->ItemAt(i)); if (item && item->RequiresUpdate()) { item = static_cast<TWindowMenuItem *>(teamMenu->RemoveItem(i)); delete item; totalItems--; teamMenu->Window()->Lock(); teamMenu->SizeWindow(); teamMenu->Window()->Unlock(); } } } // If any of the WindowMenuItems changed state, we need to force a repaint. if (itemModified) { teamMenu->Window()->Lock(); teamMenu->Invalidate(); teamMenu->Window()->Unlock(); } // sleep for a bit... snooze(150000); } return B_OK; }
int32 TExpandoMenuBar::monitor_team_windows(void* arg) { TExpandoMenuBar* teamMenu = (TExpandoMenuBar*)arg; while (teamMenu->sDoMonitor) { sMonLocker.Lock(); if (teamMenu->Window()->LockWithTimeout(50000) == B_OK) { int32 totalItems = teamMenu->CountItems(); // Set all WindowMenuItems to require an update. TWindowMenuItem* item = NULL; for (int32 i = 0; i < totalItems; i++) { if (!teamMenu->SubmenuAt(i)) { item = static_cast<TWindowMenuItem*>(teamMenu->ItemAt(i)); item->SetRequireUpdate(true); } } // Perform SetTo() on all the items that still exist as well as add // new items. bool itemModified = false; bool resize = false; TTeamMenuItem* teamItem = NULL; for (int32 i = 0; i < totalItems; i++) { if (teamMenu->SubmenuAt(i) == NULL) continue; teamItem = static_cast<TTeamMenuItem*>(teamMenu->ItemAt(i)); if (teamItem->IsExpanded()) { int32 teamCount = teamItem->Teams()->CountItems(); for (int32 j = 0; j < teamCount; j++) { // The following code is almost a copy/paste from // WindowMenu.cpp team_id theTeam = (addr_t)teamItem->Teams()->ItemAt(j); int32 count = 0; int32* tokens = get_token_list(theTeam, &count); for (int32 k = 0; k < count; k++) { client_window_info* wInfo = get_window_info(tokens[k]); if (wInfo == NULL) continue; if (TWindowMenu::WindowShouldBeListed(wInfo)) { // Check if we have a matching window item... item = teamItem->ExpandedWindowItem( wInfo->server_token); if (item != NULL) { item->SetTo(wInfo->name, wInfo->server_token, wInfo->is_mini, ((1 << current_workspace()) & wInfo->workspaces) != 0); if (strcasecmp(item->Label(), wInfo->name) > 0) item->SetLabel(wInfo->name); if (item->Modified()) itemModified = true; } else if (teamItem->IsExpanded()) { // Add the item item = new TWindowMenuItem(wInfo->name, wInfo->server_token, wInfo->is_mini, ((1 << current_workspace()) & wInfo->workspaces) != 0, false); item->SetExpanded(true); teamMenu->AddItem(item, TWindowMenuItem::InsertIndexFor( teamMenu, i + 1, item)); resize = true; } } free(wInfo); } free(tokens); } } } // Remove any remaining items which require an update. for (int32 i = 0; i < totalItems; i++) { if (!teamMenu->SubmenuAt(i)) { item = static_cast<TWindowMenuItem*>(teamMenu->ItemAt(i)); if (item && item->RequiresUpdate()) { item = static_cast<TWindowMenuItem*> (teamMenu->RemoveItem(i)); delete item; totalItems--; resize = true; } } } // If any of the WindowMenuItems changed state, we need to force a // repaint. if (itemModified || resize) { teamMenu->Invalidate(); if (resize) teamMenu->SizeWindow(1); } teamMenu->Window()->Unlock(); } sMonLocker.Unlock(); // sleep for a bit... snooze(150000); } return B_OK; }