void TExpandoMenuBar::AddTeam(team_id team, const char* signature) { int32 itemCount = CountItems(); for (int32 i = 0; i < itemCount; i++) { // Only add to team menu items TTeamMenuItem* item = dynamic_cast<TTeamMenuItem*>(ItemAt(i)); if (item != NULL && strcasecmp(item->Signature(), signature) == 0 && !(item->Teams()->HasItem((void*)(addr_t)team))) { item->Teams()->AddItem((void*)(addr_t)team); break; } } }
void TExpandoMenuBar::RemoveTeam(team_id team, bool partial) { TWindowMenuItem* windowItem = NULL; for (int32 i = CountItems() - 1; i >= 0; i--) { TTeamMenuItem* item = dynamic_cast<TTeamMenuItem*>(ItemAt(i)); if (item != NULL && item->Teams()->HasItem((void*)(addr_t)team)) { item->Teams()->RemoveItem(team); if (partial) return; BAutolock locker(sMonLocker); // make the update thread wait RemoveItem(i); if (item == fPreviousDragTargetItem) fPreviousDragTargetItem = NULL; if (item == fLastMousedOverItem) fLastMousedOverItem = NULL; if (item == fLastClickedItem) fLastClickedItem = NULL; delete item; while ((windowItem = dynamic_cast<TWindowMenuItem*>( ItemAt(i))) != NULL) { // Also remove window items (if there are any) RemoveItem(i); if (windowItem == fLastMousedOverItem) fLastMousedOverItem = NULL; if (windowItem == fLastClickedItem) fLastClickedItem = NULL; delete windowItem; } SizeWindow(-1); Window()->UpdateIfNeeded(); return; } } }
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; }
void TExpandoMenuBar::MouseDown(BPoint where) { BMessage *message = Window()->CurrentMessage(); // check for three finger salute, a.k.a. Vulcan Death Grip if (message != NULL) { int32 modifiers = 0; message->FindInt32("modifiers", &modifiers); if ((modifiers & B_COMMAND_KEY) != 0 && (modifiers & B_OPTION_KEY) != 0 && (modifiers & B_SHIFT_KEY) != 0 && !fBarView->Dragging()) { TTeamMenuItem *item = ItemAtPoint(where); if (item) { const BList *teams = item->Teams(); int32 teamCount = teams->CountItems(); team_id teamID; for (int32 team = 0; team < teamCount; team++) { teamID = (team_id)teams->ItemAt(team); kill_team(teamID); // remove the team immediately // from display RemoveTeam(teamID, false); } return; } } } const int32 count = CountItems(); // This feature is broken because the menu bar never receives // the second click #ifdef DOUBLECLICKBRINGSTOFRONT // doubleclick on an item brings all to front for (int32 i = fFirstApp; i < count; i++) { TTeamMenuItem *item = (TTeamMenuItem *)ItemAt(i); if (item->Frame().Contains(where)) { bigtime_t clickSpeed = 0; get_click_speed(&clickSpeed); if ( (fLastClickItem == i) && (clickSpeed > (system_time() - fLastClickTime)) ) { // bring this team's window to the front BMessage showMessage(M_BRING_TEAM_TO_FRONT); showMessage.AddInt32("itemIndex", i); Window()->PostMessage(&showMessage, this); return; } fLastClickItem = i; fLastClickTime = system_time(); break; } } #endif // control click - show all/hide all shortcut if (message != NULL) { int32 modifiers = 0; message->FindInt32("modifiers", &modifiers); if ((modifiers & B_CONTROL_KEY) != 0 && ! fBarView->Dragging()) { int32 lastApp = -1; // find the clicked item for (int32 i = fFirstApp; i < count; i++) { const TTeamMenuItem *item = (TTeamMenuItem *)ItemAt(i); // check if this item is really a team item (what a cruel way...) // "lastApp" will always point to the last application in // the list - the other entries might be windows (due to the team expander) if (item->Submenu()) lastApp = i; if (item->Frame().Contains(where)) { // show/hide item's teams BMessage showMessage((modifiers & B_SHIFT_KEY) != 0 ? M_MINIMIZE_TEAM : M_BRING_TEAM_TO_FRONT); showMessage.AddInt32("itemIndex", lastApp); Window()->PostMessage(&showMessage, this); return; } } } } // Check the bounds of the expand Team icon if (fShowTeamExpander && fVertical && !fBarView->Dragging()) { TTeamMenuItem *item = ItemAtPoint(where); if (item->Submenu()){ BRect expanderRect = item->ExpanderBounds(); if (expanderRect.Contains(where)) { item->ToggleExpandState(true); item->Draw(); // Absorb the message. return; } } } BMenuBar::MouseDown(where); }
void TExpandoMenuBar::MessageReceived(BMessage *message) { int32 index; TTeamMenuItem *item; switch (message->what) { case B_SOME_APP_LAUNCHED: { BList *teams = NULL; message->FindPointer("teams", (void **)&teams); BBitmap *icon = NULL; message->FindPointer("icon", (void **)&icon); const char *sig; if (message->FindString("sig", &sig) == B_OK &&strcasecmp(sig, TASK_BAR_MIME_SIG) == 0) { delete teams; delete icon; break; } uint32 flags; if (message->FindInt32("flags", ((int32*) &flags)) == B_OK && (flags & B_BACKGROUND_APP) != 0) { delete teams; delete icon; break; } const char *name = NULL; message->FindString("name", &name); AddTeam(teams, icon, strdup(name), strdup(sig)); break; } case msg_AddTeam: AddTeam(message->FindInt32("team"), message->FindString("sig")); break; case msg_RemoveTeam: { team_id team = -1; message->FindInt32("team", &team); RemoveTeam(team, true); break; } case B_SOME_APP_QUIT: { team_id team = -1; message->FindInt32("team", &team); RemoveTeam(team, false); break; } case M_MINIMIZE_TEAM: { index = message->FindInt32("itemIndex"); item = dynamic_cast<TTeamMenuItem *>(ItemAt(index)); if (item == NULL) break; TShowHideMenuItem::TeamShowHideCommon(B_MINIMIZE_WINDOW, item->Teams(), item->Menu()->ConvertToScreen(item->Frame()), true); break; } case M_BRING_TEAM_TO_FRONT: { index = message->FindInt32("itemIndex"); item = dynamic_cast<TTeamMenuItem *>(ItemAt(index)); if (item == NULL) break; TShowHideMenuItem::TeamShowHideCommon(B_BRING_TO_FRONT, item->Teams(), item->Menu()->ConvertToScreen(item->Frame()), true); break; } default: BMenuBar::MessageReceived(message); break; } }
void TExpandoMenuBar::MouseDown(BPoint where) { BMessage* message = Window()->CurrentMessage(); BMenuItem* menuItem; TTeamMenuItem* item = TeamItemAtPoint(where, &menuItem); // check for three finger salute, a.k.a. Vulcan Death Grip if (message != NULL && item != NULL && !fBarView->Dragging()) { int32 modifiers = 0; message->FindInt32("modifiers", &modifiers); if ((modifiers & B_COMMAND_KEY) != 0 && (modifiers & B_CONTROL_KEY) != 0 && (modifiers & B_SHIFT_KEY) != 0) { const BList* teams = item->Teams(); int32 teamCount = teams->CountItems(); team_id teamID; for (int32 team = 0; team < teamCount; team++) { teamID = (team_id)teams->ItemAt(team); kill_team(teamID); // remove the team immediately from display RemoveTeam(teamID, false); } return; } // control click - show all/hide all shortcut if ((modifiers & B_CONTROL_KEY) != 0) { // show/hide item's teams BMessage showMessage((modifiers & B_SHIFT_KEY) != 0 ? kMinimizeTeam : kBringTeamToFront); showMessage.AddInt32("itemIndex", IndexOf(item)); Window()->PostMessage(&showMessage, this); return; } // Check the bounds of the expand Team icon if (fShowTeamExpander && fVertical) { BRect expanderRect = item->ExpanderBounds(); if (expanderRect.Contains(where)) { // Let the update thread wait... BAutolock locker(sMonLocker); // Toggle the item item->ToggleExpandState(true); item->Draw(); // Absorb the message. return; } } // double-click on an item brings the team to front int32 clicks; if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1 && item == menuItem && item == fLastClickItem) { // activate this team be_roster->ActivateApp((team_id)item->Teams()->ItemAt(0)); return; } fLastClickItem = item; } BMenuBar::MouseDown(where); }
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; }
void TExpandoMenuBar::MouseDown(BPoint where) { BMessage* message = Window()->CurrentMessage(); BMenuItem* menuItem; TTeamMenuItem* item = TeamItemAtPoint(where, &menuItem); if (message == NULL || item == NULL || fBarView->Dragging()) { BMenuBar::MouseDown(where); return; } int32 modifiers = 0; message->FindInt32("modifiers", &modifiers); // check for three finger salute, a.k.a. Vulcan Death Grip if ((modifiers & B_COMMAND_KEY) != 0 && (modifiers & B_CONTROL_KEY) != 0 && (modifiers & B_SHIFT_KEY) != 0) { const BList* teams = item->Teams(); int32 teamCount = teams->CountItems(); team_id teamID; for (int32 team = 0; team < teamCount; team++) { teamID = (addr_t)teams->ItemAt(team); kill_team(teamID); RemoveTeam(teamID, false); // remove the team from display immediately } return; // absorb the message } // control click - show all/hide all shortcut if ((modifiers & B_CONTROL_KEY) != 0) { // show/hide item's teams BMessage showMessage((modifiers & B_SHIFT_KEY) != 0 ? kMinimizeTeam : kBringTeamToFront); showMessage.AddInt32("itemIndex", IndexOf(item)); Window()->PostMessage(&showMessage, this); return; // absorb the message } // check if within expander bounds to expand window items if (fVertical && static_cast<TBarApp*>(be_app)->Settings()->superExpando && item->ExpanderBounds().Contains(where)) { // start the animation here, finish on mouse up fLastClickedItem = item; MouseDownThread<TExpandoMenuBar>::TrackMouse(this, &TExpandoMenuBar::_DoneTracking, &TExpandoMenuBar::_Track); Invalidate(item->ExpanderBounds()); return; // absorb the message } // double-click on an item brings the team to front int32 clicks; if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1 && item == menuItem && item == fLastClickedItem) { be_roster->ActivateApp((addr_t)item->Teams()->ItemAt(0)); // activate this team return; // absorb the message } fLastClickedItem = item; BMenuBar::MouseDown(where); }
void TExpandoMenuBar::MessageReceived(BMessage* message) { int32 index; TTeamMenuItem* item; switch (message->what) { case B_SOME_APP_LAUNCHED: { BList* teams = NULL; message->FindPointer("teams", (void**)&teams); BBitmap* icon = NULL; message->FindPointer("icon", (void**)&icon); const char* signature = NULL; message->FindString("sig", &signature); uint32 flags = 0; message->FindInt32("flags", ((int32*) &flags)); const char* name = NULL; message->FindString("name", &name); AddTeam(teams, icon, strdup(name), strdup(signature)); break; } case B_MOUSE_WHEEL_CHANGED: { float deltaY = 0; message->FindFloat("be:wheel_delta_y", &deltaY); if (deltaY == 0) return; TInlineScrollView* scrollView = dynamic_cast<TInlineScrollView*>(Parent()); if (scrollView == NULL) return; float largeStep; float smallStep; scrollView->GetSteps(&smallStep, &largeStep); // pressing the option/command/control key scrolls faster if (modifiers() & (B_OPTION_KEY | B_COMMAND_KEY | B_CONTROL_KEY)) deltaY *= largeStep; else deltaY *= smallStep; scrollView->ScrollBy(deltaY); break; } case kAddTeam: AddTeam(message->FindInt32("team"), message->FindString("sig")); break; case kRemoveTeam: { team_id team = -1; message->FindInt32("team", &team); RemoveTeam(team, true); break; } case B_SOME_APP_QUIT: { team_id team = -1; message->FindInt32("team", &team); RemoveTeam(team, false); break; } case kMinimizeTeam: { index = message->FindInt32("itemIndex"); item = dynamic_cast<TTeamMenuItem*>(ItemAt(index)); if (item == NULL) break; TShowHideMenuItem::TeamShowHideCommon(B_MINIMIZE_WINDOW, item->Teams(), item->Menu()->ConvertToScreen(item->Frame()), true); break; } case kBringTeamToFront: { index = message->FindInt32("itemIndex"); item = dynamic_cast<TTeamMenuItem*>(ItemAt(index)); if (item == NULL) break; TShowHideMenuItem::TeamShowHideCommon(B_BRING_TO_FRONT, item->Teams(), item->Menu()->ConvertToScreen(item->Frame()), true); break; } default: BMenuBar::MessageReceived(message); break; } }