| Index: chrome/browser/gtk/gtk_util.cc
|
| ===================================================================
|
| --- chrome/browser/gtk/gtk_util.cc (revision 71352)
|
| +++ chrome/browser/gtk/gtk_util.cc (working copy)
|
| @@ -1,1250 +0,0 @@
|
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/gtk/gtk_util.h"
|
| -
|
| -#include <cairo/cairo.h>
|
| -#include <gtk/gtk.h>
|
| -#include <gdk/gdkx.h>
|
| -
|
| -#include <cstdarg>
|
| -#include <map>
|
| -
|
| -#include "app/l10n_util.h"
|
| -#include "app/resource_bundle.h"
|
| -#include "app/x11_util.h"
|
| -#include "base/environment.h"
|
| -#include "base/i18n/rtl.h"
|
| -#include "base/linux_util.h"
|
| -#include "base/logging.h"
|
| -#include "base/nix/xdg_util.h"
|
| -#include "base/string_number_conversions.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "chrome/browser/autocomplete/autocomplete.h"
|
| -#include "chrome/browser/autocomplete/autocomplete_classifier.h"
|
| -#include "chrome/browser/autocomplete/autocomplete_match.h"
|
| -#include "chrome/browser/browser_list.h"
|
| -#include "chrome/browser/browser_window.h"
|
| -#include "chrome/browser/gtk/cairo_cached_surface.h"
|
| -#include "chrome/browser/gtk/gtk_theme_provider.h"
|
| -#include "chrome/browser/profiles/profile.h"
|
| -#include "chrome/browser/renderer_host/render_view_host.h"
|
| -#include "chrome/browser/tab_contents/tab_contents.h"
|
| -#include "chrome/common/renderer_preferences.h"
|
| -#include "gfx/gtk_util.h"
|
| -#include "googleurl/src/gurl.h"
|
| -#include "grit/theme_resources.h"
|
| -#include "third_party/skia/include/core/SkBitmap.h"
|
| -#include "third_party/skia/include/core/SkColor.h"
|
| -
|
| -#if defined(OS_CHROMEOS)
|
| -#include "chrome/browser/chromeos/frame/browser_view.h"
|
| -#include "chrome/browser/chromeos/native_dialog_window.h"
|
| -#include "chrome/browser/chromeos/options/options_window_view.h"
|
| -#include "views/window/window.h"
|
| -#else
|
| -#include "chrome/browser/gtk/browser_window_gtk.h"
|
| -#endif
|
| -
|
| -using WebKit::WebDragOperationsMask;
|
| -using WebKit::WebDragOperation;
|
| -using WebKit::WebDragOperationNone;
|
| -using WebKit::WebDragOperationCopy;
|
| -using WebKit::WebDragOperationLink;
|
| -using WebKit::WebDragOperationMove;
|
| -
|
| -namespace {
|
| -
|
| -const char kBoldLabelMarkup[] = "<span weight='bold'>%s</span>";
|
| -
|
| -// Callback used in RemoveAllChildren.
|
| -void RemoveWidget(GtkWidget* widget, gpointer container) {
|
| - gtk_container_remove(GTK_CONTAINER(container), widget);
|
| -}
|
| -
|
| -// These two functions are copped almost directly from gtk core. The only
|
| -// difference is that they accept middle clicks.
|
| -gboolean OnMouseButtonPressed(GtkWidget* widget, GdkEventButton* event,
|
| - gpointer userdata) {
|
| - if (event->type == GDK_BUTTON_PRESS) {
|
| - if (gtk_button_get_focus_on_click(GTK_BUTTON(widget)) &&
|
| - !GTK_WIDGET_HAS_FOCUS(widget)) {
|
| - gtk_widget_grab_focus(widget);
|
| - }
|
| -
|
| - gint button_mask = GPOINTER_TO_INT(userdata);
|
| - if (button_mask & (1 << event->button))
|
| - gtk_button_pressed(GTK_BUTTON(widget));
|
| - }
|
| -
|
| - return TRUE;
|
| -}
|
| -
|
| -gboolean OnMouseButtonReleased(GtkWidget* widget, GdkEventButton* event,
|
| - gpointer userdata) {
|
| - gint button_mask = GPOINTER_TO_INT(userdata);
|
| - if (button_mask && (1 << event->button))
|
| - gtk_button_released(GTK_BUTTON(widget));
|
| -
|
| - return TRUE;
|
| -}
|
| -
|
| -// Returns the approximate number of characters that can horizontally fit in
|
| -// |pixel_width| pixels.
|
| -int GetCharacterWidthForPixels(GtkWidget* widget, int pixel_width) {
|
| - DCHECK(GTK_WIDGET_REALIZED(widget))
|
| - << " widget must be realized to compute font metrics correctly";
|
| -
|
| - PangoContext* context = gtk_widget_create_pango_context(widget);
|
| - PangoFontMetrics* metrics = pango_context_get_metrics(context,
|
| - widget->style->font_desc, pango_context_get_language(context));
|
| -
|
| - // This technique (max of char and digit widths) matches the code in
|
| - // gtklabel.c.
|
| - int char_width = pixel_width * PANGO_SCALE /
|
| - std::max(pango_font_metrics_get_approximate_char_width(metrics),
|
| - pango_font_metrics_get_approximate_digit_width(metrics));
|
| -
|
| - pango_font_metrics_unref(metrics);
|
| - g_object_unref(context);
|
| -
|
| - return char_width;
|
| -}
|
| -
|
| -void OnLabelRealize(GtkWidget* label, gpointer pixel_width) {
|
| - gtk_label_set_width_chars(
|
| - GTK_LABEL(label),
|
| - GetCharacterWidthForPixels(label,GPOINTER_TO_INT(pixel_width)));
|
| -}
|
| -
|
| -// Ownership of |icon_list| is passed to the caller.
|
| -GList* GetIconList() {
|
| - ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| - GList* icon_list = NULL;
|
| - icon_list = g_list_append(icon_list, rb.GetPixbufNamed(IDR_PRODUCT_ICON_32));
|
| - icon_list = g_list_append(icon_list, rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
|
| - return icon_list;
|
| -}
|
| -
|
| -// Expose event handler for a container that simply suppresses the default
|
| -// drawing and propagates the expose event to the container's children.
|
| -gboolean PaintNoBackground(GtkWidget* widget,
|
| - GdkEventExpose* event,
|
| - gpointer unused) {
|
| - GList* children = gtk_container_get_children(GTK_CONTAINER(widget));
|
| - for (GList* item = children; item; item = item->next) {
|
| - gtk_container_propagate_expose(GTK_CONTAINER(widget),
|
| - GTK_WIDGET(item->data),
|
| - event);
|
| - }
|
| - g_list_free(children);
|
| -
|
| - return TRUE;
|
| -}
|
| -
|
| -#if defined(OS_CHROMEOS)
|
| -
|
| -TabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) {
|
| - chromeos::BrowserView* browser_view = static_cast<chromeos::BrowserView*>(
|
| - window);
|
| - return browser_view->GetSelectedTabContents();
|
| -}
|
| -
|
| -GtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) {
|
| - gfx::NativeView widget = gtk_window_get_focus(window->GetNativeHandle());
|
| -
|
| - if (widget == NULL) {
|
| - chromeos::BrowserView* browser_view = static_cast<chromeos::BrowserView*>(
|
| - window);
|
| - widget = browser_view->saved_focused_widget();
|
| - }
|
| -
|
| - return widget;
|
| -}
|
| -
|
| -#else
|
| -
|
| -TabContents* GetBrowserWindowSelectedTabContents(BrowserWindow* window) {
|
| - BrowserWindowGtk* browser_window = static_cast<BrowserWindowGtk*>(
|
| - window);
|
| - return browser_window->browser()->GetSelectedTabContents();
|
| -}
|
| -
|
| -GtkWidget* GetBrowserWindowFocusedWidget(BrowserWindow* window) {
|
| - return gtk_window_get_focus(window->GetNativeHandle());
|
| -}
|
| -
|
| -#endif
|
| -
|
| -} // namespace
|
| -
|
| -namespace event_utils {
|
| -
|
| -WindowOpenDisposition DispositionFromEventFlags(guint event_flags) {
|
| - if ((event_flags & GDK_BUTTON2_MASK) || (event_flags & GDK_CONTROL_MASK)) {
|
| - return (event_flags & GDK_SHIFT_MASK) ?
|
| - NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
|
| - }
|
| -
|
| - if (event_flags & GDK_SHIFT_MASK)
|
| - return NEW_WINDOW;
|
| - return false /*event.IsAltDown()*/ ? SAVE_TO_DISK : CURRENT_TAB;
|
| -}
|
| -
|
| -} // namespace event_utils
|
| -
|
| -namespace gtk_util {
|
| -
|
| -const GdkColor kGdkWhite = GDK_COLOR_RGB(0xff, 0xff, 0xff);
|
| -const GdkColor kGdkGray = GDK_COLOR_RGB(0x7f, 0x7f, 0x7f);
|
| -const GdkColor kGdkBlack = GDK_COLOR_RGB(0x00, 0x00, 0x00);
|
| -const GdkColor kGdkGreen = GDK_COLOR_RGB(0x00, 0xff, 0x00);
|
| -
|
| -GtkWidget* CreateLabeledControlsGroup(std::vector<GtkWidget*>* labels,
|
| - const char* text, ...) {
|
| - va_list ap;
|
| - va_start(ap, text);
|
| - GtkWidget* table = gtk_table_new(0, 2, FALSE);
|
| - gtk_table_set_col_spacing(GTK_TABLE(table), 0, kLabelSpacing);
|
| - gtk_table_set_row_spacings(GTK_TABLE(table), kControlSpacing);
|
| -
|
| - for (guint row = 0; text; ++row) {
|
| - gtk_table_resize(GTK_TABLE(table), row + 1, 2);
|
| - GtkWidget* control = va_arg(ap, GtkWidget*);
|
| - GtkWidget* label = gtk_label_new(text);
|
| - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
| - if (labels)
|
| - labels->push_back(label);
|
| -
|
| - gtk_table_attach(GTK_TABLE(table), label,
|
| - 0, 1, row, row + 1,
|
| - GTK_FILL, GTK_FILL,
|
| - 0, 0);
|
| - gtk_table_attach_defaults(GTK_TABLE(table), control,
|
| - 1, 2, row, row + 1);
|
| - text = va_arg(ap, const char*);
|
| - }
|
| - va_end(ap);
|
| -
|
| - return table;
|
| -}
|
| -
|
| -GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color,
|
| - int top, int bottom, int left, int right) {
|
| - // Use a GtkEventBox to get the background painted. However, we can't just
|
| - // use a container border, since it won't paint there. Use an alignment
|
| - // inside to get the sizes exactly of how we want the border painted.
|
| - GtkWidget* ebox = gtk_event_box_new();
|
| - if (color)
|
| - gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, color);
|
| - GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
|
| - gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), top, bottom, left, right);
|
| - gtk_container_add(GTK_CONTAINER(alignment), child);
|
| - gtk_container_add(GTK_CONTAINER(ebox), alignment);
|
| - return ebox;
|
| -}
|
| -
|
| -GtkWidget* LeftAlignMisc(GtkWidget* misc) {
|
| - gtk_misc_set_alignment(GTK_MISC(misc), 0, 0.5);
|
| - return misc;
|
| -}
|
| -
|
| -GtkWidget* CreateBoldLabel(const std::string& text) {
|
| - GtkWidget* label = gtk_label_new(NULL);
|
| - char* markup = g_markup_printf_escaped(kBoldLabelMarkup, text.c_str());
|
| - gtk_label_set_markup(GTK_LABEL(label), markup);
|
| - g_free(markup);
|
| -
|
| - return LeftAlignMisc(label);
|
| -}
|
| -
|
| -void GetWidgetSizeFromCharacters(
|
| - GtkWidget* widget, double width_chars, double height_lines,
|
| - int* width, int* height) {
|
| - DCHECK(GTK_WIDGET_REALIZED(widget))
|
| - << " widget must be realized to compute font metrics correctly";
|
| - PangoContext* context = gtk_widget_create_pango_context(widget);
|
| - PangoFontMetrics* metrics = pango_context_get_metrics(context,
|
| - widget->style->font_desc, pango_context_get_language(context));
|
| - if (width) {
|
| - *width = static_cast<int>(
|
| - pango_font_metrics_get_approximate_char_width(metrics) *
|
| - width_chars / PANGO_SCALE);
|
| - }
|
| - if (height) {
|
| - *height = static_cast<int>(
|
| - (pango_font_metrics_get_ascent(metrics) +
|
| - pango_font_metrics_get_descent(metrics)) *
|
| - height_lines / PANGO_SCALE);
|
| - }
|
| - pango_font_metrics_unref(metrics);
|
| - g_object_unref(context);
|
| -}
|
| -
|
| -void GetWidgetSizeFromResources(
|
| - GtkWidget* widget, int width_chars, int height_lines,
|
| - int* width, int* height) {
|
| - DCHECK(GTK_WIDGET_REALIZED(widget))
|
| - << " widget must be realized to compute font metrics correctly";
|
| -
|
| - double chars = 0;
|
| - if (width)
|
| - base::StringToDouble(l10n_util::GetStringUTF8(width_chars), &chars);
|
| -
|
| - double lines = 0;
|
| - if (height)
|
| - base::StringToDouble(l10n_util::GetStringUTF8(height_lines), &lines);
|
| -
|
| - GetWidgetSizeFromCharacters(widget, chars, lines, width, height);
|
| -}
|
| -
|
| -void SetWindowSizeFromResources(GtkWindow* window,
|
| - int width_id, int height_id, bool resizable) {
|
| - int width = -1;
|
| - int height = -1;
|
| - gtk_util::GetWidgetSizeFromResources(GTK_WIDGET(window), width_id, height_id,
|
| - (width_id != -1) ? &width : NULL,
|
| - (height_id != -1) ? &height : NULL);
|
| -
|
| - if (resizable) {
|
| - gtk_window_set_default_size(window, width, height);
|
| - } else {
|
| - // For a non-resizable window, GTK tries to snap the window size
|
| - // to the minimum size around the content. We use the sizes in
|
| - // the resources to set *minimum* window size to allow windows
|
| - // with long titles to be wide enough to display their titles.
|
| - //
|
| - // But if GTK wants to make the window *wider* due to very wide
|
| - // controls, we should allow that too, so be careful to pick the
|
| - // wider of the resources size and the natural window size.
|
| -
|
| - gtk_widget_show_all(GTK_BIN(window)->child);
|
| - GtkRequisition requisition;
|
| - gtk_widget_size_request(GTK_WIDGET(window), &requisition);
|
| - gtk_widget_set_size_request(
|
| - GTK_WIDGET(window),
|
| - width == -1 ? -1 : std::max(width, requisition.width),
|
| - height == -1 ? -1 : std::max(height, requisition.height));
|
| - }
|
| - gtk_window_set_resizable(window, resizable ? TRUE : FALSE);
|
| -}
|
| -
|
| -void CenterOverWindow(GtkWindow* window, GtkWindow* parent) {
|
| - gfx::Rect frame_bounds = gtk_util::GetWidgetScreenBounds(GTK_WIDGET(parent));
|
| - gfx::Point origin = frame_bounds.origin();
|
| - gfx::Size size = gtk_util::GetWidgetSize(GTK_WIDGET(window));
|
| - origin.Offset(
|
| - (frame_bounds.width() - size.width()) / 2,
|
| - (frame_bounds.height() - size.height()) / 2);
|
| -
|
| - // Prevent moving window out of monitor bounds.
|
| - GdkScreen* screen = gtk_window_get_screen(parent);
|
| - if (screen) {
|
| - // It would be better to check against workarea for given monitor
|
| - // but getting workarea for particular monitor is tricky.
|
| - gint monitor = gdk_screen_get_monitor_at_window(screen,
|
| - GTK_WIDGET(parent)->window);
|
| - GdkRectangle rect;
|
| - gdk_screen_get_monitor_geometry(screen, monitor, &rect);
|
| -
|
| - // Check the right bottom corner.
|
| - if (origin.x() > rect.x + rect.width - size.width())
|
| - origin.set_x(rect.x + rect.width - size.width());
|
| - if (origin.y() > rect.y + rect.height - size.height())
|
| - origin.set_y(rect.y + rect.height - size.height());
|
| -
|
| - // Check the left top corner.
|
| - if (origin.x() < rect.x)
|
| - origin.set_x(rect.x);
|
| - if (origin.y() < rect.y)
|
| - origin.set_y(rect.y);
|
| - }
|
| -
|
| - gtk_window_move(window, origin.x(), origin.y());
|
| -
|
| - // Move to user expected desktop if window is already visible.
|
| - if (GTK_WIDGET(window)->window) {
|
| - x11_util::ChangeWindowDesktop(
|
| - x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(window)),
|
| - x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(parent)));
|
| - }
|
| -}
|
| -
|
| -void MakeAppModalWindowGroup() {
|
| -#if GTK_CHECK_VERSION(2, 14, 0)
|
| - // Older versions of GTK+ don't give us gtk_window_group_list() which is what
|
| - // we need to add current non-browser modal dialogs to the list. If
|
| - // we have 2.14+ we can do things the correct way.
|
| - GtkWindowGroup* window_group = gtk_window_group_new();
|
| - for (BrowserList::const_iterator it = BrowserList::begin();
|
| - it != BrowserList::end(); ++it) {
|
| - // List all windows in this current group
|
| - GtkWindowGroup* old_group =
|
| - gtk_window_get_group((*it)->window()->GetNativeHandle());
|
| -
|
| - GList* all_windows = gtk_window_group_list_windows(old_group);
|
| - for (GList* window = all_windows; window; window = window->next) {
|
| - gtk_window_group_add_window(window_group, GTK_WINDOW(window->data));
|
| - }
|
| - g_list_free(all_windows);
|
| - }
|
| - g_object_unref(window_group);
|
| -#else
|
| - // Otherwise just grab all browser windows and be slightly broken.
|
| - GtkWindowGroup* window_group = gtk_window_group_new();
|
| - for (BrowserList::const_iterator it = BrowserList::begin();
|
| - it != BrowserList::end(); ++it) {
|
| - gtk_window_group_add_window(window_group,
|
| - (*it)->window()->GetNativeHandle());
|
| - }
|
| - g_object_unref(window_group);
|
| -#endif
|
| -}
|
| -
|
| -void AppModalDismissedUngroupWindows() {
|
| -#if GTK_CHECK_VERSION(2, 14, 0)
|
| - if (BrowserList::begin() != BrowserList::end()) {
|
| - std::vector<GtkWindow*> transient_windows;
|
| -
|
| - // All windows should be part of one big modal group right now.
|
| - GtkWindowGroup* window_group = gtk_window_get_group(
|
| - (*BrowserList::begin())->window()->GetNativeHandle());
|
| - GList* windows = gtk_window_group_list_windows(window_group);
|
| -
|
| - for (GList* item = windows; item; item = item->next) {
|
| - GtkWindow* window = GTK_WINDOW(item->data);
|
| - GtkWindow* transient_for = gtk_window_get_transient_for(window);
|
| - if (transient_for) {
|
| - transient_windows.push_back(window);
|
| - } else {
|
| - GtkWindowGroup* window_group = gtk_window_group_new();
|
| - gtk_window_group_add_window(window_group, window);
|
| - g_object_unref(window_group);
|
| - }
|
| - }
|
| -
|
| - // Put each transient window in the same group as its transient parent.
|
| - for (std::vector<GtkWindow*>::iterator it = transient_windows.begin();
|
| - it != transient_windows.end(); ++it) {
|
| - GtkWindow* transient_parent = gtk_window_get_transient_for(*it);
|
| - GtkWindowGroup* group = gtk_window_get_group(transient_parent);
|
| - gtk_window_group_add_window(group, *it);
|
| - }
|
| - }
|
| -#else
|
| - // This is slightly broken in the case where a different window had a dialog,
|
| - // but its the best we can do since we don't have newer gtk stuff.
|
| - for (BrowserList::const_iterator it = BrowserList::begin();
|
| - it != BrowserList::end(); ++it) {
|
| - GtkWindowGroup* window_group = gtk_window_group_new();
|
| - gtk_window_group_add_window(window_group,
|
| - (*it)->window()->GetNativeHandle());
|
| - g_object_unref(window_group);
|
| - }
|
| -#endif
|
| -}
|
| -
|
| -void RemoveAllChildren(GtkWidget* container) {
|
| - gtk_container_foreach(GTK_CONTAINER(container), RemoveWidget, container);
|
| -}
|
| -
|
| -void ForceFontSizePixels(GtkWidget* widget, double size_pixels) {
|
| - GtkStyle* style = widget->style;
|
| - PangoFontDescription* font_desc = style->font_desc;
|
| - // pango_font_description_set_absolute_size sets the font size in device
|
| - // units, which for us is pixels.
|
| - pango_font_description_set_absolute_size(font_desc,
|
| - PANGO_SCALE * size_pixels);
|
| - gtk_widget_modify_font(widget, font_desc);
|
| -}
|
| -
|
| -void UndoForceFontSize(GtkWidget* widget) {
|
| - gtk_widget_modify_font(widget, NULL);
|
| -}
|
| -
|
| -gfx::Point GetWidgetScreenPosition(GtkWidget* widget) {
|
| - if (!widget->window) {
|
| - NOTREACHED() << "Must only be called on realized widgets.";
|
| - return gfx::Point(0, 0);
|
| - }
|
| -
|
| - gint x, y;
|
| - gdk_window_get_origin(widget->window, &x, &y);
|
| -
|
| - if (!GTK_IS_WINDOW(widget)) {
|
| - x += widget->allocation.x;
|
| - y += widget->allocation.y;
|
| - }
|
| -
|
| - return gfx::Point(x, y);
|
| -}
|
| -
|
| -gfx::Rect GetWidgetScreenBounds(GtkWidget* widget) {
|
| - gfx::Point position = GetWidgetScreenPosition(widget);
|
| - return gfx::Rect(position.x(), position.y(),
|
| - widget->allocation.width, widget->allocation.height);
|
| -}
|
| -
|
| -gfx::Size GetWidgetSize(GtkWidget* widget) {
|
| - GtkRequisition size;
|
| - gtk_widget_size_request(widget, &size);
|
| - return gfx::Size(size.width, size.height);
|
| -}
|
| -
|
| -void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p) {
|
| - DCHECK(widget);
|
| - DCHECK(p);
|
| -
|
| - gfx::Point position = GetWidgetScreenPosition(widget);
|
| - p->SetPoint(p->x() + position.x(), p->y() + position.y());
|
| -}
|
| -
|
| -void InitRCStyles() {
|
| - static const char kRCText[] =
|
| - // Make our dialogs styled like the GNOME HIG.
|
| - //
|
| - // TODO(evanm): content-area-spacing was introduced in a later
|
| - // version of GTK, so we need to set that manually on all dialogs.
|
| - // Perhaps it would make sense to have a shared FixupDialog() function.
|
| - "style \"gnome-dialog\" {\n"
|
| - " xthickness = 12\n"
|
| - " GtkDialog::action-area-border = 0\n"
|
| - " GtkDialog::button-spacing = 6\n"
|
| - " GtkDialog::content-area-spacing = 18\n"
|
| - " GtkDialog::content-area-border = 12\n"
|
| - "}\n"
|
| - // Note we set it at the "application" priority, so users can override.
|
| - "widget \"GtkDialog\" style : application \"gnome-dialog\"\n"
|
| -
|
| - // Make our about dialog special, so the image is flush with the edge.
|
| - "style \"about-dialog\" {\n"
|
| - " GtkDialog::action-area-border = 12\n"
|
| - " GtkDialog::button-spacing = 6\n"
|
| - " GtkDialog::content-area-spacing = 18\n"
|
| - " GtkDialog::content-area-border = 0\n"
|
| - "}\n"
|
| - "widget \"about-dialog\" style : application \"about-dialog\"\n";
|
| -
|
| - gtk_rc_parse_string(kRCText);
|
| -}
|
| -
|
| -GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget,
|
| - bool pack_at_end, int padding) {
|
| - GtkWidget* centering_vbox = gtk_vbox_new(FALSE, 0);
|
| - gtk_box_pack_start(GTK_BOX(centering_vbox), widget, TRUE, FALSE, 0);
|
| - if (pack_at_end)
|
| - gtk_box_pack_end(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
|
| - else
|
| - gtk_box_pack_start(GTK_BOX(hbox), centering_vbox, FALSE, FALSE, padding);
|
| -
|
| - return centering_vbox;
|
| -}
|
| -
|
| -bool IsScreenComposited() {
|
| - GdkScreen* screen = gdk_screen_get_default();
|
| - return gdk_screen_is_composited(screen) == TRUE;
|
| -}
|
| -
|
| -void EnumerateTopLevelWindows(x11_util::EnumerateWindowsDelegate* delegate) {
|
| - std::vector<XID> stack;
|
| - if (!x11_util::GetXWindowStack(&stack)) {
|
| - // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
|
| - // to old school enumeration of all X windows. Some WMs parent 'top-level'
|
| - // windows in unnamed actual top-level windows (ion WM), so extend the
|
| - // search depth to all children of top-level windows.
|
| - const int kMaxSearchDepth = 1;
|
| - x11_util::EnumerateAllWindows(delegate, kMaxSearchDepth);
|
| - return;
|
| - }
|
| -
|
| - std::vector<XID>::iterator iter;
|
| - for (iter = stack.begin(); iter != stack.end(); iter++) {
|
| - if (delegate->ShouldStopIterating(*iter))
|
| - return;
|
| - }
|
| -}
|
| -
|
| -void SetButtonClickableByMouseButtons(GtkWidget* button,
|
| - bool left, bool middle, bool right) {
|
| - gint button_mask = 0;
|
| - if (left)
|
| - button_mask |= 1 << 1;
|
| - if (middle)
|
| - button_mask |= 1 << 2;
|
| - if (right)
|
| - button_mask |= 1 << 3;
|
| - void* userdata = GINT_TO_POINTER(button_mask);
|
| -
|
| - g_signal_connect(button, "button-press-event",
|
| - G_CALLBACK(OnMouseButtonPressed), userdata);
|
| - g_signal_connect(button, "button-release-event",
|
| - G_CALLBACK(OnMouseButtonReleased), userdata);
|
| -}
|
| -
|
| -void SetButtonTriggersNavigation(GtkWidget* button) {
|
| - SetButtonClickableByMouseButtons(button, true, true, false);
|
| -}
|
| -
|
| -int MirroredLeftPointForRect(GtkWidget* widget, const gfx::Rect& bounds) {
|
| - if (!base::i18n::IsRTL())
|
| - return bounds.x();
|
| - return widget->allocation.width - bounds.x() - bounds.width();
|
| -}
|
| -
|
| -int MirroredXCoordinate(GtkWidget* widget, int x) {
|
| - if (base::i18n::IsRTL())
|
| - return widget->allocation.width - x;
|
| - return x;
|
| -}
|
| -
|
| -bool WidgetContainsCursor(GtkWidget* widget) {
|
| - gint x = 0;
|
| - gint y = 0;
|
| - gtk_widget_get_pointer(widget, &x, &y);
|
| - return WidgetBounds(widget).Contains(x, y);
|
| -}
|
| -
|
| -void SetWindowIcon(GtkWindow* window) {
|
| - GList* icon_list = GetIconList();
|
| - gtk_window_set_icon_list(window, icon_list);
|
| - g_list_free(icon_list);
|
| -}
|
| -
|
| -void SetDefaultWindowIcon() {
|
| - GList* icon_list = GetIconList();
|
| - gtk_window_set_default_icon_list(icon_list);
|
| - g_list_free(icon_list);
|
| -}
|
| -
|
| -GtkWidget* AddButtonToDialog(GtkWidget* dialog, const gchar* text,
|
| - const gchar* stock_id, gint response_id) {
|
| - GtkWidget* button = gtk_button_new_with_label(text);
|
| - gtk_button_set_image(GTK_BUTTON(button),
|
| - gtk_image_new_from_stock(stock_id,
|
| - GTK_ICON_SIZE_BUTTON));
|
| - gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button,
|
| - response_id);
|
| - return button;
|
| -}
|
| -
|
| -GtkWidget* BuildDialogButton(GtkWidget* dialog, int ids_id,
|
| - const gchar* stock_id) {
|
| - GtkWidget* button = gtk_button_new_with_mnemonic(
|
| - gfx::ConvertAcceleratorsFromWindowsStyle(
|
| - l10n_util::GetStringUTF8(ids_id)).c_str());
|
| - gtk_button_set_image(GTK_BUTTON(button),
|
| - gtk_image_new_from_stock(stock_id,
|
| - GTK_ICON_SIZE_BUTTON));
|
| - return button;
|
| -}
|
| -
|
| -GtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image) {
|
| - GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
|
| - gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
|
| - gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
|
| - return hbox;
|
| -}
|
| -
|
| -void SetLabelColor(GtkWidget* label, const GdkColor* color) {
|
| - gtk_widget_modify_fg(label, GTK_STATE_NORMAL, color);
|
| - gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, color);
|
| - gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, color);
|
| - gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, color);
|
| -}
|
| -
|
| -GtkWidget* IndentWidget(GtkWidget* content) {
|
| - GtkWidget* content_alignment = gtk_alignment_new(0.0, 0.5, 1.0, 1.0);
|
| - gtk_alignment_set_padding(GTK_ALIGNMENT(content_alignment), 0, 0,
|
| - gtk_util::kGroupIndent, 0);
|
| - gtk_container_add(GTK_CONTAINER(content_alignment), content);
|
| - return content_alignment;
|
| -}
|
| -
|
| -void UpdateGtkFontSettings(RendererPreferences* prefs) {
|
| - DCHECK(prefs);
|
| -
|
| - // From http://library.gnome.org/devel/gtk/unstable/GtkSettings.html, this is
|
| - // the default value for gtk-cursor-blink-time.
|
| - static const gint kGtkDefaultCursorBlinkTime = 1200;
|
| -
|
| - gint cursor_blink_time = kGtkDefaultCursorBlinkTime;
|
| - gboolean cursor_blink = TRUE;
|
| - gint antialias = 0;
|
| - gint hinting = 0;
|
| - gchar* hint_style = NULL;
|
| - gchar* rgba_style = NULL;
|
| - g_object_get(gtk_settings_get_default(),
|
| - "gtk-cursor-blink-time", &cursor_blink_time,
|
| - "gtk-cursor-blink", &cursor_blink,
|
| - "gtk-xft-antialias", &antialias,
|
| - "gtk-xft-hinting", &hinting,
|
| - "gtk-xft-hintstyle", &hint_style,
|
| - "gtk-xft-rgba", &rgba_style,
|
| - NULL);
|
| -
|
| - // Set some reasonable defaults.
|
| - prefs->should_antialias_text = true;
|
| - prefs->hinting = RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT;
|
| - prefs->subpixel_rendering =
|
| - RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT;
|
| -
|
| - if (cursor_blink) {
|
| - // Dividing by 2*1000ms follows the WebKit GTK port and makes the blink
|
| - // frequency appear similar to the omnibox. Without this the blink is too
|
| - // slow.
|
| - prefs->caret_blink_interval = cursor_blink_time / 2000.;
|
| - } else {
|
| - prefs->caret_blink_interval = 0;
|
| - }
|
| -
|
| - // g_object_get() doesn't tell us whether the properties were present or not,
|
| - // but if they aren't (because gnome-settings-daemon isn't running), we'll get
|
| - // NULL values for the strings.
|
| - if (hint_style && rgba_style) {
|
| - prefs->should_antialias_text = antialias;
|
| -
|
| - if (hinting == 0 || strcmp(hint_style, "hintnone") == 0) {
|
| - prefs->hinting = RENDERER_PREFERENCES_HINTING_NONE;
|
| - } else if (strcmp(hint_style, "hintslight") == 0) {
|
| - prefs->hinting = RENDERER_PREFERENCES_HINTING_SLIGHT;
|
| - } else if (strcmp(hint_style, "hintmedium") == 0) {
|
| - prefs->hinting = RENDERER_PREFERENCES_HINTING_MEDIUM;
|
| - } else if (strcmp(hint_style, "hintfull") == 0) {
|
| - prefs->hinting = RENDERER_PREFERENCES_HINTING_FULL;
|
| - }
|
| -
|
| - if (strcmp(rgba_style, "none") == 0) {
|
| - prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE;
|
| - } else if (strcmp(rgba_style, "rgb") == 0) {
|
| - prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB;
|
| - } else if (strcmp(rgba_style, "bgr") == 0) {
|
| - prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR;
|
| - } else if (strcmp(rgba_style, "vrgb") == 0) {
|
| - prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB;
|
| - } else if (strcmp(rgba_style, "vbgr") == 0) {
|
| - prefs->subpixel_rendering = RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR;
|
| - }
|
| - }
|
| -
|
| - if (hint_style)
|
| - g_free(hint_style);
|
| - if (rgba_style)
|
| - g_free(rgba_style);
|
| -}
|
| -
|
| -gfx::Point ScreenPoint(GtkWidget* widget) {
|
| - int x, y;
|
| - gdk_display_get_pointer(gtk_widget_get_display(widget), NULL, &x, &y,
|
| - NULL);
|
| - return gfx::Point(x, y);
|
| -}
|
| -
|
| -gfx::Point ClientPoint(GtkWidget* widget) {
|
| - int x, y;
|
| - gtk_widget_get_pointer(widget, &x, &y);
|
| - return gfx::Point(x, y);
|
| -}
|
| -
|
| -GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr) {
|
| - GdkPoint point = {ltr ? x : width - x, y};
|
| - return point;
|
| -}
|
| -
|
| -void DrawTextEntryBackground(GtkWidget* offscreen_entry,
|
| - GtkWidget* widget_to_draw_on,
|
| - GdkRectangle* dirty_rec,
|
| - GdkRectangle* rec) {
|
| - GtkStyle* gtk_owned_style = gtk_rc_get_style(offscreen_entry);
|
| - // GTK owns the above and we're going to have to make our own copy of it
|
| - // that we can edit.
|
| - GtkStyle* our_style = gtk_style_copy(gtk_owned_style);
|
| - our_style = gtk_style_attach(our_style, widget_to_draw_on->window);
|
| -
|
| - // TODO(erg): Draw the focus ring if appropriate...
|
| -
|
| - // We're using GTK rendering; draw a GTK entry widget onto the background.
|
| - gtk_paint_shadow(our_style, widget_to_draw_on->window,
|
| - GTK_STATE_NORMAL, GTK_SHADOW_IN, dirty_rec,
|
| - widget_to_draw_on, "entry",
|
| - rec->x, rec->y, rec->width, rec->height);
|
| -
|
| - // Draw the interior background (not all themes draw the entry background
|
| - // above; this is a noop on themes that do).
|
| - gint xborder = our_style->xthickness;
|
| - gint yborder = our_style->ythickness;
|
| - gint width = rec->width - 2 * xborder;
|
| - gint height = rec->height - 2 * yborder;
|
| - if (width > 0 && height > 0) {
|
| - gtk_paint_flat_box(our_style, widget_to_draw_on->window,
|
| - GTK_STATE_NORMAL, GTK_SHADOW_NONE, dirty_rec,
|
| - widget_to_draw_on, "entry_bg",
|
| - rec->x + xborder, rec->y + yborder,
|
| - width, height);
|
| - }
|
| -
|
| - gtk_style_detach(our_style);
|
| - g_object_unref(our_style);
|
| -}
|
| -
|
| -void DrawThemedToolbarBackground(GtkWidget* widget,
|
| - cairo_t* cr,
|
| - GdkEventExpose* event,
|
| - const gfx::Point& tabstrip_origin,
|
| - GtkThemeProvider* theme_provider) {
|
| - // Fill the entire region with the toolbar color.
|
| - GdkColor color = theme_provider->GetGdkColor(
|
| - BrowserThemeProvider::COLOR_TOOLBAR);
|
| - gdk_cairo_set_source_color(cr, &color);
|
| - cairo_fill(cr);
|
| -
|
| - // The toolbar is supposed to blend in with the active tab, so we have to pass
|
| - // coordinates for the IDR_THEME_TOOLBAR bitmap relative to the top of the
|
| - // tab strip.
|
| - CairoCachedSurface* background = theme_provider->GetSurfaceNamed(
|
| - IDR_THEME_TOOLBAR, widget);
|
| - background->SetSource(cr, tabstrip_origin.x(), tabstrip_origin.y());
|
| - // We tile the toolbar background in both directions.
|
| - cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
|
| - cairo_rectangle(cr,
|
| - tabstrip_origin.x(),
|
| - tabstrip_origin.y(),
|
| - event->area.x + event->area.width - tabstrip_origin.x(),
|
| - event->area.y + event->area.height - tabstrip_origin.y());
|
| - cairo_fill(cr);
|
| -}
|
| -
|
| -GdkColor AverageColors(GdkColor color_one, GdkColor color_two) {
|
| - GdkColor average_color;
|
| - average_color.pixel = 0;
|
| - average_color.red = (color_one.red + color_two.red) / 2;
|
| - average_color.green = (color_one.green + color_two.green) / 2;
|
| - average_color.blue = (color_one.blue + color_two.blue) / 2;
|
| - return average_color;
|
| -}
|
| -
|
| -void SetAlwaysShowImage(GtkWidget* image_menu_item) {
|
| - // Compile time check: if it's available, just use the API.
|
| - // GTK_CHECK_VERSION is TRUE if the passed version is compatible.
|
| -#if GTK_CHECK_VERSION(2, 16, 1)
|
| - gtk_image_menu_item_set_always_show_image(
|
| - GTK_IMAGE_MENU_ITEM(image_menu_item), TRUE);
|
| -#else
|
| - // Run time check: if the API is not available, set the property manually.
|
| - // This will still only work with GTK 2.16+ as the property doesn't exist
|
| - // in earlier versions.
|
| - // gtk_check_version() returns NULL if the passed version is compatible.
|
| - if (!gtk_check_version(2, 16, 1)) {
|
| - GValue true_value = { 0 };
|
| - g_value_init(&true_value, G_TYPE_BOOLEAN);
|
| - g_value_set_boolean(&true_value, TRUE);
|
| - g_object_set_property(G_OBJECT(image_menu_item), "always-show-image",
|
| - &true_value);
|
| - }
|
| -#endif
|
| -}
|
| -
|
| -void StackPopupWindow(GtkWidget* popup, GtkWidget* toplevel) {
|
| - DCHECK(GTK_IS_WINDOW(popup) && GTK_WIDGET_TOPLEVEL(popup) &&
|
| - GTK_WIDGET_REALIZED(popup));
|
| - DCHECK(GTK_IS_WINDOW(toplevel) && GTK_WIDGET_TOPLEVEL(toplevel) &&
|
| - GTK_WIDGET_REALIZED(toplevel));
|
| -
|
| - // Stack the |popup| window directly above the |toplevel| window.
|
| - // The popup window is a direct child of the root window, so we need to
|
| - // find a similar ancestor for the toplevel window (which might have been
|
| - // reparented by a window manager). We grab the server while we're doing
|
| - // this -- otherwise, we'll get an error if the window manager reparents the
|
| - // toplevel window right after we call GetHighestAncestorWindow().
|
| - gdk_x11_display_grab(gtk_widget_get_display(toplevel));
|
| - XID toplevel_window_base = x11_util::GetHighestAncestorWindow(
|
| - x11_util::GetX11WindowFromGtkWidget(toplevel),
|
| - x11_util::GetX11RootWindow());
|
| - if (toplevel_window_base) {
|
| - XID window_xid = x11_util::GetX11WindowFromGtkWidget(popup);
|
| - XID window_parent = x11_util::GetParentWindow(window_xid);
|
| - if (window_parent == x11_util::GetX11RootWindow()) {
|
| - x11_util::RestackWindow(window_xid, toplevel_window_base, true);
|
| - } else {
|
| - // The window manager shouldn't reparent override-redirect windows.
|
| - DLOG(ERROR) << "override-redirect window " << window_xid
|
| - << "'s parent is " << window_parent
|
| - << ", rather than root window "
|
| - << x11_util::GetX11RootWindow();
|
| - }
|
| - }
|
| - gdk_x11_display_ungrab(gtk_widget_get_display(toplevel));
|
| -}
|
| -
|
| -gfx::Rect GetWidgetRectRelativeToToplevel(GtkWidget* widget) {
|
| - DCHECK(GTK_WIDGET_REALIZED(widget));
|
| -
|
| - GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
|
| - DCHECK(toplevel);
|
| - DCHECK(GTK_WIDGET_REALIZED(toplevel));
|
| -
|
| - gint x = 0, y = 0;
|
| - gtk_widget_translate_coordinates(widget,
|
| - toplevel,
|
| - 0, 0,
|
| - &x, &y);
|
| - return gfx::Rect(x, y, widget->allocation.width, widget->allocation.height);
|
| -}
|
| -
|
| -void SuppressDefaultPainting(GtkWidget* container) {
|
| - g_signal_connect(container, "expose-event",
|
| - G_CALLBACK(PaintNoBackground), NULL);
|
| -}
|
| -
|
| -WindowOpenDisposition DispositionForCurrentButtonPressEvent() {
|
| - GdkEvent* event = gtk_get_current_event();
|
| - if (!event) {
|
| - NOTREACHED();
|
| - return NEW_FOREGROUND_TAB;
|
| - }
|
| -
|
| - guint state = event->button.state;
|
| - gdk_event_free(event);
|
| - return event_utils::DispositionFromEventFlags(state);
|
| -}
|
| -
|
| -bool GrabAllInput(GtkWidget* widget) {
|
| - guint time = gtk_get_current_event_time();
|
| -
|
| - if (!GTK_WIDGET_VISIBLE(widget))
|
| - return false;
|
| -
|
| - if (!gdk_pointer_grab(widget->window, TRUE,
|
| - GdkEventMask(GDK_BUTTON_PRESS_MASK |
|
| - GDK_BUTTON_RELEASE_MASK |
|
| - GDK_ENTER_NOTIFY_MASK |
|
| - GDK_LEAVE_NOTIFY_MASK |
|
| - GDK_POINTER_MOTION_MASK),
|
| - NULL, NULL, time) == 0) {
|
| - return false;
|
| - }
|
| -
|
| - if (!gdk_keyboard_grab(widget->window, TRUE, time) == 0) {
|
| - gdk_display_pointer_ungrab(gdk_drawable_get_display(widget->window), time);
|
| - return false;
|
| - }
|
| -
|
| - gtk_grab_add(widget);
|
| - return true;
|
| -}
|
| -
|
| -gfx::Rect WidgetBounds(GtkWidget* widget) {
|
| - // To quote the gtk docs:
|
| - //
|
| - // Widget coordinates are a bit odd; for historical reasons, they are
|
| - // defined as widget->window coordinates for widgets that are not
|
| - // GTK_NO_WINDOW widgets, and are relative to widget->allocation.x,
|
| - // widget->allocation.y for widgets that are GTK_NO_WINDOW widgets.
|
| - //
|
| - // So the base is always (0,0).
|
| - return gfx::Rect(0, 0, widget->allocation.width, widget->allocation.height);
|
| -}
|
| -
|
| -void SetWMLastUserActionTime(GtkWindow* window) {
|
| - gdk_x11_window_set_user_time(GTK_WIDGET(window)->window, XTimeNow());
|
| -}
|
| -
|
| -guint32 XTimeNow() {
|
| - struct timespec ts;
|
| - clock_gettime(CLOCK_MONOTONIC, &ts);
|
| - return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
| -}
|
| -
|
| -bool URLFromPrimarySelection(Profile* profile, GURL* url) {
|
| - GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
|
| - DCHECK(clipboard);
|
| - gchar* selection_text = gtk_clipboard_wait_for_text(clipboard);
|
| - if (!selection_text)
|
| - return false;
|
| -
|
| - // Use autocomplete to clean up the text, going so far as to turn it into
|
| - // a search query if necessary.
|
| - AutocompleteMatch match;
|
| - profile->GetAutocompleteClassifier()->Classify(UTF8ToWide(selection_text),
|
| - std::wstring(), false, &match, NULL);
|
| - g_free(selection_text);
|
| - if (!match.destination_url.is_valid())
|
| - return false;
|
| -
|
| - *url = match.destination_url;
|
| - return true;
|
| -}
|
| -
|
| -bool AddWindowAlphaChannel(GtkWidget* window) {
|
| - GdkScreen* screen = gtk_widget_get_screen(window);
|
| - GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen);
|
| - if (rgba)
|
| - gtk_widget_set_colormap(window, rgba);
|
| -
|
| - return rgba;
|
| -}
|
| -
|
| -void GetTextColors(GdkColor* normal_base,
|
| - GdkColor* selected_base,
|
| - GdkColor* normal_text,
|
| - GdkColor* selected_text) {
|
| - GtkWidget* fake_entry = gtk_entry_new();
|
| - GtkStyle* style = gtk_rc_get_style(fake_entry);
|
| -
|
| - if (normal_base)
|
| - *normal_base = style->base[GTK_STATE_NORMAL];
|
| - if (selected_base)
|
| - *selected_base = style->base[GTK_STATE_SELECTED];
|
| - if (normal_text)
|
| - *normal_text = style->text[GTK_STATE_NORMAL];
|
| - if (selected_text)
|
| - *selected_text = style->text[GTK_STATE_SELECTED];
|
| -
|
| - g_object_ref_sink(fake_entry);
|
| - g_object_unref(fake_entry);
|
| -}
|
| -
|
| -#if defined(OS_CHROMEOS)
|
| -
|
| -GtkWindow* GetDialogTransientParent(GtkWindow* dialog) {
|
| - GtkWindow* parent = gtk_window_get_transient_for(dialog);
|
| - if (!parent)
|
| - parent = chromeos::GetOptionsViewParent();
|
| -
|
| - return parent;
|
| -}
|
| -
|
| -void ShowDialog(GtkWidget* dialog) {
|
| - // Make sure all controls are visible so that we get correct size.
|
| - gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
|
| -
|
| - // Get dialog window size.
|
| - gint width = 0;
|
| - gint height = 0;
|
| - gtk_window_get_size(GTK_WINDOW(dialog), &width, &height);
|
| -
|
| - chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
|
| - dialog,
|
| - gtk_window_get_resizable(GTK_WINDOW(dialog)) ?
|
| - chromeos::DIALOG_FLAG_RESIZEABLE :
|
| - chromeos::DIALOG_FLAG_DEFAULT,
|
| - gfx::Size(width, height),
|
| - gfx::Size());
|
| -}
|
| -
|
| -void ShowDialogWithLocalizedSize(GtkWidget* dialog,
|
| - int width_id,
|
| - int height_id,
|
| - bool resizeable) {
|
| - int width = (width_id == -1) ? 0 :
|
| - views::Window::GetLocalizedContentsWidth(width_id);
|
| - int height = (height_id == -1) ? 0 :
|
| - views::Window::GetLocalizedContentsHeight(height_id);
|
| -
|
| - chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
|
| - dialog,
|
| - resizeable ? chromeos::DIALOG_FLAG_RESIZEABLE :
|
| - chromeos::DIALOG_FLAG_DEFAULT,
|
| - gfx::Size(width, height),
|
| - gfx::Size());
|
| -}
|
| -
|
| -void ShowModalDialogWithMinLocalizedWidth(GtkWidget* dialog,
|
| - int width_id) {
|
| - int width = (width_id == -1) ? 0 :
|
| - views::Window::GetLocalizedContentsWidth(width_id);
|
| -
|
| - chromeos::ShowNativeDialog(GetDialogTransientParent(GTK_WINDOW(dialog)),
|
| - dialog,
|
| - chromeos::DIALOG_FLAG_MODAL,
|
| - gfx::Size(),
|
| - gfx::Size(width, 0));
|
| -}
|
| -
|
| -void PresentWindow(GtkWidget* window, int timestamp) {
|
| - GtkWindow* host_window = chromeos::GetNativeDialogWindow(window);
|
| - if (!host_window)
|
| - host_window = GTK_WINDOW(window);
|
| - if (timestamp)
|
| - gtk_window_present_with_time(host_window, timestamp);
|
| - else
|
| - gtk_window_present(host_window);
|
| -}
|
| -
|
| -GtkWindow* GetDialogWindow(GtkWidget* dialog) {
|
| - return chromeos::GetNativeDialogWindow(dialog);
|
| -}
|
| -
|
| -gfx::Rect GetDialogBounds(GtkWidget* dialog) {
|
| - return chromeos::GetNativeDialogContentsBounds(dialog);
|
| -}
|
| -
|
| -#else
|
| -
|
| -void ShowDialog(GtkWidget* dialog) {
|
| - gtk_widget_show_all(dialog);
|
| -}
|
| -
|
| -void ShowDialogWithLocalizedSize(GtkWidget* dialog,
|
| - int width_id,
|
| - int height_id,
|
| - bool resizeable) {
|
| - gtk_widget_realize(dialog);
|
| - SetWindowSizeFromResources(GTK_WINDOW(dialog),
|
| - width_id,
|
| - height_id,
|
| - resizeable);
|
| - gtk_widget_show_all(dialog);
|
| -}
|
| -
|
| -void ShowModalDialogWithMinLocalizedWidth(GtkWidget* dialog,
|
| - int width_id) {
|
| - gtk_widget_show_all(dialog);
|
| -
|
| - // Suggest a minimum size.
|
| - gint width;
|
| - GtkRequisition req;
|
| - gtk_widget_size_request(dialog, &req);
|
| - gtk_util::GetWidgetSizeFromResources(dialog, width_id, 0, &width, NULL);
|
| - if (width > req.width)
|
| - gtk_widget_set_size_request(dialog, width, -1);
|
| -}
|
| -
|
| -void PresentWindow(GtkWidget* window, int timestamp) {
|
| - if (timestamp)
|
| - gtk_window_present_with_time(GTK_WINDOW(window), timestamp);
|
| - else
|
| - gtk_window_present(GTK_WINDOW(window));
|
| -}
|
| -
|
| -GtkWindow* GetDialogWindow(GtkWidget* dialog) {
|
| - return GTK_WINDOW(dialog);
|
| -}
|
| -
|
| -gfx::Rect GetDialogBounds(GtkWidget* dialog) {
|
| - gint x = 0, y = 0, width = 1, height = 1;
|
| - gtk_window_get_position(GTK_WINDOW(dialog), &x, &y);
|
| - gtk_window_get_size(GTK_WINDOW(dialog), &width, &height);
|
| -
|
| - return gfx::Rect(x, y, width, height);
|
| -}
|
| -
|
| -#endif
|
| -
|
| -string16 GetStockPreferencesMenuLabel() {
|
| - GtkStockItem stock_item;
|
| - string16 preferences;
|
| - if (gtk_stock_lookup(GTK_STOCK_PREFERENCES, &stock_item)) {
|
| - const char16 kUnderscore[] = { '_', 0 };
|
| - RemoveChars(UTF8ToUTF16(stock_item.label), kUnderscore, &preferences);
|
| - }
|
| - return preferences;
|
| -}
|
| -
|
| -bool IsWidgetAncestryVisible(GtkWidget* widget) {
|
| - GtkWidget* parent = widget;
|
| - while (parent && GTK_WIDGET_VISIBLE(parent))
|
| - parent = parent->parent;
|
| - return !parent;
|
| -}
|
| -
|
| -void SetGtkFont(const std::string& font_name) {
|
| - g_object_set(gtk_settings_get_default(),
|
| - "gtk-font-name", font_name.c_str(), NULL);
|
| -}
|
| -
|
| -void SetLabelWidth(GtkWidget* label, int pixel_width) {
|
| - gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
|
| -
|
| - // Do the simple thing in LTR because the bug only affects right-aligned
|
| - // text. Also, when using the workaround, the label tries to maintain
|
| - // uniform line-length, which we don't really want.
|
| - if (gtk_widget_get_direction(label) == GTK_TEXT_DIR_LTR) {
|
| - gtk_widget_set_size_request(label, pixel_width, -1);
|
| - } else {
|
| - // The label has to be realized before we can adjust its width.
|
| - if (GTK_WIDGET_REALIZED(label)) {
|
| - OnLabelRealize(label, GINT_TO_POINTER(pixel_width));
|
| - } else {
|
| - g_signal_connect(label, "realize", G_CALLBACK(OnLabelRealize),
|
| - GINT_TO_POINTER(pixel_width));
|
| - }
|
| - }
|
| -}
|
| -
|
| -void InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label) {
|
| - GtkRequisition size;
|
| - gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_NONE);
|
| - gtk_widget_set_size_request(label, -1, -1);
|
| - gtk_widget_size_request(label, &size);
|
| - gtk_widget_set_size_request(label, size.width, size.height);
|
| - gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
|
| -}
|
| -
|
| -GdkDragAction WebDragOpToGdkDragAction(WebDragOperationsMask op) {
|
| - GdkDragAction action = static_cast<GdkDragAction>(0);
|
| - if (op & WebDragOperationCopy)
|
| - action = static_cast<GdkDragAction>(action | GDK_ACTION_COPY);
|
| - if (op & WebDragOperationLink)
|
| - action = static_cast<GdkDragAction>(action | GDK_ACTION_LINK);
|
| - if (op & WebDragOperationMove)
|
| - action = static_cast<GdkDragAction>(action | GDK_ACTION_MOVE);
|
| - return action;
|
| -}
|
| -
|
| -WebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action) {
|
| - WebDragOperationsMask op = WebDragOperationNone;
|
| - if (action & GDK_ACTION_COPY)
|
| - op = static_cast<WebDragOperationsMask>(op | WebDragOperationCopy);
|
| - if (action & GDK_ACTION_LINK)
|
| - op = static_cast<WebDragOperationsMask>(op | WebDragOperationLink);
|
| - if (action & GDK_ACTION_MOVE)
|
| - op = static_cast<WebDragOperationsMask>(op | WebDragOperationMove);
|
| - return op;
|
| -}
|
| -
|
| -void ApplyMessageDialogQuirks(GtkWidget* dialog) {
|
| - if (gtk_window_get_modal(GTK_WINDOW(dialog))) {
|
| - // Work around a KDE 3 window manager bug.
|
| - scoped_ptr<base::Environment> env(base::Environment::Create());
|
| - if (base::nix::DESKTOP_ENVIRONMENT_KDE3 ==
|
| - base::nix::GetDesktopEnvironment(env.get()))
|
| - gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
|
| - }
|
| -}
|
| -
|
| -// Performs Cut/Copy/Paste operation on the |window|.
|
| -// If the current render view is focused, then just call the specified |method|
|
| -// against the current render view host, otherwise emit the specified |signal|
|
| -// against the focused widget.
|
| -// TODO(suzhe): This approach does not work for plugins.
|
| -void DoCutCopyPaste(BrowserWindow* window,
|
| - void (RenderViewHost::*method)(),
|
| - const char* signal) {
|
| - GtkWidget* widget = GetBrowserWindowFocusedWidget(window);
|
| - if (widget == NULL)
|
| - return; // Do nothing if no focused widget.
|
| -
|
| - TabContents* current_tab = GetBrowserWindowSelectedTabContents(window);
|
| - if (current_tab && widget == current_tab->GetContentNativeView()) {
|
| - (current_tab->render_view_host()->*method)();
|
| - } else {
|
| - guint id;
|
| - if ((id = g_signal_lookup(signal, G_OBJECT_TYPE(widget))) != 0)
|
| - g_signal_emit(widget, id, 0);
|
| - }
|
| -}
|
| -
|
| -void DoCut(BrowserWindow* window) {
|
| - DoCutCopyPaste(window, &RenderViewHost::Cut, "cut-clipboard");
|
| -}
|
| -
|
| -void DoCopy(BrowserWindow* window) {
|
| - DoCutCopyPaste(window, &RenderViewHost::Copy, "copy-clipboard");
|
| -}
|
| -
|
| -void DoPaste(BrowserWindow* window) {
|
| - DoCutCopyPaste(window, &RenderViewHost::Paste, "paste-clipboard");
|
| -}
|
| -
|
| -} // namespace gtk_util
|
|
|