172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/task_manager_gtk.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gdk/gdkkeysyms.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <utility>
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/auto_reset.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h"
194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/defaults.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/memory_purger.h"
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/scoped_user_pref_update.h"
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h"
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_tree.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h"
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/models/simple_menu_model.h"
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gtk_util.h"
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(TOOLKIT_VIEWS)
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "views/controls/menu/menu_2.h"
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/menu_gtk.h"
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The task manager window default size.
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDefaultWidth = 460;
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDefaultHeight = 270;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The resource id for the 'End process' button.
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst gint kTaskManagerResponseKill = 1;
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The resource id for the 'Stats for nerds' link button.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst gint kTaskManagerAboutMemoryLink = 2;
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The resource id for the 'Purge Memory' button
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst gint kTaskManagerPurgeMemory = 3;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum TaskManagerColumn {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerIcon,
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerPage,
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerSharedMem,
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerPrivateMem,
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerCPU,
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerNetwork,
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerProcessID,
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerJavaScriptMemory,
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerWebCoreImageCache,
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerWebCoreScriptsCache,
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerWebCoreCssCache,
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  kTaskManagerSqliteMemoryUsed,
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerGoatsTeleported,
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Columns below this point are not visible in the task manager.
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  kTaskManagerBackgroundColor,
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kTaskManagerColumnCount,
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst TaskManagerColumn kTaskManagerLastVisibleColumn =
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    kTaskManagerGoatsTeleported;
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic const GdkColor kHighlightColor = GDK_COLOR_RGB(0xff, 0xfa, 0xcd);
8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTaskManagerColumn TaskManagerResourceIDToColumnID(int id) {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (id) {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_PAGE_COLUMN:
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerPage;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerSharedMem;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerPrivateMem;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_CPU_COLUMN:
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerCPU;
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_NET_COLUMN:
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerNetwork;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerProcessID;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerJavaScriptMemory;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerWebCoreImageCache;
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerWebCoreScriptsCache;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerWebCoreCssCache;
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return kTaskManagerSqliteMemoryUsed;
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN:
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return kTaskManagerGoatsTeleported;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return static_cast<TaskManagerColumn>(-1);
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TaskManagerColumnIDToResourceID(int id) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (id) {
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerPage:
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_PAGE_COLUMN;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerSharedMem:
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_SHARED_MEM_COLUMN;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerPrivateMem:
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerCPU:
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_CPU_COLUMN;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerNetwork:
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_NET_COLUMN;
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerProcessID:
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_PROCESS_ID_COLUMN;
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerJavaScriptMemory:
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerWebCoreImageCache:
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN;
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerWebCoreScriptsCache:
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerWebCoreCssCache:
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN;
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case kTaskManagerSqliteMemoryUsed:
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case kTaskManagerGoatsTeleported:
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN;
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return -1;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Should be used for all gtk_tree_view functions that require a column index on
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// input.
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We need colid - 1 because the gtk_tree_view function is asking for the
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// column index, not the column id, and both kTaskManagerIcon and
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// kTaskManagerPage are in the same column index, so all column IDs are off by
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// one.
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TreeViewColumnIndexFromID(TaskManagerColumn colid) {
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return colid - 1;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Shows or hides a treeview column.
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TreeViewColumnSetVisible(GtkWidget* treeview, TaskManagerColumn colid,
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              bool visible) {
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeViewColumn* column = gtk_tree_view_get_column(
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_set_visible(column, visible);
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TreeViewColumnIsVisible(GtkWidget* treeview, TaskManagerColumn colid) {
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeViewColumn* column = gtk_tree_view_get_column(
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gtk_tree_view_column_get_visible(column);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TreeViewInsertColumnWithPixbuf(GtkWidget* treeview, int resid) {
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int colid = TaskManagerResourceIDToColumnID(resid);
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeViewColumn* column = gtk_tree_view_column_new();
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_set_title(column,
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 l10n_util::GetStringUTF8(resid).c_str());
176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(treeview), colid);
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkCellRenderer* image_renderer = gtk_cell_renderer_pixbuf_new();
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_pack_start(column, image_renderer, FALSE);
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_add_attribute(column, image_renderer,
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     "pixbuf", kTaskManagerIcon);
18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gtk_tree_view_column_add_attribute(column, image_renderer,
18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                     "cell-background-gdk",
18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                     kTaskManagerBackgroundColor);
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkCellRenderer* text_renderer = gtk_cell_renderer_text_new();
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_add_attribute(column, text_renderer, "text", colid);
18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gtk_tree_view_column_add_attribute(column, text_renderer,
18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                     "cell-background-gdk",
18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                     kTaskManagerBackgroundColor);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_set_resizable(column, TRUE);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is temporary: we'll turn expanding off after getting the size.
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_set_expand(column, TRUE);
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_set_sort_column_id(column, colid);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Inserts a column with a column id of |colid| and |name|.
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TreeViewInsertColumnWithName(GtkWidget* treeview,
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  TaskManagerColumn colid, const char* name) {
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gtk_tree_view_insert_column_with_attributes(
20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      GTK_TREE_VIEW(treeview), -1,
20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      name, renderer,
20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      "text", colid,
20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      "cell-background-gdk", kTaskManagerBackgroundColor,
20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      NULL);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeViewColumn* column = gtk_tree_view_get_column(
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_TREE_VIEW(treeview), TreeViewColumnIndexFromID(colid));
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_set_resizable(column, TRUE);
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_set_sort_column_id(column, colid);
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Loads the column name from |resid| and uses the corresponding
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TaskManagerColumn value as the column id to insert into the treeview.
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TreeViewInsertColumn(GtkWidget* treeview, int resid) {
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumnWithName(treeview, TaskManagerResourceIDToColumnID(resid),
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               l10n_util::GetStringUTF8(resid).c_str());
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Set the current width of the column without forcing a minimum width as
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// gtk_tree_view_column_set_fixed_width() would. This would basically be
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// gtk_tree_view_column_set_width() except that there is no such function.
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TreeViewColumnSetWidth(GtkTreeViewColumn* column, gint width) {
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  column->width = width;
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  column->resized_width = width;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  column->use_resized_width = TRUE;
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Needed for use_resized_width to be effective.
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_queue_resize(column->tree_view);
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass TaskManagerGtk::ContextMenuController
23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : public ui::SimpleMenuModel::Delegate {
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit ContextMenuController(TaskManagerGtk* task_manager)
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : task_manager_(task_manager) {
23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    menu_model_.reset(new ui::SimpleMenuModel(this));
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    for (int i = kTaskManagerPage; i <= kTaskManagerLastVisibleColumn; i++) {
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      menu_model_->AddCheckItemWithStringId(
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          i, TaskManagerColumnIDToResourceID(i));
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(TOOLKIT_VIEWS)
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    menu_.reset(new views::Menu2(menu_model_.get()));
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    menu_.reset(new MenuGtk(NULL, menu_model_.get()));
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~ContextMenuController() {}
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void RunMenu(const gfx::Point& point, guint32 event_time) {
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(TOOLKIT_VIEWS)
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    menu_->RunContextMenuAt(point);
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else
25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    menu_->PopupAsContext(point, event_time);
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Cancel() {
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    task_manager_ = NULL;
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(TOOLKIT_VIEWS)
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    menu_->CancelMenu();
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    menu_->Cancel();
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ui::SimpleMenuModel::Delegate implementation:
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool IsCommandIdEnabled(int command_id) const {
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!task_manager_)
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool IsCommandIdChecked(int command_id) const {
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!task_manager_)
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TaskManagerColumn colid = static_cast<TaskManagerColumn>(command_id);
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return TreeViewColumnIsVisible(task_manager_->treeview_, colid);
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool GetAcceleratorForCommandId(
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int command_id,
28872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ui::Accelerator* accelerator) {
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void ExecuteCommand(int command_id) {
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!task_manager_)
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TaskManagerColumn colid = static_cast<TaskManagerColumn>(command_id);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool visible = !TreeViewColumnIsVisible(task_manager_->treeview_, colid);
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TreeViewColumnSetVisible(task_manager_->treeview_, colid, visible);
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The model and view for the right click context menu.
30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_ptr<ui::SimpleMenuModel> menu_model_;
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(TOOLKIT_VIEWS)
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<views::Menu2> menu_;
3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<MenuGtk> menu_;
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The TaskManager the context menu was brought up for. Set to NULL when the
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // menu is canceled.
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TaskManagerGtk* task_manager_;
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTaskManagerGtk::TaskManagerGtk(bool highlight_background_resources)
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  : task_manager_(TaskManager::GetInstance()),
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model_(TaskManager::GetInstance()->model()),
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    dialog_(NULL),
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    treeview_(NULL),
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    process_list_(NULL),
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    process_count_(0),
32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ignore_selection_changed_(false),
32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    highlight_background_resources_(highlight_background_resources) {
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Init();
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTaskManagerGtk* TaskManagerGtk::instance_ = NULL;
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTaskManagerGtk::~TaskManagerGtk() {
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  model_->RemoveObserver(this);
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  task_manager_->OnWindowClosed();
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_accel_group_disconnect_key(accel_group_, GDK_w, GDK_CONTROL_MASK);
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_remove_accel_group(GTK_WINDOW(dialog_), accel_group_);
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_unref(accel_group_);
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  accel_group_ = NULL;
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Disconnect the destroy signal so it doesn't delete |this|.
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_handler_disconnect(G_OBJECT(dialog_), destroy_handler_id_);
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_destroy(dialog_);
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TaskManagerGtk, TaskManagerModelObserver implementation:
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::OnModelChanged() {
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Nothing to do.
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::OnItemsChanged(int start, int length) {
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeIter iter;
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &iter,
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                NULL, start);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = start; i < start + length; i++) {
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetRowDataFromModel(i, &iter);
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_tree_model_iter_next(GTK_TREE_MODEL(process_list_), &iter);
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::OnItemsAdded(int start, int length) {
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AutoReset<bool> autoreset(&ignore_selection_changed_, true);
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeIter iter;
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (start == 0) {
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_list_store_prepend(process_list_, &iter);
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (start >= process_count_) {
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_list_store_append(process_list_, &iter);
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkTreeIter sibling;
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &sibling,
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  NULL, start);
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_list_store_insert_before(process_list_, &iter, &sibling);
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetRowDataFromModel(start, &iter);
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = start + 1; i < start + length; i++) {
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_list_store_insert_after(process_list_, &iter, &iter);
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetRowDataFromModel(i, &iter);
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  process_count_ += length;
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::OnItemsRemoved(int start, int length) {
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AutoReset<bool> autoreset(&ignore_selection_changed_, true);
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkTreeIter iter;
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(process_list_), &iter,
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  NULL, start);
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int i = 0; i < length; i++) {
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // |iter| is moved to the next valid node when the current node is
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // removed.
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_list_store_remove(process_list_, &iter);
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    process_count_ -= length;
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It is possible that we have removed the current selection; run selection
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // changed to detect that case.
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OnSelectionChanged(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_)));
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TaskManagerGtk, public:
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid TaskManagerGtk::Close() {
41472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Blow away our dialog - this will cause TaskManagerGtk to free itself.
41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gtk_widget_destroy(dialog_);
41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!instance_);
41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
41872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
42072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid TaskManagerGtk::Show(bool highlight_background_resources) {
42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (instance_ &&
42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      instance_->highlight_background_resources_ !=
42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          highlight_background_resources) {
42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    instance_->Close();
42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK(!instance_);
42672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (instance_) {
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If there's a Task manager window open already, just activate it.
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::PresentWindow(instance_->dialog_, 0);
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    instance_ = new TaskManagerGtk(highlight_background_resources);
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    instance_->model_->StartUpdating();
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TaskManagerGtk, private:
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::Init() {
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  dialog_ = gtk_dialog_new_with_buttons(
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_TASK_MANAGER_TITLE).c_str(),
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Task Manager window is shared between all browsers.
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL,
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_DIALOG_NO_SEPARATOR,
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL);
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allow browser windows to go in front of the task manager dialog in
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // metacity.
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (CommandLine::ForCurrentProcess()->HasSwitch(
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      switches::kPurgeMemoryButton)) {
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_dialog_add_button(GTK_DIALOG(dialog_),
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        l10n_util::GetStringUTF8(IDS_TASK_MANAGER_PURGE_MEMORY).c_str(),
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kTaskManagerPurgeMemory);
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (browser_defaults::kShowCancelButtonInTaskManager) {
4604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    gtk_dialog_add_button(GTK_DIALOG(dialog_),
4614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        l10n_util::GetStringUTF8(IDS_CLOSE).c_str(),
4624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        GTK_RESPONSE_DELETE_EVENT);
4634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
4644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_dialog_add_button(GTK_DIALOG(dialog_),
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_TASK_MANAGER_KILL).c_str(),
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kTaskManagerResponseKill);
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The response button should not be sensitive when the dialog is first opened
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // because the selection is initially empty.
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    kTaskManagerResponseKill, FALSE);
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* link = gtk_chrome_link_button_new(
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK).c_str());
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_dialog_add_action_widget(GTK_DIALOG(dialog_), link,
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               kTaskManagerAboutMemoryLink);
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Setting the link widget to secondary positions the button on the left side
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of the action area (vice versa for RTL layout).
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_button_box_set_child_secondary(
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_BUTTON_BOX(GTK_DIALOG(dialog_)->action_area), link, TRUE);
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ConnectAccelerators();
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      gtk_util::kContentAreaSpacing);
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  destroy_handler_id_ = g_signal_connect(dialog_, "destroy",
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         G_CALLBACK(OnDestroyThunk), this);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
49272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // GTK does menu on mouse-up while views does menu on mouse-down,
49372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // so connect to different handlers.
49472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(TOOLKIT_VIEWS)
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(dialog_, "button-release-event",
49672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   G_CALLBACK(OnButtonEventThunk), this);
49772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#else
49872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  g_signal_connect(dialog_, "button-press-event",
49972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   G_CALLBACK(OnButtonEventThunk), this);
50072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_add_events(dialog_,
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Wrap the treeview widget in a scrolled window in order to have a frame.
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      GTK_SHADOW_ETCHED_IN);
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), scrolled);
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CreateTaskManagerTreeview();
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(treeview_), TRUE);
51521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  g_signal_connect(treeview_, "row-activated",
51621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                   G_CALLBACK(OnRowActivatedThunk), this);
517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(TOOLKIT_GTK)
518dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  g_signal_connect(treeview_, "button-press-event",
519dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                   G_CALLBACK(OnButtonEventThunk), this);
520dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |selection| is owned by |treeview_|.
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeSelection* selection = gtk_tree_view_get_selection(
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_TREE_VIEW(treeview_));
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(selection, "changed",
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnSelectionChangedThunk), this);
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(scrolled), treeview_);
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetInitialDialogSize();
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::ShowDialog(dialog_);
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
534731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // If the model already has resources, we need to add them before we start
535731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // observing events.
536731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (model_->ResourceCount() > 0)
537731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    OnItemsAdded(0, model_->ResourceCount());
538731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  model_->AddObserver(this);
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::SetInitialDialogSize() {
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Hook up to the realize event so we can size the page column to the
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // size of the leftover space after packing the other columns.
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(treeview_, "realize",
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnTreeViewRealizeThunk), this);
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we previously saved the dialog's bounds, use them.
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (g_browser_process->local_state()) {
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const DictionaryValue* placement_pref =
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_browser_process->local_state()->GetDictionary(
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            prefs::kTaskManagerWindowPlacement);
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int top = 0, left = 0, bottom = 1, right = 1;
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (placement_pref &&
5543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        placement_pref->GetInteger("top", &top) &&
5553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        placement_pref->GetInteger("left", &left) &&
5563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        placement_pref->GetInteger("bottom", &bottom) &&
5573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        placement_pref->GetInteger("right", &right)) {
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_window_resize(GTK_WINDOW(dialog_),
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        std::max(1, right - left),
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        std::max(1, bottom - top));
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise, just set a default size (GTK will override this if it's not
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // large enough to hold the window's contents).
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_set_default_size(
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_WINDOW(dialog_), kDefaultWidth, kDefaultHeight);
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::ConnectAccelerators() {
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  accel_group_ = gtk_accel_group_new();
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_add_accel_group(GTK_WINDOW(dialog_), accel_group_);
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_accel_group_connect(accel_group_,
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          GDK_w, GDK_CONTROL_MASK, GtkAccelFlags(0),
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          g_cclosure_new(G_CALLBACK(OnGtkAcceleratorThunk),
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         this, NULL));
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::CreateTaskManagerTreeview() {
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  process_list_ = gtk_list_store_new(kTaskManagerColumnCount,
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
5853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
58672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      G_TYPE_STRING, GDK_TYPE_COLOR);
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Support sorting on all columns.
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  process_list_sort_ = gtk_tree_model_sort_new_with_model(
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_TREE_MODEL(process_list_));
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerPage,
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  ComparePage, this, NULL);
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerSharedMem,
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompareSharedMemory, this, NULL);
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerPrivateMem,
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  ComparePrivateMemory, this, NULL);
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerJavaScriptMemory,
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompareV8Memory, this, NULL);
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerCPU,
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompareCPU, this, NULL);
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerNetwork,
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompareNetwork, this, NULL);
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerProcessID,
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompareProcessID, this, NULL);
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerWebCoreImageCache,
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompareWebCoreImageCache, this, NULL);
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerWebCoreScriptsCache,
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompareWebCoreScriptsCache, this, NULL);
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerWebCoreCssCache,
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompareWebCoreCssCache, this, NULL);
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
6223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  kTaskManagerSqliteMemoryUsed,
6233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  CompareSqliteMemoryUsed, this, NULL);
6243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(process_list_sort_),
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  kTaskManagerGoatsTeleported,
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompareGoatsTeleported, this, NULL);
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  treeview_ = gtk_tree_view_new_with_model(process_list_sort_);
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Insert all the columns.
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumnWithPixbuf(treeview_, IDS_TASK_MANAGER_PAGE_COLUMN);
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_CPU_COLUMN);
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_NET_COLUMN);
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_,
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN);
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN);
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_,
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN);
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN);
6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN);
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewInsertColumn(treeview_, IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN);
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Hide some columns by default.
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewColumnSetVisible(treeview_, kTaskManagerSharedMem, false);
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewColumnSetVisible(treeview_, kTaskManagerProcessID, false);
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewColumnSetVisible(treeview_, kTaskManagerJavaScriptMemory, false);
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewColumnSetVisible(treeview_, kTaskManagerWebCoreImageCache, false);
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewColumnSetVisible(treeview_, kTaskManagerWebCoreScriptsCache, false);
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewColumnSetVisible(treeview_, kTaskManagerWebCoreCssCache, false);
6523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TreeViewColumnSetVisible(treeview_, kTaskManagerSqliteMemoryUsed, false);
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewColumnSetVisible(treeview_, kTaskManagerGoatsTeleported, false);
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_unref(process_list_);
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_unref(process_list_sort_);
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsSharedByGroup(int col_id) {
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (col_id) {
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_CPU_COLUMN:
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string TaskManagerGtk::GetModelText(int row, int col_id) {
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsSharedByGroup(col_id) && !model_->IsResourceFirstInGroup(row))
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return std::string();
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (col_id) {
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_PAGE_COLUMN:  // Process
6813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceTitle(row));
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:  // Memory
6843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourcePrivateMemory(row));
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:  // Memory
6873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceSharedMemory(row));
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_CPU_COLUMN:  // CPU
6903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceCPUUsage(row));
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_NET_COLUMN:  // Net
6933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceNetworkUsage(row));
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:  // Process ID
6963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceProcessId(row));
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
6993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceV8MemoryAllocatedSize(row));
700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
7023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceWebCoreImageCacheSize(row));
703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
7053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceWebCoreScriptsCacheSize(row));
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
7083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceWebCoreCSSCacheSize(row));
7093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
7113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceSqliteMemoryUsed(row));
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN:  // Goats Teleported!
7143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return UTF16ToUTF8(model_->GetResourceGoatsTeleported(row));
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return std::string();
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGdkPixbuf* TaskManagerGtk::GetModelIcon(int row) {
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap icon = model_->GetResourceIcon(row);
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (icon.pixelRef() ==
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ResourceBundle::GetSharedInstance().GetBitmapNamed(
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          IDR_DEFAULT_FAVICON)->pixelRef()) {
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return static_cast<GdkPixbuf*>(g_object_ref(
728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        GtkThemeService::GetDefaultFavicon(true)));
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::GdkPixbufFromSkBitmap(&icon);
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::SetRowDataFromModel(int row, GtkTreeIter* iter) {
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkPixbuf* icon = GetModelIcon(row);
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string page = GetModelText(row, IDS_TASK_MANAGER_PAGE_COLUMN);
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string shared_mem = GetModelText(
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      row, IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string priv_mem = GetModelText(row, IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string cpu = GetModelText(row, IDS_TASK_MANAGER_CPU_COLUMN);
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string net = GetModelText(row, IDS_TASK_MANAGER_NET_COLUMN);
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string procid = GetModelText(row, IDS_TASK_MANAGER_PROCESS_ID_COLUMN);
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Querying the renderer metrics is slow as it has to do IPC, so only do it
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // when the columns are visible.
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string javascript_memory;
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (TreeViewColumnIsVisible(treeview_, kTaskManagerJavaScriptMemory))
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    javascript_memory = GetModelText(
749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        row, IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN);
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string wk_img_cache;
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (TreeViewColumnIsVisible(treeview_, kTaskManagerWebCoreImageCache))
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    wk_img_cache = GetModelText(
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        row, IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN);
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string wk_scripts_cache;
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (TreeViewColumnIsVisible(treeview_, kTaskManagerWebCoreScriptsCache))
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    wk_scripts_cache = GetModelText(
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        row, IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN);
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string wk_css_cache;
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (TreeViewColumnIsVisible(treeview_, kTaskManagerWebCoreCssCache))
760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    wk_css_cache = GetModelText(
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        row, IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN);
7623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string sqlite_memory;
7633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (TreeViewColumnIsVisible(treeview_, kTaskManagerSqliteMemoryUsed))
7643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    sqlite_memory = GetModelText(
7653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        row, IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN);
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string goats = GetModelText(
768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      row, IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN);
76972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
77072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool is_background = model_->IsBackgroundResource(row) &&
77172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      highlight_background_resources_;
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_list_store_set(process_list_, iter,
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerIcon, icon,
774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerPage, page.c_str(),
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerSharedMem, shared_mem.c_str(),
776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerPrivateMem, priv_mem.c_str(),
777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerCPU, cpu.c_str(),
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerNetwork, net.c_str(),
779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerProcessID, procid.c_str(),
780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerJavaScriptMemory, javascript_memory.c_str(),
781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerWebCoreImageCache, wk_img_cache.c_str(),
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerWebCoreScriptsCache, wk_scripts_cache.c_str(),
783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerWebCoreCssCache, wk_css_cache.c_str(),
7843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                     kTaskManagerSqliteMemoryUsed, sqlite_memory.c_str(),
785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     kTaskManagerGoatsTeleported, goats.c_str(),
78672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     kTaskManagerBackgroundColor,
78772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     is_background ? &kHighlightColor : NULL,
788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     -1);
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_unref(icon);
790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::KillSelectedProcesses() {
793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeSelection* selection = gtk_tree_view_get_selection(
794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_TREE_VIEW(treeview_));
795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeModel* model;
797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GList* paths = gtk_tree_selection_get_selected_rows(selection, &model);
798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (GList* item = paths; item; item = item->next) {
799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkTreePath* path = gtk_tree_model_sort_convert_path_to_child_path(
800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GTK_TREE_MODEL_SORT(process_list_sort_),
801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        reinterpret_cast<GtkTreePath*>(item->data));
802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int row = gtk_tree::GetRowNumForPath(path);
803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_tree_path_free(path);
804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    task_manager_->KillProcess(row);
805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_list_free(paths);
808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid TaskManagerGtk::ShowContextMenu(const gfx::Point& point,
81172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                     guint32 event_time) {
8123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!menu_controller_.get())
8133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    menu_controller_.reset(new ContextMenuController(this));
8143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
81572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  menu_controller_->RunMenu(point, event_time);
8163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::OnLinkActivated() {
819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  task_manager_->OpenAboutMemory();
820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgint TaskManagerGtk::CompareImpl(GtkTreeModel* model, GtkTreeIter* a,
823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 GtkTreeIter* b, int id) {
824731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  int row1 = gtk_tree::GetRowNumForIter(model, b);
825731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  int row2 = gtk_tree::GetRowNumForIter(model, a);
826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When sorting by non-grouped attributes (e.g., Network), just do a normal
828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // sort.
829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsSharedByGroup(id))
830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return model_->CompareValues(row1, row2, id);
831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise, make sure grouped resources are shown together.
833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::pair<int, int> group_range1 = model_->GetGroupRangeForResource(row1);
834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::pair<int, int> group_range2 = model_->GetGroupRangeForResource(row2);
835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (group_range1 == group_range2) {
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Sort within groups.
838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We want the first-in-group row at the top, whether we are sorting up or
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // down.
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkSortType sort_type;
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(process_list_sort_),
842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         NULL, &sort_type);
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (row1 == group_range1.first)
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return sort_type == GTK_SORT_ASCENDING ? -1 : 1;
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (row2 == group_range2.first)
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return sort_type == GTK_SORT_ASCENDING ? 1 : -1;
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return model_->CompareValues(row1, row2, id);
849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Sort between groups.
851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Compare by the first-in-group rows so that the groups will stay together.
852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return model_->CompareValues(group_range1.first, group_range2.first, id);
853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::OnDestroy(GtkWidget* dialog) {
857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  instance_ = NULL;
858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete this;
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
861dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid TaskManagerGtk::OnResponse(GtkWidget* dialog, int response_id) {
862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (response_id == GTK_RESPONSE_DELETE_EVENT) {
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Store the dialog's size so we can restore it the next time it's opened.
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (g_browser_process->local_state()) {
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gfx::Rect dialog_bounds = gtk_util::GetDialogBounds(GTK_WIDGET(dialog));
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
867ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DictionaryPrefUpdate update(g_browser_process->local_state(),
868ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  prefs::kTaskManagerWindowPlacement);
869ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DictionaryValue* placement_pref = update.Get();
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Note that we store left/top for consistency with Windows, but that we
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // *don't* restore them.
8723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      placement_pref->SetInteger("left", dialog_bounds.x());
8733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      placement_pref->SetInteger("top", dialog_bounds.y());
8743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      placement_pref->SetInteger("right", dialog_bounds.right());
8753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      placement_pref->SetInteger("bottom", dialog_bounds.bottom());
8763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      placement_pref->SetBoolean("maximized", false);
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    instance_ = NULL;
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete this;
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (response_id == kTaskManagerResponseKill) {
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    KillSelectedProcesses();
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (response_id == kTaskManagerAboutMemoryLink) {
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OnLinkActivated();
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (response_id == kTaskManagerPurgeMemory) {
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MemoryPurger::PurgeAll();
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::OnTreeViewRealize(GtkTreeView* treeview) {
891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Four columns show by default: the page column, the memory column, the
892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // CPU column, and the network column. Initially we set the page column to
893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // take all the extra space, with the other columns being sized to fit the
894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // column names. Here we turn off the expand property of the first column
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (to make the table behave sanely when the user resizes columns) and set
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the effective sizes of all four default columns to the automatically
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // chosen size before any rows are added. This causes them to stay at that
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // size even if the data would overflow, preventing a horizontal scroll
899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // bar from appearing due to the row data.
900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const TaskManagerColumn dfl_columns[] = {kTaskManagerNetwork, kTaskManagerCPU,
901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           kTaskManagerPrivateMem};
902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeViewColumn* column = NULL;
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint width;
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < arraysize(dfl_columns); ++i) {
905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    column = gtk_tree_view_get_column(treeview,
906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        TreeViewColumnIndexFromID(dfl_columns[i]));
907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    width = gtk_tree_view_column_get_width(column);
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TreeViewColumnSetWidth(column, width);
909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Do the page column separately since it's a little different.
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  column = gtk_tree_view_get_column(treeview,
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      TreeViewColumnIndexFromID(kTaskManagerPage));
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  width = gtk_tree_view_column_get_width(column);
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Turn expanding back off to make resizing columns behave sanely.
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_column_set_expand(column, FALSE);
916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TreeViewColumnSetWidth(column, width);
917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TaskManagerGtk::OnSelectionChanged(GtkTreeSelection* selection) {
920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ignore_selection_changed_)
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AutoReset<bool> autoreset(&ignore_selection_changed_, true);
923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The set of groups that should be selected.
925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::set<std::pair<int, int> > ranges;
926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool selection_contains_browser_process = false;
927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeModel* model;
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GList* paths = gtk_tree_selection_get_selected_rows(selection, &model);
930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (GList* item = paths; item; item = item->next) {
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkTreePath* path = gtk_tree_model_sort_convert_path_to_child_path(
932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GTK_TREE_MODEL_SORT(process_list_sort_),
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        reinterpret_cast<GtkTreePath*>(item->data));
934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int row = gtk_tree::GetRowNumForPath(path);
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_tree_path_free(path);
936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (task_manager_->IsBrowserProcess(row))
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      selection_contains_browser_process = true;
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ranges.insert(model_->GetGroupRangeForResource(row));
939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL);
941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_list_free(paths);
942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::set<std::pair<int, int> >::iterator iter = ranges.begin();
944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       iter != ranges.end(); ++iter) {
945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int i = 0; i < iter->second; ++i) {
946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GtkTreePath* child_path = gtk_tree_path_new_from_indices(iter->first + i,
947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                               -1);
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GtkTreePath* sort_path = gtk_tree_model_sort_convert_child_path_to_path(
949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GTK_TREE_MODEL_SORT(process_list_sort_), child_path);
950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_tree_selection_select_path(selection, sort_path);
951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_tree_path_free(child_path);
952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_tree_path_free(sort_path);
953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sensitive = (paths != NULL) && !selection_contains_browser_process;
957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    kTaskManagerResponseKill, sensitive);
959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid TaskManagerGtk::OnRowActivated(GtkWidget* widget,
96221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                    GtkTreePath* path,
96321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                    GtkTreeViewColumn* column) {
96421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  GtkTreePath* child_path = gtk_tree_model_sort_convert_path_to_child_path(
96521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      GTK_TREE_MODEL_SORT(process_list_sort_), path);
96621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int row = gtk_tree::GetRowNumForPath(child_path);
96721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  gtk_tree_path_free(child_path);
96821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  task_manager_->ActivateProcess(row);
969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
97172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsengboolean TaskManagerGtk::OnButtonEvent(GtkWidget* widget,
97272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                       GdkEventButton* event) {
97372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // GTK does menu on mouse-up while views does menu on mouse-down,
974dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // so this function can be called from either signal.
9753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (event->button == 3) {
97672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ShowContextMenu(gfx::Point(event->x_root, event->y_root),
97772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                    event->time);
978dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return TRUE;
9793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean TaskManagerGtk::OnGtkAccelerator(GtkAccelGroup* accel_group,
985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          GObject* acceleratable,
986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          guint keyval,
987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          GdkModifierType modifier) {
988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (keyval == GDK_w && modifier == GDK_CONTROL_MASK) {
989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The GTK_RESPONSE_DELETE_EVENT response must be sent before the widget
990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // is destroyed.  The deleted object will receive gtk signals otherwise.
991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_dialog_response(GTK_DIALOG(dialog_), GTK_RESPONSE_DELETE_EVENT);
992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
996