task_manager_view.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/task_manager/task_manager.h" 6 7#include "base/compiler_specific.h" 8#include "base/metrics/stats_table.h" 9#include "base/prefs/pref_service.h" 10#include "base/prefs/scoped_user_pref_update.h" 11#include "base/strings/utf_string_conversions.h" 12#include "chrome/app/chrome_command_ids.h" 13#include "chrome/browser/browser_process.h" 14#include "chrome/browser/ui/browser.h" 15#include "chrome/browser/ui/browser_list.h" 16#include "chrome/browser/ui/browser_window.h" 17#include "chrome/browser/ui/host_desktop.h" 18#include "chrome/browser/ui/views/browser_dialogs.h" 19#include "chrome/common/pref_names.h" 20#include "grit/chromium_strings.h" 21#include "grit/generated_resources.h" 22#include "grit/theme_resources.h" 23#include "ui/base/accelerators/accelerator.h" 24#include "ui/base/l10n/l10n_util.h" 25#include "ui/base/models/simple_menu_model.h" 26#include "ui/base/models/table_model.h" 27#include "ui/base/models/table_model_observer.h" 28#include "ui/events/event_constants.h" 29#include "ui/events/keycodes/keyboard_codes.h" 30#include "ui/gfx/canvas.h" 31#include "ui/views/context_menu_controller.h" 32#include "ui/views/controls/button/label_button.h" 33#include "ui/views/controls/link.h" 34#include "ui/views/controls/link_listener.h" 35#include "ui/views/controls/menu/menu_runner.h" 36#include "ui/views/controls/table/table_grouper.h" 37#include "ui/views/controls/table/table_view.h" 38#include "ui/views/controls/table/table_view_observer.h" 39#include "ui/views/layout/layout_constants.h" 40#include "ui/views/widget/widget.h" 41#include "ui/views/window/dialog_delegate.h" 42 43#if defined(USE_ASH) 44#include "ash/wm/window_util.h" 45#include "chrome/browser/ui/ash/launcher/launcher_item_util.h" 46#include "grit/ash_resources.h" 47#endif 48 49#if defined(OS_WIN) 50#include "chrome/browser/shell_integration.h" 51#include "ui/base/win/shell.h" 52#include "ui/views/win/hwnd_util.h" 53#include "win8/util/win8_util.h" 54#endif 55 56namespace { 57 58//////////////////////////////////////////////////////////////////////////////// 59// TaskManagerTableModel class 60//////////////////////////////////////////////////////////////////////////////// 61 62class TaskManagerTableModel 63 : public ui::TableModel, 64 public views::TableGrouper, 65 public TaskManagerModelObserver { 66 public: 67 explicit TaskManagerTableModel(TaskManagerModel* model) 68 : model_(model), 69 observer_(NULL) { 70 model_->AddObserver(this); 71 } 72 73 virtual ~TaskManagerTableModel() { 74 model_->RemoveObserver(this); 75 } 76 77 // TableModel overrides: 78 virtual int RowCount() OVERRIDE; 79 virtual base::string16 GetText(int row, int column) OVERRIDE; 80 virtual gfx::ImageSkia GetIcon(int row) OVERRIDE; 81 virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE; 82 virtual int CompareValues(int row1, int row2, int column_id) OVERRIDE; 83 84 // TableGrouper overrides: 85 virtual void GetGroupRange(int model_index, 86 views::GroupRange* range) OVERRIDE; 87 88 // TaskManagerModelObserver overrides: 89 virtual void OnModelChanged() OVERRIDE; 90 virtual void OnItemsChanged(int start, int length) OVERRIDE; 91 virtual void OnItemsAdded(int start, int length) OVERRIDE; 92 virtual void OnItemsRemoved(int start, int length) OVERRIDE; 93 94 private: 95 TaskManagerModel* model_; 96 ui::TableModelObserver* observer_; 97 98 DISALLOW_COPY_AND_ASSIGN(TaskManagerTableModel); 99}; 100 101int TaskManagerTableModel::RowCount() { 102 return model_->ResourceCount(); 103} 104 105base::string16 TaskManagerTableModel::GetText(int row, int col_id) { 106 return model_->GetResourceById(row, col_id); 107} 108 109gfx::ImageSkia TaskManagerTableModel::GetIcon(int row) { 110 return model_->GetResourceIcon(row); 111} 112 113void TaskManagerTableModel::SetObserver(ui::TableModelObserver* observer) { 114 observer_ = observer; 115} 116 117int TaskManagerTableModel::CompareValues(int row1, int row2, int column_id) { 118 return model_->CompareValues(row1, row2, column_id); 119} 120 121void TaskManagerTableModel::GetGroupRange(int model_index, 122 views::GroupRange* range) { 123 TaskManagerModel::GroupRange range_pair = 124 model_->GetGroupRangeForResource(model_index); 125 range->start = range_pair.first; 126 range->length = range_pair.second; 127} 128 129void TaskManagerTableModel::OnModelChanged() { 130 if (observer_) 131 observer_->OnModelChanged(); 132} 133 134void TaskManagerTableModel::OnItemsChanged(int start, int length) { 135 if (observer_) 136 observer_->OnItemsChanged(start, length); 137} 138 139void TaskManagerTableModel::OnItemsAdded(int start, int length) { 140 if (observer_) 141 observer_->OnItemsAdded(start, length); 142} 143 144void TaskManagerTableModel::OnItemsRemoved(int start, int length) { 145 if (observer_) 146 observer_->OnItemsRemoved(start, length); 147} 148 149// The Task manager UI container. 150class TaskManagerView : public views::ButtonListener, 151 public views::DialogDelegateView, 152 public views::TableViewObserver, 153 public views::LinkListener, 154 public views::ContextMenuController, 155 public ui::SimpleMenuModel::Delegate { 156 public: 157 explicit TaskManagerView(chrome::HostDesktopType desktop_type); 158 virtual ~TaskManagerView(); 159 160 // Shows the Task manager window, or re-activates an existing one. 161 static void Show(Browser* browser); 162 163 // views::View: 164 virtual void Layout() OVERRIDE; 165 virtual gfx::Size GetPreferredSize() OVERRIDE; 166 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; 167 virtual void ViewHierarchyChanged( 168 const ViewHierarchyChangedDetails& details) OVERRIDE; 169 170 // views::ButtonListener: 171 virtual void ButtonPressed(views::Button* sender, 172 const ui::Event& event) OVERRIDE; 173 174 // views::DialogDelegateView: 175 virtual bool CanResize() const OVERRIDE; 176 virtual bool CanMaximize() const OVERRIDE; 177 virtual bool ExecuteWindowsCommand(int command_id) OVERRIDE; 178 virtual base::string16 GetWindowTitle() const OVERRIDE; 179 virtual std::string GetWindowName() const OVERRIDE; 180 virtual int GetDialogButtons() const OVERRIDE; 181 virtual void WindowClosing() OVERRIDE; 182 virtual bool UseNewStyleForThisDialog() const OVERRIDE; 183 184 // views::TableViewObserver: 185 virtual void OnSelectionChanged() OVERRIDE; 186 virtual void OnDoubleClick() OVERRIDE; 187 virtual void OnKeyDown(ui::KeyboardCode keycode) OVERRIDE; 188 189 // views::LinkListener: 190 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 191 192 // Called by the column picker to pick up any new stat counters that 193 // may have appeared since last time. 194 void UpdateStatsCounters(); 195 196 // views::ContextMenuController: 197 virtual void ShowContextMenuForView(views::View* source, 198 const gfx::Point& point, 199 ui::MenuSourceType source_type) OVERRIDE; 200 201 // ui::SimpleMenuModel::Delegate: 202 virtual bool IsCommandIdChecked(int id) const OVERRIDE; 203 virtual bool IsCommandIdEnabled(int id) const OVERRIDE; 204 virtual bool GetAcceleratorForCommandId( 205 int command_id, 206 ui::Accelerator* accelerator) OVERRIDE; 207 virtual void ExecuteCommand(int id, int event_flags) OVERRIDE; 208 209 private: 210 // Creates the child controls. 211 void Init(); 212 213 // Initializes the state of the always-on-top setting as the window is shown. 214 void InitAlwaysOnTopState(); 215 216 // Activates the tab associated with the focused row. 217 void ActivateFocusedTab(); 218 219 // Restores saved always on top state from a previous session. 220 bool GetSavedAlwaysOnTopState(bool* always_on_top) const; 221 222 views::LabelButton* kill_button_; 223 views::Link* about_memory_link_; 224 views::TableView* tab_table_; 225 views::View* tab_table_parent_; 226 227 TaskManager* task_manager_; 228 229 TaskManagerModel* model_; 230 231 // all possible columns, not necessarily visible 232 std::vector<ui::TableColumn> columns_; 233 234 scoped_ptr<TaskManagerTableModel> table_model_; 235 236 // True when the Task Manager window should be shown on top of other windows. 237 bool is_always_on_top_; 238 239 // The host desktop type this task manager belongs to. 240 const chrome::HostDesktopType desktop_type_; 241 242 // We need to own the text of the menu, the Windows API does not copy it. 243 base::string16 always_on_top_menu_text_; 244 245 // An open Task manager window. There can only be one open at a time. This 246 // is reset to NULL when the window is closed. 247 static TaskManagerView* instance_; 248 249 scoped_ptr<views::MenuRunner> menu_runner_; 250 251 DISALLOW_COPY_AND_ASSIGN(TaskManagerView); 252}; 253 254// static 255TaskManagerView* TaskManagerView::instance_ = NULL; 256 257 258TaskManagerView::TaskManagerView(chrome::HostDesktopType desktop_type) 259 : kill_button_(NULL), 260 about_memory_link_(NULL), 261 tab_table_(NULL), 262 tab_table_parent_(NULL), 263 task_manager_(TaskManager::GetInstance()), 264 model_(TaskManager::GetInstance()->model()), 265 is_always_on_top_(false), 266 desktop_type_(desktop_type) { 267 Init(); 268} 269 270TaskManagerView::~TaskManagerView() { 271 // Delete child views now, while our table model still exists. 272 RemoveAllChildViews(true); 273} 274 275void TaskManagerView::Init() { 276 table_model_.reset(new TaskManagerTableModel(model_)); 277 278 // Page column has no header label. 279 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_TASK_COLUMN, 280 ui::TableColumn::LEFT, -1, 1)); 281 columns_.back().sortable = true; 282 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PROFILE_NAME_COLUMN, 283 ui::TableColumn::LEFT, -1, 0)); 284 columns_.back().sortable = true; 285 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN, 286 ui::TableColumn::RIGHT, -1, 0)); 287 columns_.back().sortable = true; 288 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_SHARED_MEM_COLUMN, 289 ui::TableColumn::RIGHT, -1, 0)); 290 columns_.back().sortable = true; 291 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, 292 ui::TableColumn::RIGHT, -1, 0)); 293 columns_.back().sortable = true; 294 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_CPU_COLUMN, 295 ui::TableColumn::RIGHT, -1, 0)); 296 columns_.back().sortable = true; 297 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_NET_COLUMN, 298 ui::TableColumn::RIGHT, -1, 0)); 299 columns_.back().sortable = true; 300 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PROCESS_ID_COLUMN, 301 ui::TableColumn::RIGHT, -1, 0)); 302 columns_.back().sortable = true; 303#if defined(OS_WIN) 304 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_GDI_HANDLES_COLUMN, 305 ui::TableColumn::RIGHT, -1, 0)); 306 columns_.back().sortable = true; 307 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_USER_HANDLES_COLUMN, 308 ui::TableColumn::RIGHT, -1, 0)); 309 columns_.back().sortable = true; 310#endif 311 columns_.push_back(ui::TableColumn( 312 IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN, 313 ui::TableColumn::RIGHT, -1, 0)); 314 columns_.back().sortable = true; 315 columns_.push_back(ui::TableColumn( 316 IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN, 317 ui::TableColumn::RIGHT, -1, 0)); 318 columns_.back().sortable = true; 319 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN, 320 ui::TableColumn::RIGHT, -1, 0)); 321 columns_.back().sortable = true; 322 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_FPS_COLUMN, 323 ui::TableColumn::RIGHT, -1, 0)); 324 columns_.back().sortable = true; 325 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN, 326 ui::TableColumn::RIGHT, -1, 0)); 327 columns_.back().sortable = true; 328 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN, 329 ui::TableColumn::RIGHT, -1, 0)); 330 columns_.back().sortable = true; 331 columns_.push_back(ui::TableColumn( 332 IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN, 333 ui::TableColumn::RIGHT, -1, 0)); 334 columns_.back().sortable = true; 335 columns_.push_back( 336 ui::TableColumn(IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN, 337 ui::TableColumn::RIGHT, -1, 0)); 338 columns_.back().sortable = true; 339 340 tab_table_ = new views::TableView( 341 table_model_.get(), columns_, views::ICON_AND_TEXT, false); 342 tab_table_->SetGrouper(table_model_.get()); 343 344 // Hide some columns by default 345 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PROFILE_NAME_COLUMN, false); 346 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_SHARED_MEM_COLUMN, false); 347 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, false); 348 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN, 349 false); 350 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN, 351 false); 352 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN, 353 false); 354 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN, 355 false); 356 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN, 357 false); 358 tab_table_->SetColumnVisibility( 359 IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN, false); 360 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN, 361 false); 362 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_GDI_HANDLES_COLUMN, false); 363 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_USER_HANDLES_COLUMN, false); 364 365 UpdateStatsCounters(); 366 tab_table_->SetObserver(this); 367 tab_table_->set_context_menu_controller(this); 368 set_context_menu_controller(this); 369 kill_button_ = new views::LabelButton(this, 370 l10n_util::GetStringUTF16(IDS_TASK_MANAGER_KILL)); 371 kill_button_->SetStyle(views::Button::STYLE_BUTTON); 372 about_memory_link_ = new views::Link( 373 l10n_util::GetStringUTF16(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK)); 374 about_memory_link_->set_listener(this); 375 376 // Makes sure our state is consistent. 377 OnSelectionChanged(); 378 379 ui::Accelerator ctrl_w(ui::VKEY_W, ui::EF_CONTROL_DOWN); 380 AddAccelerator(ctrl_w); 381} 382 383void TaskManagerView::UpdateStatsCounters() { 384 base::StatsTable* stats = base::StatsTable::current(); 385 if (stats != NULL) { 386 int max = stats->GetMaxCounters(); 387 // skip the first row (it's header data) 388 for (int i = 1; i < max; i++) { 389 const char* row = stats->GetRowName(i); 390 if (row != NULL && row[0] != '\0' && !tab_table_->HasColumn(i)) { 391 // TODO(erikkay): Use l10n to get display names for stats. Right 392 // now we're just displaying the internal counter name. Perhaps 393 // stat names not in the string table would be filtered out. 394 ui::TableColumn col; 395 col.id = i; 396 col.title = base::ASCIIToUTF16(row); 397 col.alignment = ui::TableColumn::RIGHT; 398 // TODO(erikkay): Width is hard-coded right now, so many column 399 // names are clipped. 400 col.width = 90; 401 col.sortable = true; 402 columns_.push_back(col); 403 tab_table_->AddColumn(col); 404 } 405 } 406 } 407} 408 409void TaskManagerView::ViewHierarchyChanged( 410 const ViewHierarchyChangedDetails& details) { 411 // Since we want the Kill button and the Memory Details link to show up in 412 // the same visual row as the close button, which is provided by the 413 // framework, we must add the buttons to the non-client view, which is the 414 // parent of this view. Similarly, when we're removed from the view 415 // hierarchy, we must take care to clean up those items as well. 416 if (details.child == this) { 417 if (details.is_add) { 418 details.parent->AddChildView(about_memory_link_); 419 details.parent->AddChildView(kill_button_); 420 tab_table_parent_ = tab_table_->CreateParentIfNecessary(); 421 AddChildView(tab_table_parent_); 422 } else { 423 details.parent->RemoveChildView(kill_button_); 424 details.parent->RemoveChildView(about_memory_link_); 425 } 426 } 427} 428 429void TaskManagerView::Layout() { 430 gfx::Size size = kill_button_->GetPreferredSize(); 431 gfx::Rect parent_bounds = parent()->GetContentsBounds(); 432 const int horizontal_margin = views::kPanelHorizMargin; 433 const int vertical_margin = views::kButtonVEdgeMargin; 434 int x = width() - size.width() - horizontal_margin; 435 int y_buttons = parent_bounds.bottom() - size.height() - vertical_margin; 436 kill_button_->SetBounds(x, y_buttons, size.width(), size.height()); 437 438 size = about_memory_link_->GetPreferredSize(); 439 about_memory_link_->SetBounds( 440 horizontal_margin, 441 y_buttons + (kill_button_->height() - size.height()) / 2, 442 size.width(), size.height()); 443 444 gfx::Rect rect = GetLocalBounds(); 445 rect.Inset(horizontal_margin, views::kPanelVertMargin); 446 rect.Inset(0, 0, 0, 447 kill_button_->height() + views::kUnrelatedControlVerticalSpacing); 448 tab_table_parent_->SetBoundsRect(rect); 449} 450 451gfx::Size TaskManagerView::GetPreferredSize() { 452 return gfx::Size(460, 270); 453} 454 455bool TaskManagerView::AcceleratorPressed(const ui::Accelerator& accelerator) { 456 DCHECK_EQ(ui::VKEY_W, accelerator.key_code()); 457 DCHECK_EQ(ui::EF_CONTROL_DOWN, accelerator.modifiers()); 458 GetWidget()->Close(); 459 return true; 460} 461 462// static 463void TaskManagerView::Show(Browser* browser) { 464#if defined(OS_WIN) 465 // In Windows Metro it's not good to open this native window. 466 DCHECK(!win8::IsSingleWindowMetroMode()); 467#endif 468 // In ash we can come here through the ChromeShellDelegate. If there is no 469 // browser window at that time of the call, browser could be passed as NULL. 470 const chrome::HostDesktopType desktop_type = 471 browser ? browser->host_desktop_type() : chrome::HOST_DESKTOP_TYPE_ASH; 472 473 if (instance_) { 474 // If there's a Task manager window open already, just activate it. 475 instance_->GetWidget()->Activate(); 476 return; 477 } 478 instance_ = new TaskManagerView(desktop_type); 479 gfx::NativeWindow window = 480 browser ? browser->window()->GetNativeWindow() : NULL; 481#if defined(USE_ASH) 482 if (!window) 483 window = ash::wm::GetActiveWindow(); 484#endif 485 DialogDelegate::CreateDialogWidget(instance_, window, NULL); 486 instance_->InitAlwaysOnTopState(); 487 instance_->model_->StartUpdating(); 488#if defined(OS_WIN) 489 // Set the app id for the task manager to the app id of its parent browser. If 490 // no parent is specified, the app id will default to that of the initial 491 // process. 492 if (browser) { 493 ui::win::SetAppIdForWindow( 494 ShellIntegration::GetChromiumModelIdForProfile( 495 browser->profile()->GetPath()), 496 views::HWNDForWidget(instance_->GetWidget())); 497 } 498#endif 499 instance_->GetWidget()->Show(); 500 501 // Set the initial focus to the list of tasks. 502 views::FocusManager* focus_manager = instance_->GetFocusManager(); 503 if (focus_manager) 504 focus_manager->SetFocusedView(instance_->tab_table_); 505 506#if defined(USE_ASH) 507 CreateShelfItemForDialog(IDR_AURA_LAUNCHER_ICON_TASK_MANAGER, 508 instance_->GetWidget()->GetNativeWindow()); 509#endif 510} 511 512// ButtonListener implementation. 513void TaskManagerView::ButtonPressed( 514 views::Button* sender, 515 const ui::Event& event) { 516 typedef ui::ListSelectionModel::SelectedIndices SelectedIndices; 517 DCHECK_EQ(kill_button_, sender); 518 SelectedIndices selection(tab_table_->selection_model().selected_indices()); 519 for (SelectedIndices::const_reverse_iterator i = selection.rbegin(); 520 i != selection.rend(); ++i) { 521 task_manager_->KillProcess(*i); 522 } 523} 524 525// DialogDelegate implementation. 526bool TaskManagerView::CanResize() const { 527 return true; 528} 529 530bool TaskManagerView::CanMaximize() const { 531 return true; 532} 533 534bool TaskManagerView::ExecuteWindowsCommand(int command_id) { 535 return false; 536} 537 538base::string16 TaskManagerView::GetWindowTitle() const { 539 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_TITLE); 540} 541 542std::string TaskManagerView::GetWindowName() const { 543 return prefs::kTaskManagerWindowPlacement; 544} 545 546int TaskManagerView::GetDialogButtons() const { 547 return ui::DIALOG_BUTTON_NONE; 548} 549 550void TaskManagerView::WindowClosing() { 551 // Now that the window is closed, we can allow a new one to be opened. 552 // (WindowClosing comes in asynchronously from the call to Close() and we 553 // may have already opened a new instance). 554 if (instance_ == this) 555 instance_ = NULL; 556 task_manager_->OnWindowClosed(); 557} 558 559bool TaskManagerView::UseNewStyleForThisDialog() const { 560 return false; 561} 562 563// views::TableViewObserver implementation. 564void TaskManagerView::OnSelectionChanged() { 565 const ui::ListSelectionModel::SelectedIndices& selection( 566 tab_table_->selection_model().selected_indices()); 567 bool selection_contains_browser_process = false; 568 for (size_t i = 0; i < selection.size(); ++i) { 569 if (task_manager_->IsBrowserProcess(selection[i])) { 570 selection_contains_browser_process = true; 571 break; 572 } 573 } 574 kill_button_->SetEnabled(!selection_contains_browser_process && 575 !selection.empty()); 576} 577 578void TaskManagerView::OnDoubleClick() { 579 ActivateFocusedTab(); 580} 581 582void TaskManagerView::OnKeyDown(ui::KeyboardCode keycode) { 583 if (keycode == ui::VKEY_RETURN) 584 ActivateFocusedTab(); 585} 586 587void TaskManagerView::LinkClicked(views::Link* source, int event_flags) { 588 DCHECK_EQ(about_memory_link_, source); 589 task_manager_->OpenAboutMemory(desktop_type_); 590} 591 592void TaskManagerView::ShowContextMenuForView(views::View* source, 593 const gfx::Point& point, 594 ui::MenuSourceType source_type) { 595 UpdateStatsCounters(); 596 ui::SimpleMenuModel menu_model(this); 597 for (std::vector<ui::TableColumn>::iterator i(columns_.begin()); 598 i != columns_.end(); ++i) { 599 menu_model.AddCheckItem(i->id, l10n_util::GetStringUTF16(i->id)); 600 } 601 menu_runner_.reset(new views::MenuRunner(&menu_model)); 602 if (menu_runner_->RunMenuAt(GetWidget(), NULL, gfx::Rect(point, gfx::Size()), 603 views::MenuItemView::TOPLEFT, source_type, 604 views::MenuRunner::CONTEXT_MENU) == 605 views::MenuRunner::MENU_DELETED) 606 return; 607} 608 609bool TaskManagerView::IsCommandIdChecked(int id) const { 610 return tab_table_->IsColumnVisible(id); 611} 612 613bool TaskManagerView::IsCommandIdEnabled(int id) const { 614 return true; 615} 616 617bool TaskManagerView::GetAcceleratorForCommandId( 618 int command_id, 619 ui::Accelerator* accelerator) { 620 return false; 621} 622 623void TaskManagerView::ExecuteCommand(int id, int event_flags) { 624 tab_table_->SetColumnVisibility(id, !tab_table_->IsColumnVisible(id)); 625} 626 627void TaskManagerView::InitAlwaysOnTopState() { 628 is_always_on_top_ = false; 629 if (GetSavedAlwaysOnTopState(&is_always_on_top_)) 630 GetWidget()->SetAlwaysOnTop(is_always_on_top_); 631} 632 633void TaskManagerView::ActivateFocusedTab() { 634 const int active_row = tab_table_->selection_model().active(); 635 if (active_row != -1) 636 task_manager_->ActivateProcess(active_row); 637} 638 639bool TaskManagerView::GetSavedAlwaysOnTopState(bool* always_on_top) const { 640 if (!g_browser_process->local_state()) 641 return false; 642 643 const base::DictionaryValue* dictionary = 644 g_browser_process->local_state()->GetDictionary(GetWindowName().c_str()); 645 return dictionary && 646 dictionary->GetBoolean("always_on_top", always_on_top) && always_on_top; 647} 648 649} // namespace 650 651namespace chrome { 652 653// Declared in browser_dialogs.h so others don't need to depend on our header. 654void ShowTaskManager(Browser* browser) { 655 TaskManagerView::Show(browser); 656} 657 658} // namespace chrome 659