| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 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.h" | |
| 6 | |
| 7 #include "app/l10n_util.h" | |
| 8 #include "app/table_model_observer.h" | |
| 9 #include "base/stats_table.h" | |
| 10 #include "chrome/app/chrome_dll_resource.h" | |
| 11 #include "chrome/browser/browser_list.h" | |
| 12 #include "chrome/browser/browser_process.h" | |
| 13 #include "chrome/browser/browser_window.h" | |
| 14 #include "chrome/common/pref_names.h" | |
| 15 #include "chrome/common/pref_service.h" | |
| 16 #include "grit/chromium_strings.h" | |
| 17 #include "grit/generated_resources.h" | |
| 18 #include "grit/theme_resources.h" | |
| 19 #include "views/accelerator.h" | |
| 20 #include "views/background.h" | |
| 21 #include "views/controls/button/native_button.h" | |
| 22 #include "views/controls/link.h" | |
| 23 #include "views/controls/menu/menu.h" | |
| 24 #include "views/controls/table/group_table_view.h" | |
| 25 #include "views/controls/table/table_view_observer.h" | |
| 26 #include "views/standard_layout.h" | |
| 27 #include "views/widget/widget.h" | |
| 28 #include "views/window/dialog_delegate.h" | |
| 29 #include "views/window/window.h" | |
| 30 | |
| 31 // The task manager window default size. | |
| 32 static const int kDefaultWidth = 460; | |
| 33 static const int kDefaultHeight = 270; | |
| 34 | |
| 35 // An id for the most important column, made sufficiently large so as not to | |
| 36 // collide with anything else. | |
| 37 static const int64 kNuthMagicNumber = 1737350766; | |
| 38 static const int kBitMask = 0x7FFFFFFF; | |
| 39 static const int kGoatsTeleportedColumn = | |
| 40 (94024 * kNuthMagicNumber) & kBitMask; | |
| 41 | |
| 42 namespace { | |
| 43 | |
| 44 //////////////////////////////////////////////////////////////////////////////// | |
| 45 // TaskManagerTableModel class | |
| 46 //////////////////////////////////////////////////////////////////////////////// | |
| 47 | |
| 48 class TaskManagerTableModel : public views::GroupTableModel, | |
| 49 public TaskManagerModelObserver { | |
| 50 public: | |
| 51 explicit TaskManagerTableModel(TaskManagerModel* model) | |
| 52 : model_(model), | |
| 53 observer_(NULL) { | |
| 54 model->SetObserver(this); | |
| 55 } | |
| 56 ~TaskManagerTableModel() {} | |
| 57 | |
| 58 // GroupTableModel. | |
| 59 int RowCount(); | |
| 60 std::wstring GetText(int row, int column); | |
| 61 SkBitmap GetIcon(int row); | |
| 62 void GetGroupRangeForItem(int item, views::GroupRange* range); | |
| 63 void SetObserver(TableModelObserver* observer); | |
| 64 virtual int CompareValues(int row1, int row2, int column_id); | |
| 65 | |
| 66 // TaskManagerModelObserver. | |
| 67 virtual void OnModelChanged(); | |
| 68 virtual void OnItemsChanged(int start, int length); | |
| 69 virtual void OnItemsAdded(int start, int length); | |
| 70 virtual void OnItemsRemoved(int start, int length); | |
| 71 | |
| 72 private: | |
| 73 const TaskManagerModel* model_; | |
| 74 TableModelObserver* observer_; | |
| 75 }; | |
| 76 | |
| 77 int TaskManagerTableModel::RowCount() { | |
| 78 return model_->ResourceCount(); | |
| 79 } | |
| 80 | |
| 81 std::wstring TaskManagerTableModel::GetText(int row, int col_id) { | |
| 82 switch (col_id) { | |
| 83 case IDS_TASK_MANAGER_PAGE_COLUMN: // Process | |
| 84 return model_->GetResourceTitle(row); | |
| 85 | |
| 86 case IDS_TASK_MANAGER_NET_COLUMN: // Net | |
| 87 return model_->GetResourceNetworkUsage(row); | |
| 88 | |
| 89 case IDS_TASK_MANAGER_CPU_COLUMN: // CPU | |
| 90 if (!model_->IsResourceFirstInGroup(row)) | |
| 91 return std::wstring(); | |
| 92 return model_->GetResourceCPUUsage(row); | |
| 93 | |
| 94 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: // Memory | |
| 95 if (!model_->IsResourceFirstInGroup(row)) | |
| 96 return std::wstring(); | |
| 97 return model_->GetResourcePrivateMemory(row); | |
| 98 | |
| 99 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: // Memory | |
| 100 if (!model_->IsResourceFirstInGroup(row)) | |
| 101 return std::wstring(); | |
| 102 return model_->GetResourceSharedMemory(row); | |
| 103 | |
| 104 case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: // Memory | |
| 105 if (!model_->IsResourceFirstInGroup(row)) | |
| 106 return std::wstring(); | |
| 107 return model_->GetResourcePhysicalMemory(row); | |
| 108 | |
| 109 case IDS_TASK_MANAGER_PROCESS_ID_COLUMN: | |
| 110 if (!model_->IsResourceFirstInGroup(row)) | |
| 111 return std::wstring(); | |
| 112 return model_->GetResourceProcessId(row); | |
| 113 | |
| 114 case kGoatsTeleportedColumn: // Goats Teleported! | |
| 115 return model_->GetResourceGoatsTeleported(row); | |
| 116 | |
| 117 default: | |
| 118 return model_->GetResourceStatsValue(row, col_id); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 SkBitmap TaskManagerTableModel::GetIcon(int row) { | |
| 123 return model_->GetResourceIcon(row); | |
| 124 } | |
| 125 | |
| 126 void TaskManagerTableModel::GetGroupRangeForItem(int item, | |
| 127 views::GroupRange* range) { | |
| 128 std::pair<int, int> range_pair = model_->GetGroupRangeForResource(item); | |
| 129 range->start = range_pair.first; | |
| 130 range->length = range_pair.second; | |
| 131 } | |
| 132 | |
| 133 void TaskManagerTableModel::SetObserver(TableModelObserver* observer) { | |
| 134 observer_ = observer; | |
| 135 } | |
| 136 | |
| 137 int TaskManagerTableModel::CompareValues(int row1, int row2, int column_id) { | |
| 138 return model_->CompareValues(row1, row2, column_id); | |
| 139 } | |
| 140 | |
| 141 void TaskManagerTableModel::OnModelChanged() { | |
| 142 if (observer_) | |
| 143 observer_->OnModelChanged(); | |
| 144 } | |
| 145 | |
| 146 void TaskManagerTableModel::OnItemsChanged(int start, int length) { | |
| 147 if (observer_) | |
| 148 observer_->OnItemsChanged(start, length); | |
| 149 } | |
| 150 | |
| 151 void TaskManagerTableModel::OnItemsAdded(int start, int length) { | |
| 152 if (observer_) | |
| 153 observer_->OnItemsAdded(start, length); | |
| 154 } | |
| 155 | |
| 156 void TaskManagerTableModel::OnItemsRemoved(int start, int length) { | |
| 157 if (observer_) | |
| 158 observer_->OnItemsRemoved(start, length); | |
| 159 } | |
| 160 | |
| 161 //////////////////////////////////////////////////////////////////////////////// | |
| 162 // TaskManagerViewImpl class | |
| 163 // | |
| 164 // The view containing the different widgets. | |
| 165 // | |
| 166 //////////////////////////////////////////////////////////////////////////////// | |
| 167 | |
| 168 class TaskManagerViewImpl : public TaskManagerView, | |
| 169 public views::View, | |
| 170 public views::ButtonListener, | |
| 171 public views::DialogDelegate, | |
| 172 public views::TableViewObserver, | |
| 173 public views::LinkController, | |
| 174 public views::ContextMenuController, | |
| 175 public views::Menu::Delegate { | |
| 176 public: | |
| 177 TaskManagerViewImpl(TaskManager* task_manager, | |
| 178 TaskManagerModel* model); | |
| 179 virtual ~TaskManagerViewImpl(); | |
| 180 | |
| 181 void Init(); | |
| 182 virtual void Layout(); | |
| 183 virtual gfx::Size GetPreferredSize(); | |
| 184 virtual void ViewHierarchyChanged(bool is_add, views::View* parent, | |
| 185 views::View* child); | |
| 186 | |
| 187 // TaskManagerView | |
| 188 virtual void GetSelection(std::vector<int>* selection); | |
| 189 virtual void GetFocused(std::vector<int>* focused); | |
| 190 virtual void OpenWindow(); | |
| 191 virtual void ActivateWindow(); | |
| 192 virtual void CloseWindow(); | |
| 193 | |
| 194 // ButtonListener implementation. | |
| 195 virtual void ButtonPressed(views::Button* sender); | |
| 196 | |
| 197 // views::DialogDelegate | |
| 198 virtual bool CanResize() const; | |
| 199 virtual bool CanMaximize() const; | |
| 200 virtual bool ExecuteWindowsCommand(int command_id); | |
| 201 virtual std::wstring GetWindowTitle() const; | |
| 202 virtual std::wstring GetWindowName() const; | |
| 203 virtual int GetDialogButtons() const; | |
| 204 virtual void WindowClosing(); | |
| 205 virtual void DeleteDelegate(); | |
| 206 virtual views::View* GetContentsView(); | |
| 207 | |
| 208 // views::TableViewObserver implementation. | |
| 209 virtual void OnSelectionChanged(); | |
| 210 virtual void OnDoubleClick(); | |
| 211 virtual void OnKeyDown(unsigned short virtual_keycode); | |
| 212 | |
| 213 // views::LinkController implementation. | |
| 214 virtual void LinkActivated(views::Link* source, int event_flags); | |
| 215 | |
| 216 // Called by the column picker to pick up any new stat counters that | |
| 217 // may have appeared since last time. | |
| 218 void UpdateStatsCounters(); | |
| 219 | |
| 220 // Menu::Delegate | |
| 221 virtual void ShowContextMenu(views::View* source, | |
| 222 int x, | |
| 223 int y, | |
| 224 bool is_mouse_gesture); | |
| 225 virtual bool IsItemChecked(int id) const; | |
| 226 virtual void ExecuteCommand(int id); | |
| 227 | |
| 228 private: | |
| 229 // Initializes the state of the always-on-top setting as the window is shown. | |
| 230 void InitAlwaysOnTopState(); | |
| 231 | |
| 232 // Adds an always on top item to the window's system menu. | |
| 233 void AddAlwaysOnTopSystemMenuItem(); | |
| 234 | |
| 235 // Restores saved always on top state from a previous session. | |
| 236 bool GetSavedAlwaysOnTopState(bool* always_on_top) const; | |
| 237 | |
| 238 views::NativeButton* kill_button_; | |
| 239 views::Link* about_memory_link_; | |
| 240 views::GroupTableView* tab_table_; | |
| 241 | |
| 242 TaskManager* task_manager_; | |
| 243 | |
| 244 TaskManagerModel* model_; | |
| 245 | |
| 246 // all possible columns, not necessarily visible | |
| 247 std::vector<TableColumn> columns_; | |
| 248 | |
| 249 scoped_ptr<TaskManagerTableModel> table_model_; | |
| 250 | |
| 251 // True when the Task Manager window should be shown on top of other windows. | |
| 252 bool is_always_on_top_; | |
| 253 | |
| 254 // We need to own the text of the menu, the Windows API does not copy it. | |
| 255 std::wstring always_on_top_menu_text_; | |
| 256 | |
| 257 DISALLOW_COPY_AND_ASSIGN(TaskManagerViewImpl); | |
| 258 }; | |
| 259 | |
| 260 TaskManagerViewImpl::TaskManagerViewImpl(TaskManager* task_manager, | |
| 261 TaskManagerModel* model) | |
| 262 : task_manager_(task_manager), | |
| 263 model_(model), | |
| 264 is_always_on_top_(false) { | |
| 265 Init(); | |
| 266 } | |
| 267 | |
| 268 TaskManagerViewImpl::~TaskManagerViewImpl() { | |
| 269 // Delete child views now, while our table model still exists. | |
| 270 RemoveAllChildViews(true); | |
| 271 | |
| 272 // Prevent the table from accessing the model as part of its destruction, as | |
| 273 // the model might already be destroyed. | |
| 274 tab_table_->SetModel(NULL); | |
| 275 } | |
| 276 | |
| 277 void TaskManagerViewImpl::Init() { | |
| 278 table_model_.reset(new TaskManagerTableModel(model_)); | |
| 279 | |
| 280 columns_.push_back(TableColumn(IDS_TASK_MANAGER_PAGE_COLUMN, | |
| 281 TableColumn::LEFT, -1, 1)); | |
| 282 columns_.back().sortable = true; | |
| 283 columns_.push_back(TableColumn(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN, | |
| 284 TableColumn::RIGHT, -1, 0)); | |
| 285 columns_.back().sortable = true; | |
| 286 columns_.push_back(TableColumn(IDS_TASK_MANAGER_SHARED_MEM_COLUMN, | |
| 287 TableColumn::RIGHT, -1, 0)); | |
| 288 columns_.back().sortable = true; | |
| 289 columns_.push_back(TableColumn(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, | |
| 290 TableColumn::RIGHT, -1, 0)); | |
| 291 columns_.back().sortable = true; | |
| 292 columns_.push_back(TableColumn(IDS_TASK_MANAGER_CPU_COLUMN, | |
| 293 TableColumn::RIGHT, -1, 0)); | |
| 294 columns_.back().sortable = true; | |
| 295 columns_.push_back(TableColumn(IDS_TASK_MANAGER_NET_COLUMN, | |
| 296 TableColumn::RIGHT, -1, 0)); | |
| 297 columns_.back().sortable = true; | |
| 298 columns_.push_back(TableColumn(IDS_TASK_MANAGER_PROCESS_ID_COLUMN, | |
| 299 TableColumn::RIGHT, -1, 0)); | |
| 300 columns_.back().sortable = true; | |
| 301 | |
| 302 tab_table_ = new views::GroupTableView(table_model_.get(), columns_, | |
| 303 views::ICON_AND_TEXT, false, true, | |
| 304 true); | |
| 305 tab_table_->SetParentOwned(false); | |
| 306 | |
| 307 // Hide some columns by default | |
| 308 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PROCESS_ID_COLUMN, false); | |
| 309 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_SHARED_MEM_COLUMN, false); | |
| 310 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, false); | |
| 311 | |
| 312 UpdateStatsCounters(); | |
| 313 TableColumn col(kGoatsTeleportedColumn, L"Goats Teleported", | |
| 314 TableColumn::RIGHT, -1, 0); | |
| 315 col.sortable = true; | |
| 316 columns_.push_back(col); | |
| 317 tab_table_->AddColumn(col); | |
| 318 tab_table_->SetObserver(this); | |
| 319 SetContextMenuController(this); | |
| 320 kill_button_ = new views::NativeButton( | |
| 321 this, l10n_util::GetString(IDS_TASK_MANAGER_KILL)); | |
| 322 kill_button_->AddAccelerator(views::Accelerator('E', false, false, false)); | |
| 323 kill_button_->SetAccessibleKeyboardShortcut(L"E"); | |
| 324 about_memory_link_ = new views::Link( | |
| 325 l10n_util::GetString(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK)); | |
| 326 about_memory_link_->SetController(this); | |
| 327 | |
| 328 // Makes sure our state is consistent. | |
| 329 OnSelectionChanged(); | |
| 330 } | |
| 331 | |
| 332 void TaskManagerViewImpl::UpdateStatsCounters() { | |
| 333 StatsTable* stats = StatsTable::current(); | |
| 334 if (stats != NULL) { | |
| 335 int max = stats->GetMaxCounters(); | |
| 336 // skip the first row (it's header data) | |
| 337 for (int i = 1; i < max; i++) { | |
| 338 const char* row = stats->GetRowName(i); | |
| 339 if (row != NULL && row[0] != '\0' && !tab_table_->HasColumn(i)) { | |
| 340 // TODO(erikkay): Use l10n to get display names for stats. Right | |
| 341 // now we're just displaying the internal counter name. Perhaps | |
| 342 // stat names not in the string table would be filtered out. | |
| 343 // TODO(erikkay): Width is hard-coded right now, so many column | |
| 344 // names are clipped. | |
| 345 TableColumn col(i, ASCIIToWide(row), TableColumn::RIGHT, 90, 0); | |
| 346 col.sortable = true; | |
| 347 columns_.push_back(col); | |
| 348 tab_table_->AddColumn(col); | |
| 349 } | |
| 350 } | |
| 351 } | |
| 352 } | |
| 353 | |
| 354 void TaskManagerViewImpl::ViewHierarchyChanged(bool is_add, | |
| 355 views::View* parent, | |
| 356 views::View* child) { | |
| 357 // Since we want the Kill button and the Memory Details link to show up in | |
| 358 // the same visual row as the close button, which is provided by the | |
| 359 // framework, we must add the buttons to the non-client view, which is the | |
| 360 // parent of this view. Similarly, when we're removed from the view | |
| 361 // hierarchy, we must take care to clean up those items as well. | |
| 362 if (child == this) { | |
| 363 if (is_add) { | |
| 364 parent->AddChildView(kill_button_); | |
| 365 parent->AddChildView(about_memory_link_); | |
| 366 AddChildView(tab_table_); | |
| 367 } else { | |
| 368 parent->RemoveChildView(kill_button_); | |
| 369 parent->RemoveChildView(about_memory_link_); | |
| 370 } | |
| 371 } | |
| 372 } | |
| 373 | |
| 374 void TaskManagerViewImpl::Layout() { | |
| 375 // kPanelHorizMargin is too big. | |
| 376 const int kTableButtonSpacing = 12; | |
| 377 | |
| 378 gfx::Size size = kill_button_->GetPreferredSize(); | |
| 379 int prefered_width = size.width(); | |
| 380 int prefered_height = size.height(); | |
| 381 | |
| 382 tab_table_->SetBounds(x() + kPanelHorizMargin, | |
| 383 y() + kPanelVertMargin, | |
| 384 width() - 2 * kPanelHorizMargin, | |
| 385 height() - 2 * kPanelVertMargin - prefered_height); | |
| 386 | |
| 387 // y-coordinate of button top left. | |
| 388 gfx::Rect parent_bounds = GetParent()->GetLocalBounds(false); | |
| 389 int y_buttons = parent_bounds.bottom() - prefered_height - kButtonVEdgeMargin; | |
| 390 | |
| 391 kill_button_->SetBounds(x() + width() - prefered_width - kPanelHorizMargin, | |
| 392 y_buttons, | |
| 393 prefered_width, | |
| 394 prefered_height); | |
| 395 | |
| 396 size = about_memory_link_->GetPreferredSize(); | |
| 397 int link_prefered_width = size.width(); | |
| 398 int link_prefered_height = size.height(); | |
| 399 // center between the two buttons horizontally, and line up with | |
| 400 // bottom of buttons vertically. | |
| 401 int link_y_offset = std::max(0, prefered_height - link_prefered_height) / 2; | |
| 402 about_memory_link_->SetBounds( | |
| 403 x() + kPanelHorizMargin, | |
| 404 y_buttons + prefered_height - link_prefered_height - link_y_offset, | |
| 405 link_prefered_width, | |
| 406 link_prefered_height); | |
| 407 } | |
| 408 | |
| 409 gfx::Size TaskManagerViewImpl::GetPreferredSize() { | |
| 410 return gfx::Size(kDefaultWidth, kDefaultHeight); | |
| 411 } | |
| 412 | |
| 413 void TaskManagerViewImpl::GetSelection(std::vector<int>* selection) { | |
| 414 DCHECK(selection); | |
| 415 for (views::TableSelectionIterator iter = tab_table_->SelectionBegin(); | |
| 416 iter != tab_table_->SelectionEnd(); ++iter) { | |
| 417 // The TableView returns the selection starting from the end. | |
| 418 selection->insert(selection->begin(), *iter); | |
| 419 } | |
| 420 } | |
| 421 | |
| 422 void TaskManagerViewImpl::GetFocused(std::vector<int>* focused) { | |
| 423 DCHECK(focused); | |
| 424 int row_count = tab_table_->RowCount(); | |
| 425 for (int i = 0; i < row_count; ++i) { | |
| 426 // The TableView returns the selection starting from the end. | |
| 427 if (tab_table_->ItemHasTheFocus(i)) | |
| 428 focused->insert(focused->begin(), i); | |
| 429 } | |
| 430 } | |
| 431 | |
| 432 void TaskManagerViewImpl::OpenWindow() { | |
| 433 DCHECK(!window()); | |
| 434 views::Window::CreateChromeWindow(NULL, gfx::Rect(), this); | |
| 435 InitAlwaysOnTopState(); | |
| 436 model_->StartUpdating(); | |
| 437 window()->Show(); | |
| 438 } | |
| 439 | |
| 440 void TaskManagerViewImpl::ActivateWindow() { | |
| 441 DCHECK(window()); | |
| 442 window()->Activate(); | |
| 443 } | |
| 444 | |
| 445 void TaskManagerViewImpl::CloseWindow() { | |
| 446 if (!window()) | |
| 447 return; | |
| 448 // TODO(phajdan.jr): Destroy the window, not just hide it. | |
| 449 window()->HideWindow(); | |
| 450 } | |
| 451 | |
| 452 // ButtonListener implementation. | |
| 453 void TaskManagerViewImpl::ButtonPressed(views::Button* sender) { | |
| 454 if (sender == kill_button_) | |
| 455 task_manager_->KillSelectedProcesses(); | |
| 456 } | |
| 457 | |
| 458 // DialogDelegate implementation. | |
| 459 bool TaskManagerViewImpl::CanResize() const { | |
| 460 return true; | |
| 461 } | |
| 462 | |
| 463 bool TaskManagerViewImpl::CanMaximize() const { | |
| 464 return true; | |
| 465 } | |
| 466 | |
| 467 bool TaskManagerViewImpl::ExecuteWindowsCommand(int command_id) { | |
| 468 if (command_id == IDC_ALWAYS_ON_TOP) { | |
| 469 is_always_on_top_ = !is_always_on_top_; | |
| 470 | |
| 471 // Change the menu check state. | |
| 472 HMENU system_menu = GetSystemMenu(GetWindow()->GetNativeWindow(), FALSE); | |
| 473 MENUITEMINFO menu_info; | |
| 474 memset(&menu_info, 0, sizeof(MENUITEMINFO)); | |
| 475 menu_info.cbSize = sizeof(MENUITEMINFO); | |
| 476 BOOL r = GetMenuItemInfo(system_menu, IDC_ALWAYS_ON_TOP, | |
| 477 FALSE, &menu_info); | |
| 478 DCHECK(r); | |
| 479 menu_info.fMask = MIIM_STATE; | |
| 480 if (is_always_on_top_) | |
| 481 menu_info.fState = MFS_CHECKED; | |
| 482 r = SetMenuItemInfo(system_menu, IDC_ALWAYS_ON_TOP, FALSE, &menu_info); | |
| 483 | |
| 484 // Now change the actual window's behavior. | |
| 485 window()->SetIsAlwaysOnTop(is_always_on_top_); | |
| 486 | |
| 487 // Save the state. | |
| 488 if (g_browser_process->local_state()) { | |
| 489 DictionaryValue* window_preferences = | |
| 490 g_browser_process->local_state()->GetMutableDictionary( | |
| 491 GetWindowName().c_str()); | |
| 492 window_preferences->SetBoolean(L"always_on_top", is_always_on_top_); | |
| 493 } | |
| 494 return true; | |
| 495 } | |
| 496 return false; | |
| 497 } | |
| 498 | |
| 499 std::wstring TaskManagerViewImpl::GetWindowTitle() const { | |
| 500 return l10n_util::GetString(IDS_TASK_MANAGER_TITLE); | |
| 501 } | |
| 502 | |
| 503 std::wstring TaskManagerViewImpl::GetWindowName() const { | |
| 504 return prefs::kTaskManagerWindowPlacement; | |
| 505 } | |
| 506 | |
| 507 int TaskManagerViewImpl::GetDialogButtons() const { | |
| 508 return MessageBoxFlags::DIALOGBUTTON_NONE; | |
| 509 } | |
| 510 | |
| 511 void TaskManagerViewImpl::WindowClosing() { | |
| 512 task_manager_->OnWindowClosed(); | |
| 513 } | |
| 514 | |
| 515 void TaskManagerViewImpl::DeleteDelegate() { | |
| 516 ReleaseWindow(); | |
| 517 } | |
| 518 | |
| 519 views::View* TaskManagerViewImpl::GetContentsView() { | |
| 520 return this; | |
| 521 } | |
| 522 | |
| 523 // views::TableViewObserver implementation. | |
| 524 void TaskManagerViewImpl::OnSelectionChanged() { | |
| 525 kill_button_->SetEnabled(!task_manager_->BrowserProcessIsSelected() && | |
| 526 tab_table_->SelectedRowCount() > 0); | |
| 527 } | |
| 528 | |
| 529 void TaskManagerViewImpl::OnDoubleClick() { | |
| 530 task_manager_->ActivateFocusedTab(); | |
| 531 } | |
| 532 | |
| 533 void TaskManagerViewImpl::OnKeyDown(unsigned short virtual_keycode) { | |
| 534 if (virtual_keycode == VK_RETURN) | |
| 535 task_manager_->ActivateFocusedTab(); | |
| 536 } | |
| 537 | |
| 538 // views::LinkController implementation | |
| 539 void TaskManagerViewImpl::LinkActivated(views::Link* source, | |
| 540 int event_flags) { | |
| 541 DCHECK(source == about_memory_link_); | |
| 542 Browser* browser = BrowserList::GetLastActive(); | |
| 543 DCHECK(browser); | |
| 544 browser->OpenURL(GURL("about:memory"), GURL(), NEW_FOREGROUND_TAB, | |
| 545 PageTransition::LINK); | |
| 546 // In case the browser window is minimzed, show it. If this is an application | |
| 547 // or popup, we can only have one tab, hence we need to process this in a | |
| 548 // tabbed browser window. Currently, |browser| is pointing to the application, | |
| 549 // popup window. Therefore, we have to retrieve the last active tab again, | |
| 550 // since a new window has been used. | |
| 551 if (browser->type() & Browser::TYPE_APP_POPUP) { | |
| 552 browser = BrowserList::GetLastActive(); | |
| 553 DCHECK(browser); | |
| 554 } | |
| 555 browser->window()->Show(); | |
| 556 } | |
| 557 | |
| 558 void TaskManagerViewImpl::ShowContextMenu(views::View* source, | |
| 559 int x, | |
| 560 int y, | |
| 561 bool is_mouse_gesture) { | |
| 562 UpdateStatsCounters(); | |
| 563 scoped_ptr<views::Menu> menu(views::Menu::Create( | |
| 564 this, views::Menu::TOPLEFT, source->GetWidget()->GetNativeView())); | |
| 565 for (std::vector<TableColumn>::iterator i = | |
| 566 columns_.begin(); i != columns_.end(); ++i) { | |
| 567 menu->AppendMenuItem(i->id, i->title, views::Menu::CHECKBOX); | |
| 568 } | |
| 569 menu->RunMenuAt(x, y); | |
| 570 } | |
| 571 | |
| 572 bool TaskManagerViewImpl::IsItemChecked(int id) const { | |
| 573 return tab_table_->IsColumnVisible(id); | |
| 574 } | |
| 575 | |
| 576 void TaskManagerViewImpl::ExecuteCommand(int id) { | |
| 577 tab_table_->SetColumnVisibility(id, !tab_table_->IsColumnVisible(id)); | |
| 578 } | |
| 579 | |
| 580 void TaskManagerViewImpl::InitAlwaysOnTopState() { | |
| 581 is_always_on_top_ = false; | |
| 582 if (GetSavedAlwaysOnTopState(&is_always_on_top_)) | |
| 583 window()->SetIsAlwaysOnTop(is_always_on_top_); | |
| 584 AddAlwaysOnTopSystemMenuItem(); | |
| 585 } | |
| 586 | |
| 587 void TaskManagerViewImpl::AddAlwaysOnTopSystemMenuItem() { | |
| 588 // The Win32 API requires that we own the text. | |
| 589 always_on_top_menu_text_ = l10n_util::GetString(IDS_ALWAYS_ON_TOP); | |
| 590 | |
| 591 // Let's insert a menu to the window. | |
| 592 HMENU system_menu = ::GetSystemMenu(GetWindow()->GetNativeWindow(), FALSE); | |
| 593 int index = ::GetMenuItemCount(system_menu) - 1; | |
| 594 if (index < 0) { | |
| 595 // Paranoia check. | |
| 596 NOTREACHED(); | |
| 597 index = 0; | |
| 598 } | |
| 599 // First we add the separator. | |
| 600 MENUITEMINFO menu_info; | |
| 601 memset(&menu_info, 0, sizeof(MENUITEMINFO)); | |
| 602 menu_info.cbSize = sizeof(MENUITEMINFO); | |
| 603 menu_info.fMask = MIIM_FTYPE; | |
| 604 menu_info.fType = MFT_SEPARATOR; | |
| 605 ::InsertMenuItem(system_menu, index, TRUE, &menu_info); | |
| 606 | |
| 607 // Then the actual menu. | |
| 608 menu_info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_STATE; | |
| 609 menu_info.fType = MFT_STRING; | |
| 610 menu_info.fState = MFS_ENABLED; | |
| 611 if (is_always_on_top_) | |
| 612 menu_info.fState |= MFS_CHECKED; | |
| 613 menu_info.wID = IDC_ALWAYS_ON_TOP; | |
| 614 menu_info.dwTypeData = const_cast<wchar_t*>(always_on_top_menu_text_.c_str()); | |
| 615 ::InsertMenuItem(system_menu, index, TRUE, &menu_info); | |
| 616 } | |
| 617 | |
| 618 bool TaskManagerViewImpl::GetSavedAlwaysOnTopState(bool* always_on_top) const { | |
| 619 if (!g_browser_process->local_state()) | |
| 620 return false; | |
| 621 | |
| 622 const DictionaryValue* dictionary = | |
| 623 g_browser_process->local_state()->GetDictionary(GetWindowName().c_str()); | |
| 624 return dictionary && | |
| 625 dictionary->GetBoolean(L"always_on_top", always_on_top) && always_on_top; | |
| 626 } | |
| 627 | |
| 628 } // namespace | |
| 629 | |
| 630 void TaskManager::CreateView() { | |
| 631 DCHECK(!view_); | |
| 632 view_ = new TaskManagerViewImpl(this, model_.get()); | |
| 633 } | |
| OLD | NEW |