OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/gtk/task_manager_gtk.h" | 5 #include "chrome/browser/gtk/task_manager_gtk.h" |
6 | 6 |
7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "app/l10n_util.h" | 12 #include "app/l10n_util.h" |
13 #include "base/gfx/gtk_util.h" | 13 #include "base/gfx/gtk_util.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "chrome/browser/browser_list.h" | 15 #include "chrome/browser/browser_list.h" |
16 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
17 #include "chrome/browser/browser_window.h" | 17 #include "chrome/browser/browser_window.h" |
18 #include "chrome/browser/gtk/gtk_chrome_link_button.h" | 18 #include "chrome/browser/gtk/gtk_chrome_link_button.h" |
19 #include "chrome/browser/gtk/menu_gtk.h" | 19 #include "chrome/browser/gtk/menu_gtk.h" |
| 20 #include "chrome/common/gtk_tree.h" |
20 #include "chrome/common/gtk_util.h" | 21 #include "chrome/common/gtk_util.h" |
21 #include "chrome/common/pref_names.h" | 22 #include "chrome/common/pref_names.h" |
22 #include "chrome/common/pref_service.h" | 23 #include "chrome/common/pref_service.h" |
23 #include "grit/chromium_strings.h" | 24 #include "grit/chromium_strings.h" |
24 #include "grit/generated_resources.h" | 25 #include "grit/generated_resources.h" |
25 | 26 |
26 namespace { | 27 namespace { |
27 | 28 |
28 // The task manager window default size. | 29 // The task manager window default size. |
29 const int kDefaultWidth = 460; | 30 const int kDefaultWidth = 460; |
(...skipping 93 matching lines...) Loading... |
123 gtk_tree_view_column_set_title(column, | 124 gtk_tree_view_column_set_title(column, |
124 l10n_util::GetStringUTF8(resid).c_str()); | 125 l10n_util::GetStringUTF8(resid).c_str()); |
125 GtkCellRenderer* image_renderer = gtk_cell_renderer_pixbuf_new(); | 126 GtkCellRenderer* image_renderer = gtk_cell_renderer_pixbuf_new(); |
126 gtk_tree_view_column_pack_start(column, image_renderer, FALSE); | 127 gtk_tree_view_column_pack_start(column, image_renderer, FALSE); |
127 gtk_tree_view_column_add_attribute(column, image_renderer, | 128 gtk_tree_view_column_add_attribute(column, image_renderer, |
128 "pixbuf", kTaskManagerIcon); | 129 "pixbuf", kTaskManagerIcon); |
129 GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new(); | 130 GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new(); |
130 gtk_tree_view_column_pack_start(column, text_renderer, TRUE); | 131 gtk_tree_view_column_pack_start(column, text_renderer, TRUE); |
131 gtk_tree_view_column_add_attribute(column, text_renderer, "text", colid); | 132 gtk_tree_view_column_add_attribute(column, text_renderer, "text", colid); |
132 gtk_tree_view_column_set_resizable(column, TRUE); | 133 gtk_tree_view_column_set_resizable(column, TRUE); |
| 134 // This is temporary: we'll turn expanding off after getting the size. |
| 135 gtk_tree_view_column_set_expand(column, TRUE); |
133 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | 136 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); |
134 } | 137 } |
135 | 138 |
136 // Inserts a column with a column id of |colid| and |name|. | 139 // Inserts a column with a column id of |colid| and |name|. |
137 void TreeViewInsertColumnWithName(GtkWidget* treeview, | 140 void TreeViewInsertColumnWithName(GtkWidget* treeview, |
138 TaskManagerColumn colid, const char* name) { | 141 TaskManagerColumn colid, const char* name) { |
139 GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); | 142 GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); |
140 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1, | 143 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1, |
141 name, renderer, | 144 name, renderer, |
142 "text", colid, | 145 "text", colid, |
143 NULL); | 146 NULL); |
144 GtkTreeViewColumn* column = gtk_tree_view_get_column( | 147 GtkTreeViewColumn* column = gtk_tree_view_get_column( |
145 GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid)); | 148 GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid)); |
146 gtk_tree_view_column_set_resizable(column, TRUE); | 149 gtk_tree_view_column_set_resizable(column, TRUE); |
147 } | 150 } |
148 | 151 |
149 // Loads the column name from |resid| and uses the corresponding | 152 // Loads the column name from |resid| and uses the corresponding |
150 // TaskManagerColumn value as the column id to insert into the treeview. | 153 // TaskManagerColumn value as the column id to insert into the treeview. |
151 void TreeViewInsertColumn(GtkWidget* treeview, int resid) { | 154 void TreeViewInsertColumn(GtkWidget* treeview, int resid) { |
152 TreeViewInsertColumnWithName(treeview, TaskManagerResourceIDToColumnID(resid), | 155 TreeViewInsertColumnWithName(treeview, TaskManagerResourceIDToColumnID(resid), |
153 l10n_util::GetStringUTF8(resid).c_str()); | 156 l10n_util::GetStringUTF8(resid).c_str()); |
154 } | 157 } |
155 | 158 |
156 // Get the row number corresponding to |path|. | 159 // Set the current width of the column without forcing a minimum width as |
157 gint GetRowNumForPath(GtkTreePath* path) { | 160 // gtk_tree_view_column_set_fixed_width() would. This would basically be |
158 gint* indices = gtk_tree_path_get_indices(path); | 161 // gtk_tree_view_column_set_width() except that there is no such function. |
159 if (!indices) { | 162 void TreeViewColumnSetWidth(GtkTreeViewColumn* column, gint width) { |
160 NOTREACHED(); | 163 column->width = width; |
161 return -1; | 164 column->resized_width = width; |
162 } | 165 column->use_resized_width = TRUE; |
163 return indices[0]; | 166 // Needed for use_resized_width to be effective. |
| 167 gtk_widget_queue_resize(column->tree_view); |
164 } | 168 } |
165 | 169 |
166 } // namespace | 170 } // namespace |
167 | 171 |
168 class TaskManagerGtk::ContextMenuController : public MenuGtk::Delegate { | 172 class TaskManagerGtk::ContextMenuController : public MenuGtk::Delegate { |
169 public: | 173 public: |
170 explicit ContextMenuController(TaskManagerGtk* task_manager) | 174 explicit ContextMenuController(TaskManagerGtk* task_manager) |
171 : task_manager_(task_manager) { | 175 : task_manager_(task_manager) { |
172 menu_.reset(new MenuGtk(this, false)); | 176 menu_.reset(new MenuGtk(this, false)); |
173 for (int i = kTaskManagerPage; i < kTaskManagerColumnCount - 1; i++) { | 177 for (int i = kTaskManagerPage; i < kTaskManagerColumnCount - 1; i++) { |
(...skipping 211 matching lines...) Loading... |
385 | 389 |
386 gtk_container_add(GTK_CONTAINER(scrolled), treeview_); | 390 gtk_container_add(GTK_CONTAINER(scrolled), treeview_); |
387 | 391 |
388 SetInitialDialogSize(); | 392 SetInitialDialogSize(); |
389 gtk_widget_show_all(dialog_); | 393 gtk_widget_show_all(dialog_); |
390 | 394 |
391 model_->AddObserver(this); | 395 model_->AddObserver(this); |
392 } | 396 } |
393 | 397 |
394 void TaskManagerGtk::SetInitialDialogSize() { | 398 void TaskManagerGtk::SetInitialDialogSize() { |
| 399 // Hook up to the realize event so we can size the page column to the |
| 400 // size of the leftover space after packing the other columns. |
| 401 g_signal_connect(G_OBJECT(treeview_), "realize", |
| 402 G_CALLBACK(OnTreeViewRealize), this); |
395 // If we previously saved the dialog's bounds, use them. | 403 // If we previously saved the dialog's bounds, use them. |
396 if (g_browser_process->local_state()) { | 404 if (g_browser_process->local_state()) { |
397 const DictionaryValue* placement_pref = | 405 const DictionaryValue* placement_pref = |
398 g_browser_process->local_state()->GetDictionary( | 406 g_browser_process->local_state()->GetDictionary( |
399 prefs::kTaskManagerWindowPlacement); | 407 prefs::kTaskManagerWindowPlacement); |
400 int top = 0, left = 0, bottom = 1, right = 1; | 408 int top = 0, left = 0, bottom = 1, right = 1; |
401 if (placement_pref && | 409 if (placement_pref && |
402 placement_pref->GetInteger(L"top", &top) && | 410 placement_pref->GetInteger(L"top", &top) && |
403 placement_pref->GetInteger(L"left", &left) && | 411 placement_pref->GetInteger(L"left", &left) && |
404 placement_pref->GetInteger(L"bottom", &bottom) && | 412 placement_pref->GetInteger(L"bottom", &bottom) && |
(...skipping 120 matching lines...) Loading... |
525 g_object_unref(icon); | 533 g_object_unref(icon); |
526 } | 534 } |
527 | 535 |
528 void TaskManagerGtk::KillSelectedProcesses() { | 536 void TaskManagerGtk::KillSelectedProcesses() { |
529 GtkTreeSelection* selection = gtk_tree_view_get_selection( | 537 GtkTreeSelection* selection = gtk_tree_view_get_selection( |
530 GTK_TREE_VIEW(treeview_)); | 538 GTK_TREE_VIEW(treeview_)); |
531 | 539 |
532 GtkTreeModel* model; | 540 GtkTreeModel* model; |
533 GList* paths = gtk_tree_selection_get_selected_rows(selection, &model); | 541 GList* paths = gtk_tree_selection_get_selected_rows(selection, &model); |
534 for (GList* item = paths; item; item = item->next) { | 542 for (GList* item = paths; item; item = item->next) { |
535 int row = GetRowNumForPath(reinterpret_cast<GtkTreePath*>(item->data)); | 543 int row = gtk_tree::GetRowNumForPath( |
| 544 reinterpret_cast<GtkTreePath*>(item->data)); |
536 task_manager_->KillProcess(row); | 545 task_manager_->KillProcess(row); |
537 } | 546 } |
538 g_list_free(paths); | 547 g_list_free(paths); |
539 } | 548 } |
540 | 549 |
541 void TaskManagerGtk::ShowContextMenu() { | 550 void TaskManagerGtk::ShowContextMenu() { |
542 if (!menu_controller_.get()) | 551 if (!menu_controller_.get()) |
543 menu_controller_.reset(new ContextMenuController(this)); | 552 menu_controller_.reset(new ContextMenuController(this)); |
544 | 553 |
545 menu_controller_->RunMenu(); | 554 menu_controller_->RunMenu(); |
546 } | 555 } |
547 | 556 |
548 void TaskManagerGtk::ActivateFocusedTab() { | 557 void TaskManagerGtk::ActivateFocusedTab() { |
549 GtkTreeSelection* selection = gtk_tree_view_get_selection( | 558 GtkTreeSelection* selection = gtk_tree_view_get_selection( |
550 GTK_TREE_VIEW(treeview_)); | 559 GTK_TREE_VIEW(treeview_)); |
551 | 560 |
552 // If the user has just double clicked, only one item is selected. | 561 // If the user has just double clicked, only one item is selected. |
553 GtkTreeModel* model; | 562 GtkTreeModel* model; |
554 GList* selected = gtk_tree_selection_get_selected_rows(selection, &model); | 563 GList* selected = gtk_tree_selection_get_selected_rows(selection, &model); |
555 if (selected) { | 564 if (selected) { |
556 int row = GetRowNumForPath(reinterpret_cast<GtkTreePath*>(selected->data)); | 565 int row = gtk_tree::GetRowNumForPath( |
| 566 reinterpret_cast<GtkTreePath*>(selected->data)); |
557 task_manager_->ActivateProcess(row); | 567 task_manager_->ActivateProcess(row); |
558 } | 568 } |
559 } | 569 } |
560 | 570 |
561 void TaskManagerGtk::OnLinkActivated() { | 571 void TaskManagerGtk::OnLinkActivated() { |
562 Browser* browser = BrowserList::GetLastActive(); | 572 Browser* browser = BrowserList::GetLastActive(); |
563 DCHECK(browser); | 573 DCHECK(browser); |
564 browser->OpenURL(GURL("about:memory"), GURL(), NEW_FOREGROUND_TAB, | 574 browser->OpenURL(GURL("about:memory"), GURL(), NEW_FOREGROUND_TAB, |
565 PageTransition::LINK); | 575 PageTransition::LINK); |
566 // In case the browser window is minimzed, show it. If this is an application | 576 // In case the browser window is minimzed, show it. If this is an application |
(...skipping 33 matching lines...) Loading... |
600 instance_ = NULL; | 610 instance_ = NULL; |
601 delete task_manager; | 611 delete task_manager; |
602 } else if (response_id == kTaskManagerResponseKill) { | 612 } else if (response_id == kTaskManagerResponseKill) { |
603 task_manager->KillSelectedProcesses(); | 613 task_manager->KillSelectedProcesses(); |
604 } else if (response_id == kTaskManagerAboutMemoryLink) { | 614 } else if (response_id == kTaskManagerAboutMemoryLink) { |
605 task_manager->OnLinkActivated(); | 615 task_manager->OnLinkActivated(); |
606 } | 616 } |
607 } | 617 } |
608 | 618 |
609 // static | 619 // static |
| 620 void TaskManagerGtk::OnTreeViewRealize(GtkTreeView* treeview, |
| 621 TaskManagerGtk* task_manager) { |
| 622 GtkTreeViewColumn* column = gtk_tree_view_get_column( |
| 623 GTK_TREE_VIEW(task_manager->treeview_), |
| 624 TreeViewColumnIndexFromID(kTaskManagerPage)); |
| 625 gint width = gtk_tree_view_column_get_width(column); |
| 626 // Turn expanding back off to make resizing columns behave sanely. |
| 627 gtk_tree_view_column_set_expand(column, FALSE); |
| 628 // Subtract 1 to work around some sort of fencepost error in GTK: without |
| 629 // it, a horizontal scroll bar with one pixel of wiggle room will appear. |
| 630 TreeViewColumnSetWidth(column, width - 1); |
| 631 } |
| 632 |
| 633 // static |
610 void TaskManagerGtk::OnSelectionChanged(GtkTreeSelection* selection, | 634 void TaskManagerGtk::OnSelectionChanged(GtkTreeSelection* selection, |
611 TaskManagerGtk* task_manager) { | 635 TaskManagerGtk* task_manager) { |
612 bool selection_contains_browser_process = false; | 636 bool selection_contains_browser_process = false; |
613 | 637 |
614 GtkTreeModel* model; | 638 GtkTreeModel* model; |
615 GList* paths = gtk_tree_selection_get_selected_rows(selection, &model); | 639 GList* paths = gtk_tree_selection_get_selected_rows(selection, &model); |
616 for (GList* item = paths; item; item = item->next) { | 640 for (GList* item = paths; item; item = item->next) { |
617 int row = GetRowNumForPath(reinterpret_cast<GtkTreePath*>(item->data)); | 641 int row = gtk_tree::GetRowNumForPath( |
| 642 reinterpret_cast<GtkTreePath*>(item->data)); |
618 if (task_manager->task_manager_->IsBrowserProcess(row)) { | 643 if (task_manager->task_manager_->IsBrowserProcess(row)) { |
619 selection_contains_browser_process = true; | 644 selection_contains_browser_process = true; |
620 break; | 645 break; |
621 } | 646 } |
622 } | 647 } |
623 g_list_free(paths); | 648 g_list_free(paths); |
624 | 649 |
625 bool sensitive = (paths != NULL) && !selection_contains_browser_process; | 650 bool sensitive = (paths != NULL) && !selection_contains_browser_process; |
626 gtk_dialog_set_response_sensitive(GTK_DIALOG(task_manager->dialog_), | 651 gtk_dialog_set_response_sensitive(GTK_DIALOG(task_manager->dialog_), |
627 kTaskManagerResponseKill, sensitive); | 652 kTaskManagerResponseKill, sensitive); |
(...skipping 32 matching lines...) Loading... |
660 if (keyval == GDK_w && modifier == GDK_CONTROL_MASK) { | 685 if (keyval == GDK_w && modifier == GDK_CONTROL_MASK) { |
661 // The GTK_RESPONSE_DELETE_EVENT response must be sent before the widget | 686 // The GTK_RESPONSE_DELETE_EVENT response must be sent before the widget |
662 // is destroyed. The deleted object will receive gtk signals otherwise. | 687 // is destroyed. The deleted object will receive gtk signals otherwise. |
663 gtk_dialog_response(GTK_DIALOG(task_manager->dialog_), | 688 gtk_dialog_response(GTK_DIALOG(task_manager->dialog_), |
664 GTK_RESPONSE_DELETE_EVENT); | 689 GTK_RESPONSE_DELETE_EVENT); |
665 gtk_widget_destroy(task_manager->dialog_); | 690 gtk_widget_destroy(task_manager->dialog_); |
666 } | 691 } |
667 | 692 |
668 return TRUE; | 693 return TRUE; |
669 } | 694 } |
OLD | NEW |