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/gtk_util.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <cairo/cairo.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gdk/gdkx.h>
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <gtk/gtk.h>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <cstdarg>
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map>
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/environment.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/rtl.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/linux_util.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/nix/xdg_util.h"
19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/string_number_conversions.h"
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/autocomplete.h"
224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_classifier.h"
23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_match.h"
2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h"
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/cairo_cached_surface.h"
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h"
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/disposition_utils.h"
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/renderer_preferences.h"
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h"
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h"
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkColor.h"
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/x/x11_util.h"
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gtk_util.h"
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_CHROMEOS)
434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/chromeos/frame/browser_view.h"
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/native_dialog_window.h"
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h"
464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/browser_window_gtk.h"
484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing WebKit::WebDragOperationsMask;
51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing WebKit::WebDragOperation;
52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing WebKit::WebDragOperationNone;
53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing WebKit::WebDragOperationCopy;
54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing WebKit::WebDragOperationLink;
55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing WebKit::WebDragOperationMove;
56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(GOOGLE_CHROME_BUILD)
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic const char* kIconName = "google-chrome";
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#else
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic const char* kIconName = "chromium-browser";
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kBoldLabelMarkup[] = "<span weight='bold'>%s</span>";
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Callback used in RemoveAllChildren.
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RemoveWidget(GtkWidget* widget, gpointer container) {
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_remove(GTK_CONTAINER(container), widget);
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These two functions are copped almost directly from gtk core. The only
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// difference is that they accept middle clicks.
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean OnMouseButtonPressed(GtkWidget* widget, GdkEventButton* event,
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              gpointer userdata) {
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event->type == GDK_BUTTON_PRESS) {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (gtk_button_get_focus_on_click(GTK_BUTTON(widget)) &&
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        !GTK_WIDGET_HAS_FOCUS(widget)) {
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_grab_focus(widget);
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gint button_mask = GPOINTER_TO_INT(userdata);
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (button_mask & (1 << event->button))
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_button_pressed(GTK_BUTTON(widget));
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean OnMouseButtonReleased(GtkWidget* widget, GdkEventButton* event,
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               gpointer userdata) {
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint button_mask = GPOINTER_TO_INT(userdata);
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (button_mask && (1 << event->button))
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_button_released(GTK_BUTTON(widget));
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Returns the approximate number of characters that can horizontally fit in
100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// |pixel_width| pixels.
101513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint GetCharacterWidthForPixels(GtkWidget* widget, int pixel_width) {
102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(GTK_WIDGET_REALIZED(widget))
103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      << " widget must be realized to compute font metrics correctly";
104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  PangoContext* context = gtk_widget_create_pango_context(widget);
106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  PangoFontMetrics* metrics = pango_context_get_metrics(context,
107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      widget->style->font_desc, pango_context_get_language(context));
108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // This technique (max of char and digit widths) matches the code in
110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // gtklabel.c.
111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int char_width = pixel_width * PANGO_SCALE /
112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      std::max(pango_font_metrics_get_approximate_char_width(metrics),
113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch               pango_font_metrics_get_approximate_digit_width(metrics));
114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  pango_font_metrics_unref(metrics);
116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  g_object_unref(context);
117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return char_width;
119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid OnLabelRealize(GtkWidget* label, gpointer pixel_width) {
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gtk_label_set_width_chars(
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      GTK_LABEL(label),
124513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      GetCharacterWidthForPixels(label,GPOINTER_TO_INT(pixel_width)));
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Ownership of |icon_list| is passed to the caller.
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGList* GetIconList() {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GList* icon_list = NULL;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  icon_list = g_list_append(icon_list, rb.GetPixbufNamed(IDR_PRODUCT_ICON_32));
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  icon_list = g_list_append(icon_list, rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return icon_list;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Expose event handler for a container that simply suppresses the default
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// drawing and propagates the expose event to the container's children.
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean PaintNoBackground(GtkWidget* widget,
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           GdkEventExpose* event,
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           gpointer unused) {
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GList* children = gtk_container_get_children(GTK_CONTAINER(widget));
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (GList* item = children; item; item = item->next) {
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_container_propagate_expose(GTK_CONTAINER(widget),
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   GTK_WIDGET(item->data),
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   event);
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_list_free(children);
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(OS_CHROMEOS)
1534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) {
1554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  chromeos::BrowserView* browser_view = static_cast<chromeos::BrowserView*>(
1564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      window);
1574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return browser_view->GetSelectedTabContents();
1584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
1594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochGtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) {
1614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  gfx::NativeView widget = gtk_window_get_focus(window->GetNativeHandle());
1624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (widget == NULL) {
1644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    chromeos::BrowserView* browser_view = static_cast<chromeos::BrowserView*>(
1654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        window);
1664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    widget = browser_view->saved_focused_widget();
1674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return widget;
1704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
1714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
1734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) {
1754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
1764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      window);
1774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return browser_window->browser()->GetSelectedTabContents();
1784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
1794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochGtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) {
1814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return gtk_window_get_focus(window->GetNativeHandle());
1824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
1834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
1854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace event_utils {
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWindowOpenDisposition DispositionFromEventFlags(guint event_flags) {
19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return disposition_utils::DispositionFromClick(
19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      event_flags & GDK_BUTTON2_MASK,
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      event_flags & GDK_MOD1_MASK,
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      event_flags & GDK_CONTROL_MASK,
19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      event_flags & GDK_META_MASK,
19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      event_flags & GDK_SHIFT_MASK);
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace event_utils
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace gtk_util {
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
203513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst GdkColor kGdkWhite = GDK_COLOR_RGB(0xff, 0xff, 0xff);
204513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst GdkColor kGdkGray  = GDK_COLOR_RGB(0x7f, 0x7f, 0x7f);
205513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst GdkColor kGdkBlack = GDK_COLOR_RGB(0x00, 0x00, 0x00);
206513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst GdkColor kGdkGreen = GDK_COLOR_RGB(0x00, 0xff, 0x00);
207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* CreateLabeledControlsGroup(std::vector<GtkWidget*>* labels,
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      const char* text, ...) {
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  va_list ap;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  va_start(ap, text);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* table = gtk_table_new(0, 2, FALSE);
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_table_set_col_spacing(GTK_TABLE(table), 0, kLabelSpacing);
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_table_set_row_spacings(GTK_TABLE(table), kControlSpacing);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (guint row = 0; text; ++row) {
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_table_resize(GTK_TABLE(table), row + 1, 2);
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* control = va_arg(ap, GtkWidget*);
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* label = gtk_label_new(text);
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (labels)
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      labels->push_back(label);
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_table_attach(GTK_TABLE(table), label,
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 0, 1, row, row + 1,
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 GTK_FILL, GTK_FILL,
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 0, 0);
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_table_attach_defaults(GTK_TABLE(table), control,
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              1, 2, row, row + 1);
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    text = va_arg(ap, const char*);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  va_end(ap);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return table;
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color,
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              int top, int bottom, int left, int right) {
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Use a GtkEventBox to get the background painted.  However, we can't just
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // use a container border, since it won't paint there.  Use an alignment
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // inside to get the sizes exactly of how we want the border painted.
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* ebox = gtk_event_box_new();
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (color)
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, color);
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), top, bottom, left, right);
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(alignment), child);
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(ebox), alignment);
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ebox;
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* LeftAlignMisc(GtkWidget* misc) {
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_misc_set_alignment(GTK_MISC(misc), 0, 0.5);
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return misc;
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* CreateBoldLabel(const std::string& text) {
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* label = gtk_label_new(NULL);
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char* markup = g_markup_printf_escaped(kBoldLabelMarkup, text.c_str());
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_label_set_markup(GTK_LABEL(label), markup);
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_free(markup);
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return LeftAlignMisc(label);
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
266513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid GetWidgetSizeFromCharacters(
267513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    GtkWidget* widget, double width_chars, double height_lines,
268513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int* width, int* height) {
269513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(GTK_WIDGET_REALIZED(widget))
270513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      << " widget must be realized to compute font metrics correctly";
271513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  PangoContext* context = gtk_widget_create_pango_context(widget);
272513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  PangoFontMetrics* metrics = pango_context_get_metrics(context,
273513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      widget->style->font_desc, pango_context_get_language(context));
274513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (width) {
275513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    *width = static_cast<int>(
276513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        pango_font_metrics_get_approximate_char_width(metrics) *
277513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        width_chars / PANGO_SCALE);
278513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
279513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (height) {
280513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    *height = static_cast<int>(
281513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        (pango_font_metrics_get_ascent(metrics) +
282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        pango_font_metrics_get_descent(metrics)) *
283513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        height_lines / PANGO_SCALE);
284513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
285513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  pango_font_metrics_unref(metrics);
286513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  g_object_unref(context);
287513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
288513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
289513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid GetWidgetSizeFromResources(
290513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    GtkWidget* widget, int width_chars, int height_lines,
291513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int* width, int* height) {
292513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(GTK_WIDGET_REALIZED(widget))
293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      << " widget must be realized to compute font metrics correctly";
294513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
295513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  double chars = 0;
296513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (width)
297513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    base::StringToDouble(l10n_util::GetStringUTF8(width_chars), &chars);
298513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
299513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  double lines = 0;
300513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (height)
301513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    base::StringToDouble(l10n_util::GetStringUTF8(height_lines), &lines);
302513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
303513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GetWidgetSizeFromCharacters(widget, chars, lines, width, height);
304513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
305513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetWindowSizeFromResources(GtkWindow* window,
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                int width_id, int height_id, bool resizable) {
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int width = -1;
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int height = -1;
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::GetWidgetSizeFromResources(GTK_WIDGET(window), width_id, height_id,
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       (width_id != -1) ? &width : NULL,
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       (height_id != -1) ? &height : NULL);
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (resizable) {
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_set_default_size(window, width, height);
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // For a non-resizable window, GTK tries to snap the window size
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // to the minimum size around the content.  We use the sizes in
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the resources to set *minimum* window size to allow windows
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // with long titles to be wide enough to display their titles.
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // But if GTK wants to make the window *wider* due to very wide
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // controls, we should allow that too, so be careful to pick the
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // wider of the resources size and the natural window size.
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_show_all(GTK_BIN(window)->child);
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkRequisition requisition;
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_size_request(GTK_WIDGET(window), &requisition);
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GTK_WIDGET(window),
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        width == -1 ? -1 : std::max(width, requisition.width),
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        height == -1 ? -1 : std::max(height, requisition.height));
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_set_resizable(window, resizable ? TRUE : FALSE);
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CenterOverWindow(GtkWindow* window, GtkWindow* parent) {
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect frame_bounds = gtk_util::GetWidgetScreenBounds(GTK_WIDGET(parent));
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point origin = frame_bounds.origin();
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size size = gtk_util::GetWidgetSize(GTK_WIDGET(window));
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  origin.Offset(
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (frame_bounds.width() - size.width()) / 2,
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (frame_bounds.height() - size.height()) / 2);
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Prevent moving window out of monitor bounds.
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkScreen* screen = gtk_window_get_screen(parent);
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (screen) {
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // It would be better to check against workarea for given monitor
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // but getting workarea for particular monitor is tricky.
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gint monitor = gdk_screen_get_monitor_at_window(screen,
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GTK_WIDGET(parent)->window);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkRectangle rect;
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_screen_get_monitor_geometry(screen, monitor, &rect);
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check the right bottom corner.
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (origin.x() > rect.x + rect.width - size.width())
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      origin.set_x(rect.x + rect.width - size.width());
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (origin.y() > rect.y + rect.height - size.height())
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      origin.set_y(rect.y + rect.height - size.height());
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check the left top corner.
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (origin.x() < rect.x)
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      origin.set_x(rect.x);
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (origin.y() < rect.y)
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      origin.set_y(rect.y);
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_move(window, origin.x(), origin.y());
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Move to user expected desktop if window is already visible.
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (GTK_WIDGET(window)->window) {
37272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ui::ChangeWindowDesktop(
37372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        ui::GetX11WindowFromGtkWidget(GTK_WIDGET(window)),
37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        ui::GetX11WindowFromGtkWidget(GTK_WIDGET(parent)));
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MakeAppModalWindowGroup() {
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if GTK_CHECK_VERSION(2, 14, 0)
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Older versions of GTK+ don't give us gtk_window_group_list() which is what
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we need to add current non-browser modal dialogs to the list. If
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we have 2.14+ we can do things the correct way.
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWindowGroup* window_group = gtk_window_group_new();
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (BrowserList::const_iterator it = BrowserList::begin();
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       it != BrowserList::end(); ++it) {
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // List all windows in this current group
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWindowGroup* old_group =
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_window_get_group((*it)->window()->GetNativeHandle());
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GList* all_windows = gtk_window_group_list_windows(old_group);
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (GList* window = all_windows; window; window = window->next) {
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_window_group_add_window(window_group, GTK_WINDOW(window->data));
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_list_free(all_windows);
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_unref(window_group);
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise just grab all browser windows and be slightly broken.
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWindowGroup* window_group = gtk_window_group_new();
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (BrowserList::const_iterator it = BrowserList::begin();
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       it != BrowserList::end(); ++it) {
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_group_add_window(window_group,
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                (*it)->window()->GetNativeHandle());
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_unref(window_group);
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppModalDismissedUngroupWindows() {
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if GTK_CHECK_VERSION(2, 14, 0)
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (BrowserList::begin() != BrowserList::end()) {
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<GtkWindow*> transient_windows;
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // All windows should be part of one big modal group right now.
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWindowGroup* window_group = gtk_window_get_group(
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        (*BrowserList::begin())->window()->GetNativeHandle());
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GList* windows = gtk_window_group_list_windows(window_group);
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (GList* item = windows; item; item = item->next) {
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GtkWindow* window = GTK_WINDOW(item->data);
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GtkWindow* transient_for = gtk_window_get_transient_for(window);
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (transient_for) {
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        transient_windows.push_back(window);
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GtkWindowGroup* window_group = gtk_window_group_new();
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_window_group_add_window(window_group, window);
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_object_unref(window_group);
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Put each transient window in the same group as its transient parent.
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (std::vector<GtkWindow*>::iterator it = transient_windows.begin();
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         it != transient_windows.end(); ++it) {
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GtkWindow* transient_parent = gtk_window_get_transient_for(*it);
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GtkWindowGroup* group = gtk_window_get_group(transient_parent);
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_window_group_add_window(group, *it);
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is slightly broken in the case where a different window had a dialog,
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // but its the best we can do since we don't have newer gtk stuff.
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (BrowserList::const_iterator it = BrowserList::begin();
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       it != BrowserList::end(); ++it) {
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWindowGroup* window_group = gtk_window_group_new();
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_group_add_window(window_group,
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                (*it)->window()->GetNativeHandle());
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_object_unref(window_group);
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RemoveAllChildren(GtkWidget* container) {
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_foreach(GTK_CONTAINER(container), RemoveWidget, container);
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ForceFontSizePixels(GtkWidget* widget, double size_pixels) {
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkStyle* style = widget->style;
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PangoFontDescription* font_desc = style->font_desc;
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pango_font_description_set_absolute_size sets the font size in device
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // units, which for us is pixels.
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pango_font_description_set_absolute_size(font_desc,
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           PANGO_SCALE * size_pixels);
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_font(widget, font_desc);
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UndoForceFontSize(GtkWidget* widget) {
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_font(widget, NULL);
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Point GetWidgetScreenPosition(GtkWidget* widget) {
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!widget->window) {
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Must only be called on realized widgets.";
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return gfx::Point(0, 0);
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint x, y;
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_window_get_origin(widget->window, &x, &y);
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (GTK_WIDGET_NO_WINDOW(widget)) {
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    x += widget->allocation.x;
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    y += widget->allocation.y;
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Point(x, y);
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect GetWidgetScreenBounds(GtkWidget* widget) {
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point position = GetWidgetScreenPosition(widget);
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Rect(position.x(), position.y(),
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   widget->allocation.width, widget->allocation.height);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size GetWidgetSize(GtkWidget* widget) {
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkRequisition size;
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_size_request(widget, &size);
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Size(size.width, size.height);
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p) {
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(widget);
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(p);
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Point position = GetWidgetScreenPosition(widget);
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  p->SetPoint(p->x() + position.x(), p->y() + position.y());
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid InitRCStyles() {
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char kRCText[] =
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Make our dialogs styled like the GNOME HIG.
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      //
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // TODO(evanm): content-area-spacing was introduced in a later
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // version of GTK, so we need to set that manually on all dialogs.
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Perhaps it would make sense to have a shared FixupDialog() function.
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "style \"gnome-dialog\" {\n"
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "  xthickness = 12\n"
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "  GtkDialog::action-area-border = 0\n"
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "  GtkDialog::button-spacing = 6\n"
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "  GtkDialog::content-area-spacing = 18\n"
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "  GtkDialog::content-area-border = 12\n"
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "}\n"
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Note we set it at the "application" priority, so users can override.
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "widget \"GtkDialog\" style : application \"gnome-dialog\"\n"
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Make our about dialog special, so the image is flush with the edge.
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "style \"about-dialog\" {\n"
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "  GtkDialog::action-area-border = 12\n"
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "  GtkDialog::button-spacing = 6\n"
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "  GtkDialog::content-area-spacing = 18\n"
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "  GtkDialog::content-area-border = 0\n"
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "}\n"
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "widget \"about-dialog\" style : application \"about-dialog\"\n";
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_rc_parse_string(kRCText);
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget,
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              bool pack_at_end, int padding) {
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* centering_vbox = gtk_vbox_new(FALSE, 0);
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(centering_vbox), widget, TRUE, FALSE, 0);
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (pack_at_end)
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_end(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return centering_vbox;
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsScreenComposited() {
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkScreen* screen = gdk_screen_get_default();
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gdk_screen_is_composited(screen) == TRUE;
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) {
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<XID> stack;
55572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) {
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // to old school enumeration of all X windows.  Some WMs parent 'top-level'
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // windows in unnamed actual top-level windows (ion WM), so extend the
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // search depth to all children of top-level windows.
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kMaxSearchDepth = 1;
56172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ui::EnumerateAllWindows(delegate, kMaxSearchDepth);
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<XID>::iterator iter;
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (iter = stack.begin(); iter != stack.end(); iter++) {
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (delegate->ShouldStopIterating(*iter))
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetButtonClickableByMouseButtons(GtkWidget* button,
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      bool left, bool middle, bool right) {
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint button_mask = 0;
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (left)
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    button_mask |= 1 << 1;
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (middle)
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    button_mask |= 1 << 2;
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (right)
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    button_mask |= 1 << 3;
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void* userdata = GINT_TO_POINTER(button_mask);
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(button, "button-press-event",
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnMouseButtonPressed), userdata);
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(button, "button-release-event",
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnMouseButtonReleased), userdata);
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetButtonTriggersNavigation(GtkWidget* button) {
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetButtonClickableByMouseButtons(button, true, true, false);
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint MirroredLeftPointForRect(GtkWidget* widget, const gfx::Rect& bounds) {
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!base::i18n::IsRTL())
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return bounds.x();
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return widget->allocation.width - bounds.x() - bounds.width();
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint MirroredXCoordinate(GtkWidget* widget, int x) {
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (base::i18n::IsRTL())
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return widget->allocation.width - x;
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return x;
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WidgetContainsCursor(GtkWidget* widget) {
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint x = 0;
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint y = 0;
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_get_pointer(widget, &x, &y);
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return WidgetBounds(widget).Contains(x, y);
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetWindowIcon(GtkWindow* window) {
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GList* icon_list = GetIconList();
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_set_icon_list(window, icon_list);
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_list_free(icon_list);
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
618dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SetDefaultWindowIcon(GtkWindow* window) {
619dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  GtkIconTheme* theme =
620dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      gtk_icon_theme_get_for_screen(gtk_widget_get_screen(GTK_WIDGET(window)));
621dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
622dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (gtk_icon_theme_has_icon(theme, kIconName)) {
623dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    gtk_window_set_default_icon_name(kIconName);
624dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Sometimes the WM fails to update the icon when we tell it to. The above
625dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // line should be enough to update all existing windows, but it can fail,
626dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // e.g. with Lucid/metacity. The following line seems to fix the common
627dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // case where the first window created doesn't have an icon.
628dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    gtk_window_set_icon_name(window, kIconName);
629dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
630dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    GList* icon_list = GetIconList();
631dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    gtk_window_set_default_icon_list(icon_list);
632dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Same logic applies here.
633dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    gtk_window_set_icon_list(window, icon_list);
634dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    g_list_free(icon_list);
635dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* AddButtonToDialog(GtkWidget* dialog, const gchar* text,
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             const gchar* stock_id, gint response_id) {
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* button = gtk_button_new_with_label(text);
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_button_set_image(GTK_BUTTON(button),
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       gtk_image_new_from_stock(stock_id,
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                GTK_ICON_SIZE_BUTTON));
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button,
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               response_id);
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return button;
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* BuildDialogButton(GtkWidget* dialog, int ids_id,
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             const gchar* stock_id) {
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* button = gtk_button_new_with_mnemonic(
652513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gfx::ConvertAcceleratorsFromWindowsStyle(
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          l10n_util::GetStringUTF8(ids_id)).c_str());
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_button_set_image(GTK_BUTTON(button),
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       gtk_image_new_from_stock(stock_id,
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                GTK_ICON_SIZE_BUTTON));
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return button;
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image) {
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return hbox;
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetLabelColor(GtkWidget* label, const GdkColor* color) {
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_fg(label, GTK_STATE_NORMAL, color);
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, color);
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, color);
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, color);
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* IndentWidget(GtkWidget* content) {
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* content_alignment = gtk_alignment_new(0.0, 0.5, 1.0, 1.0);
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment), 0, 0,
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            gtk_util::kGroupIndent, 0);
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(content_alignment), content);
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return content_alignment;
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid UpdateGtkFontSettings(RendererPreferences* prefs) {
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(prefs);
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // From http://library.gnome.org/devel/gtk/unstable/GtkSettings.html, this is
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the default value for gtk-cursor-blink-time.
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const gint kGtkDefaultCursorBlinkTime = 1200;
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint cursor_blink_time = kGtkDefaultCursorBlinkTime;
690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gboolean cursor_blink = TRUE;
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint antialias = 0;
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint hinting = 0;
693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gchar* hint_style = NULL;
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gchar* rgba_style = NULL;
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_get(gtk_settings_get_default(),
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "gtk-cursor-blink-time", &cursor_blink_time,
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "gtk-cursor-blink", &cursor_blink,
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "gtk-xft-antialias", &antialias,
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "gtk-xft-hinting", &hinting,
700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "gtk-xft-hintstyle", &hint_style,
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "gtk-xft-rgba", &rgba_style,
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               NULL);
703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set some reasonable defaults.
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->should_antialias_text = true;
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->hinting = RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT;
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->subpixel_rendering =
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT;
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cursor_blink) {
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Dividing by 2*1000ms follows the WebKit GTK port and makes the blink
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // frequency appear similar to the omnibox.  Without this the blink is too
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // slow.
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    prefs->caret_blink_interval = cursor_blink_time / 2000.;
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    prefs->caret_blink_interval = 0;
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // g_object_get() doesn't tell us whether the properties were present or not,
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // but if they aren't (because gnome-settings-daemon isn't running), we'll get
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NULL values for the strings.
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (hint_style && rgba_style) {
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    prefs->should_antialias_text = antialias;
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (hinting == 0 || strcmp(hint_style, "hintnone") == 0) {
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->hinting = RENDERER_PREFERENCES_HINTING_NONE;
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (strcmp(hint_style, "hintslight") == 0) {
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->hinting = RENDERER_PREFERENCES_HINTING_SLIGHT;
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (strcmp(hint_style, "hintmedium") == 0) {
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->hinting = RENDERER_PREFERENCES_HINTING_MEDIUM;
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (strcmp(hint_style, "hintfull") == 0) {
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->hinting = RENDERER_PREFERENCES_HINTING_FULL;
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (strcmp(rgba_style, "none") == 0) {
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE;
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (strcmp(rgba_style, "rgb") == 0) {
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB;
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (strcmp(rgba_style, "bgr") == 0) {
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR;
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (strcmp(rgba_style, "vrgb") == 0) {
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB;
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (strcmp(rgba_style, "vbgr") == 0) {
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR;
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (hint_style)
749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_free(hint_style);
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rgba_style)
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_free(rgba_style);
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Point ScreenPoint(GtkWidget* widget) {
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x, y;
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_display_get_pointer(gtk_widget_get_display(widget), NULL, &x, &y,
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          NULL);
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Point(x, y);
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Point ClientPoint(GtkWidget* widget) {
762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x, y;
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_get_pointer(widget, &x, &y);
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Point(x, y);
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
767c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr) {
768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkPoint point = {ltr ? x : width - x, y};
769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return point;
770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DrawTextEntryBackground(GtkWidget* offscreen_entry,
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             GtkWidget* widget_to_draw_on,
774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             GdkRectangle* dirty_rec,
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             GdkRectangle* rec) {
776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkStyle* gtk_owned_style = gtk_rc_get_style(offscreen_entry);
777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // GTK owns the above and we're going to have to make our own copy of it
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // that we can edit.
779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkStyle* our_style = gtk_style_copy(gtk_owned_style);
780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  our_style = gtk_style_attach(our_style, widget_to_draw_on->window);
781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(erg): Draw the focus ring if appropriate...
783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We're using GTK rendering; draw a GTK entry widget onto the background.
785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_paint_shadow(our_style, widget_to_draw_on->window,
786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   GTK_STATE_NORMAL, GTK_SHADOW_IN, dirty_rec,
787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   widget_to_draw_on, "entry",
788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   rec->x, rec->y, rec->width, rec->height);
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw the interior background (not all themes draw the entry background
791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // above; this is a noop on themes that do).
792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint xborder = our_style->xthickness;
793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint yborder = our_style->ythickness;
79421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  gint width = rec->width - 2 * xborder;
79521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  gint height = rec->height - 2 * yborder;
79621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (width > 0 && height > 0) {
79721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    gtk_paint_flat_box(our_style, widget_to_draw_on->window,
79821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       GTK_STATE_NORMAL, GTK_SHADOW_NONE, dirty_rec,
79921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       widget_to_draw_on, "entry_bg",
80021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       rec->x + xborder, rec->y + yborder,
80121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       width, height);
80221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
8044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  gtk_style_detach(our_style);
805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_object_unref(our_style);
806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DrawThemedToolbarBackground(GtkWidget* widget,
809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 cairo_t* cr,
810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 GdkEventExpose* event,
811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 const gfx::Point& tabstrip_origin,
812ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 GtkThemeService* theme_service) {
813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Fill the entire region with the toolbar color.
814ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GdkColor color = theme_service->GetGdkColor(
815ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ThemeService::COLOR_TOOLBAR);
816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_cairo_set_source_color(cr, &color);
817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_fill(cr);
818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The toolbar is supposed to blend in with the active tab, so we have to pass
820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // coordinates for the IDR_THEME_TOOLBAR bitmap relative to the top of the
821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // tab strip.
822ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CairoCachedSurface* background = theme_service->GetSurfaceNamed(
823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDR_THEME_TOOLBAR, widget);
824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  background->SetSource(cr, tabstrip_origin.x(), tabstrip_origin.y());
825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We tile the toolbar background in both directions.
826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_rectangle(cr,
828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  tabstrip_origin.x(),
829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  tabstrip_origin.y(),
830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  event->area.x + event->area.width - tabstrip_origin.x(),
831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  event->area.y + event->area.height - tabstrip_origin.y());
832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cairo_fill(cr);
833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
835c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGdkColor AverageColors(GdkColor color_one, GdkColor color_two) {
836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkColor average_color;
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  average_color.pixel = 0;
838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  average_color.red = (color_one.red + color_two.red) / 2;
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  average_color.green = (color_one.green + color_two.green) / 2;
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  average_color.blue = (color_one.blue + color_two.blue) / 2;
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return average_color;
842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetAlwaysShowImage(GtkWidget* image_menu_item) {
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Compile time check: if it's available, just use the API.
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // GTK_CHECK_VERSION is TRUE if the passed version is compatible.
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if GTK_CHECK_VERSION(2, 16, 1)
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_image_menu_item_set_always_show_image(
849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_IMAGE_MENU_ITEM(image_menu_item), TRUE);
850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Run time check: if the API is not available, set the property manually.
852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This will still only work with GTK 2.16+ as the property doesn't exist
853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in earlier versions.
854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // gtk_check_version() returns NULL if the passed version is compatible.
855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!gtk_check_version(2, 16, 1)) {
856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GValue true_value = { 0 };
857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_value_init(&true_value, G_TYPE_BOOLEAN);
858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_value_set_boolean(&true_value, TRUE);
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_object_set_property(G_OBJECT(image_menu_item), "always-show-image",
860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          &true_value);
861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect GetWidgetRectRelativeToToplevel(GtkWidget* widget) {
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(GTK_WIDGET_REALIZED(widget));
867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(toplevel);
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(GTK_WIDGET_REALIZED(toplevel));
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint x = 0, y = 0;
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_translate_coordinates(widget,
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   toplevel,
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   0, 0,
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   &x, &y);
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Rect(x, y, widget->allocation.width, widget->allocation.height);
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SuppressDefaultPainting(GtkWidget* container) {
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(container, "expose-event",
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(PaintNoBackground), NULL);
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWindowOpenDisposition DispositionForCurrentButtonPressEvent() {
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkEvent* event = gtk_get_current_event();
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!event) {
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NEW_FOREGROUND_TAB;
890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  guint state = event->button.state;
893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_event_free(event);
894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return event_utils::DispositionFromEventFlags(state);
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GrabAllInput(GtkWidget* widget) {
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  guint time = gtk_get_current_event_time();
899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!GTK_WIDGET_VISIBLE(widget))
901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!gdk_pointer_grab(widget->window, TRUE,
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        GdkEventMask(GDK_BUTTON_PRESS_MASK |
905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     GDK_BUTTON_RELEASE_MASK |
906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     GDK_ENTER_NOTIFY_MASK |
907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     GDK_LEAVE_NOTIFY_MASK |
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     GDK_POINTER_MOTION_MASK),
909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        NULL, NULL, time) == 0) {
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!gdk_keyboard_grab(widget->window, TRUE, time) == 0) {
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_display_pointer_ungrab(gdk_drawable_get_display(widget->window), time);
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_grab_add(widget);
919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect WidgetBounds(GtkWidget* widget) {
923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // To quote the gtk docs:
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   Widget coordinates are a bit odd; for historical reasons, they are
926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   defined as widget->window coordinates for widgets that are not
927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   GTK_NO_WINDOW widgets, and are relative to widget->allocation.x,
928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //   widget->allocation.y for widgets that are GTK_NO_WINDOW widgets.
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // So the base is always (0,0).
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Rect(0, 0, widget->allocation.width, widget->allocation.height);
932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetWMLastUserActionTime(GtkWindow* window) {
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_x11_window_set_user_time(GTK_WIDGET(window)->window, XTimeNow());
936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochguint32 XTimeNow() {
939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct timespec ts;
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  clock_gettime(CLOCK_MONOTONIC, &ts);
941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool URLFromPrimarySelection(Profile* profile, GURL* url) {
945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(clipboard);
947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gchar* selection_text = gtk_clipboard_wait_for_text(clipboard);
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!selection_text)
949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Use autocomplete to clean up the text, going so far as to turn it into
952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a search query if necessary.
9534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  AutocompleteMatch match;
95472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  profile->GetAutocompleteClassifier()->Classify(UTF8ToUTF16(selection_text),
95572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      string16(), false, &match, NULL);
956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_free(selection_text);
9574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!match.destination_url.is_valid())
958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  *url = match.destination_url;
961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AddWindowAlphaChannel(GtkWidget* window) {
965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkScreen* screen = gtk_widget_get_screen(window);
966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen);
967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rgba)
968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_colormap(window, rgba);
969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rgba;
971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid GetTextColors(GdkColor* normal_base,
9743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                   GdkColor* selected_base,
9753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                   GdkColor* normal_text,
9763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                   GdkColor* selected_text) {
9773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  GtkWidget* fake_entry = gtk_entry_new();
9783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  GtkStyle* style = gtk_rc_get_style(fake_entry);
9793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
9803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (normal_base)
9813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *normal_base = style->base[GTK_STATE_NORMAL];
9823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (selected_base)
9833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *selected_base = style->base[GTK_STATE_SELECTED];
9843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (normal_text)
9853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *normal_text = style->text[GTK_STATE_NORMAL];
9863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (selected_text)
9873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *selected_text = style->text[GTK_STATE_SELECTED];
9883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
9893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  g_object_ref_sink(fake_entry);
9903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  g_object_unref(fake_entry);
9913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
9923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_CHROMEOS)
994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenGtkWindow* GetLastActiveBrowserWindow() {
99672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (Browser* b = BrowserList::GetLastActive()) {
99772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (b->type() != Browser::TYPE_NORMAL) {
99872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      b = BrowserList::FindBrowserWithType(b->profile(),
99972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                           Browser::TYPE_NORMAL,
100072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                           true);
100172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
100272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
100372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (b)
100472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return GTK_WINDOW(b->window()->GetNativeHandle());
100572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
100672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
100772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return NULL;
100872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
100972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1010dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint GetNativeDialogFlags(GtkWindow* dialog) {
1011dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int flags = chromeos::DIALOG_FLAG_DEFAULT;
1012dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1013dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (gtk_window_get_resizable(dialog))
1014dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    flags |= chromeos::DIALOG_FLAG_RESIZEABLE;
1015dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (gtk_window_get_modal(dialog))
1016dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    flags |= chromeos::DIALOG_FLAG_MODAL;
1017dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1018dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return flags;
1019dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1020dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWindow* GetDialogTransientParent(GtkWindow* dialog) {
1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWindow* parent = gtk_window_get_transient_for(dialog);
1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!parent)
102472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    parent = GetLastActiveBrowserWindow();
1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return parent;
1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ShowDialog(GtkWidget* dialog) {
1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure all controls are visible so that we get correct size.
1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get dialog window size.
1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint width = 0;
1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint height = 0;
1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_get_size(GTK_WINDOW(dialog), &width, &height);
1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dialog,
1040dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      GetNativeDialogFlags(GTK_WINDOW(dialog)),
1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gfx::Size(width, height),
1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gfx::Size());
1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ShowDialogWithLocalizedSize(GtkWidget* dialog,
1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 int width_id,
1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 int height_id,
1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 bool resizeable) {
1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int width = (width_id == -1) ? 0 :
1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      views::Window::GetLocalizedContentsWidth(width_id);
1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int height = (height_id == -1) ? 0 :
1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      views::Window::GetLocalizedContentsHeight(height_id);
1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dialog,
1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      resizeable ? chromeos::DIALOG_FLAG_RESIZEABLE :
1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   chromeos::DIALOG_FLAG_DEFAULT,
1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gfx::Size(width, height),
1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gfx::Size());
1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1062dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ShowDialogWithMinLocalizedWidth(GtkWidget* dialog,
1063dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     int width_id) {
1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int width = (width_id == -1) ? 0 :
1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      views::Window::GetLocalizedContentsWidth(width_id);
1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dialog,
1069dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      GetNativeDialogFlags(GTK_WINDOW(dialog)),
1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gfx::Size(),
1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gfx::Size(width, 0));
1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PresentWindow(GtkWidget* window, int timestamp) {
1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWindow* host_window = chromeos::GetNativeDialogWindow(window);
1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!host_window)
1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      host_window = GTK_WINDOW(window);
1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (timestamp)
1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_present_with_time(host_window, timestamp);
1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_present(host_window);
1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWindow* GetDialogWindow(GtkWidget* dialog) {
1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return chromeos::GetNativeDialogWindow(dialog);
1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect GetDialogBounds(GtkWidget* dialog) {
1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return chromeos::GetNativeDialogContentsBounds(dialog);
1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ShowDialog(GtkWidget* dialog) {
1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(dialog);
1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ShowDialogWithLocalizedSize(GtkWidget* dialog,
1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 int width_id,
1100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 int height_id,
1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 bool resizeable) {
1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_realize(dialog);
1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetWindowSizeFromResources(GTK_WINDOW(dialog),
1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             width_id,
1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             height_id,
1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             resizeable);
1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(dialog);
1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ShowDialogWithMinLocalizedWidth(GtkWidget* dialog,
1111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     int width_id) {
1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(dialog);
1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Suggest a minimum size.
1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint width;
1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkRequisition req;
1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_size_request(dialog, &req);
1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::GetWidgetSizeFromResources(dialog, width_id, 0, &width, NULL);
1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (width > req.width)
1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(dialog, width, -1);
1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PresentWindow(GtkWidget* window, int timestamp) {
1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (timestamp)
1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_present_with_time(GTK_WINDOW(window), timestamp);
1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_present(GTK_WINDOW(window));
1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWindow* GetDialogWindow(GtkWidget* dialog) {
1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GTK_WINDOW(dialog);
1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect GetDialogBounds(GtkWidget* dialog) {
1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gint x = 0, y = 0, width = 1, height = 1;
1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_get_position(GTK_WINDOW(dialog), &x, &y);
1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_get_size(GTK_WINDOW(dialog), &width, &height);
1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Rect(x, y, width, height);
1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
11414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstring16 GetStockPreferencesMenuLabel() {
11453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  GtkStockItem stock_item;
11463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  string16 preferences;
11473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (gtk_stock_lookup(GTK_STOCK_PREFERENCES, &stock_item)) {
11483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const char16 kUnderscore[] = { '_', 0 };
11493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    RemoveChars(UTF8ToUTF16(stock_item.label), kUnderscore, &preferences);
11503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
11513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return preferences;
11523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool IsWidgetAncestryVisible(GtkWidget* widget) {
11553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  GtkWidget* parent = widget;
11563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  while (parent && GTK_WIDGET_VISIBLE(parent))
11573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    parent = parent->parent;
11583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return !parent;
11593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SetLabelWidth(GtkWidget* label, int pixel_width) {
11623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
116372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
11643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Do the simple thing in LTR because the bug only affects right-aligned
11663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // text. Also, when using the workaround, the label tries to maintain
11673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // uniform line-length, which we don't really want.
11683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (gtk_widget_get_direction(label) == GTK_TEXT_DIR_LTR) {
11693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    gtk_widget_set_size_request(label, pixel_width, -1);
11703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
11713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // The label has to be realized before we can adjust its width.
11723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (GTK_WIDGET_REALIZED(label)) {
11733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      OnLabelRealize(label, GINT_TO_POINTER(pixel_width));
11743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
11753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      g_signal_connect(label, "realize", G_CALLBACK(OnLabelRealize),
11763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       GINT_TO_POINTER(pixel_width));
11773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
11783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
11793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label) {
11823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  GtkRequisition size;
11833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_NONE);
11843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gtk_widget_set_size_request(label, -1, -1);
11853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gtk_widget_size_request(label, &size);
11863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gtk_widget_set_size_request(label, size.width, size.height);
11873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
11883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1190731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickGdkDragAction WebDragOpToGdkDragAction(WebDragOperationsMask op) {
1191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  GdkDragAction action = static_cast<GdkDragAction>(0);
1192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (op & WebDragOperationCopy)
1193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    action = static_cast<GdkDragAction>(action | GDK_ACTION_COPY);
1194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (op & WebDragOperationLink)
1195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    action = static_cast<GdkDragAction>(action | GDK_ACTION_LINK);
1196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (op & WebDragOperationMove)
1197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    action = static_cast<GdkDragAction>(action | GDK_ACTION_MOVE);
1198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return action;
1199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1201731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickWebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action) {
1202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  WebDragOperationsMask op = WebDragOperationNone;
1203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (action & GDK_ACTION_COPY)
1204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    op = static_cast<WebDragOperationsMask>(op | WebDragOperationCopy);
1205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (action & GDK_ACTION_LINK)
1206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    op = static_cast<WebDragOperationsMask>(op | WebDragOperationLink);
1207731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (action & GDK_ACTION_MOVE)
1208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    op = static_cast<WebDragOperationsMask>(op | WebDragOperationMove);
1209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return op;
1210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1212513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ApplyMessageDialogQuirks(GtkWidget* dialog) {
1213513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (gtk_window_get_modal(GTK_WINDOW(dialog))) {
1214513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // Work around a KDE 3 window manager bug.
1215513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_ptr<base::Environment> env(base::Environment::Create());
1216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (base::nix::DESKTOP_ENVIRONMENT_KDE3 ==
1217513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        base::nix::GetDesktopEnvironment(env.get()))
1218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
1219513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
1220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
1221731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
12224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Performs Cut/Copy/Paste operation on the |window|.
12234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// If the current render view is focused, then just call the specified |method|
12244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// against the current render view host, otherwise emit the specified |signal|
12254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// against the focused widget.
12264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// TODO(suzhe): This approach does not work for plugins.
12274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid DoCutCopyPaste(BrowserWindow* window,
12284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                    void (RenderViewHost::*method)(),
12294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                    const char* signal) {
12304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  GtkWidget* widget = GetBrowserWindowFocusedWidget(window);
12314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (widget == NULL)
12324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return;  // Do nothing if no focused widget.
12334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
12344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  TabContents* current_tab = GetBrowserWindowSelectedTabContents(window);
12354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (current_tab && widget == current_tab->GetContentNativeView()) {
12364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    (current_tab->render_view_host()->*method)();
12374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  } else {
12384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    guint id;
12394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if ((id = g_signal_lookup(signal, G_OBJECT_TYPE(widget))) != 0)
12404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      g_signal_emit(widget, id, 0);
12414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
12424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
12434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
12444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid DoCut(BrowserWindow* window) {
12454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DoCutCopyPaste(window, &RenderViewHost::Cut, "cut-clipboard");
12464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
12474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
12484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid DoCopy(BrowserWindow* window) {
12494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DoCutCopyPaste(window, &RenderViewHost::Copy, "copy-clipboard");
12504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
12514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
12524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid DoPaste(BrowserWindow* window) {
12534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DoCutCopyPaste(window, &RenderViewHost::Paste, "paste-clipboard");
12544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
12554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace gtk_util
1257