1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_UI_GTK_GTK_UTIL_H_
6#define CHROME_BROWSER_UI_GTK_GTK_UTIL_H_
7#pragma once
8
9#include <gtk/gtk.h>
10#include <string>
11#include <vector>
12
13#include "base/string16.h"
14#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
15#include "ui/base/x/x11_util.h"
16#include "ui/gfx/point.h"
17#include "ui/gfx/rect.h"
18#include "webkit/glue/window_open_disposition.h"
19
20typedef struct _cairo cairo_t;
21typedef struct _GdkColor GdkColor;
22typedef struct _GtkWidget GtkWidget;
23
24class BrowserWindow;
25class GtkThemeService;
26class GURL;
27class Profile;
28struct RendererPreferences;  // from common/renderer_preferences.h
29
30const int kSkiaToGDKMultiplier = 257;
31
32// Define a macro for creating GdkColors from RGB values.  This is a macro to
33// allow static construction of literals, etc.  Use this like:
34//   GdkColor white = GDK_COLOR_RGB(0xff, 0xff, 0xff);
35#define GDK_COLOR_RGB(r, g, b) {0, r * kSkiaToGDKMultiplier, \
36        g * kSkiaToGDKMultiplier, b * kSkiaToGDKMultiplier}
37
38namespace event_utils {
39
40// Translates event flags into what kind of disposition they represent.
41// For example, a middle click would mean to open a background tab.
42// event_flags are the state in the GdkEvent structure.
43WindowOpenDisposition DispositionFromEventFlags(guint state);
44
45}  // namespace event_utils
46
47namespace gtk_util {
48
49extern const GdkColor kGdkWhite;
50extern const GdkColor kGdkGray;
51extern const GdkColor kGdkBlack;
52extern const GdkColor kGdkGreen;
53
54// Constants relating to the layout of dialog windows:
55// (See http://library.gnome.org/devel/hig-book/stable/design-window.html.en)
56
57// Spacing between controls of the same group.
58const int kControlSpacing = 6;
59
60// Horizontal spacing between a label and its control.
61const int kLabelSpacing = 12;
62
63// Indent of the controls within each group.
64const int kGroupIndent = 12;
65
66// Space around the outside of a dialog's contents.
67const int kContentAreaBorder = 12;
68
69// Spacing between groups of controls.
70const int kContentAreaSpacing = 18;
71
72// Horizontal Spacing between controls in a form.
73const int kFormControlSpacing = 10;
74
75// Create a table of labeled controls, using proper spacing and alignment.
76// Arguments should be pairs of const char*, GtkWidget*, concluding with a
77// NULL.  The first argument is a vector in which to place all labels
78// produced. It can be NULL if you don't need to keep track of the label
79// widgets. The second argument is a color to force the label text to. It can
80// be NULL to get the system default.
81//
82// For example:
83// controls = CreateLabeledControlsGroup(NULL,
84//                                       "Name:", title_entry_,
85//                                       "Folder:", folder_combobox_,
86//                                       NULL);
87GtkWidget* CreateLabeledControlsGroup(
88    std::vector<GtkWidget*>* labels,
89    const char* text, ...);
90
91// Create a GtkBin with |child| as its child widget.  This bin will paint a
92// border of color |color| with the sizes specified in pixels.
93GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color,
94                              int top, int bottom, int left, int right);
95
96// Left-align the given GtkMisc and return the same pointer.
97GtkWidget* LeftAlignMisc(GtkWidget* misc);
98
99// Create a left-aligned label with the given text in bold.
100GtkWidget* CreateBoldLabel(const std::string& text);
101
102// As above, but uses number of characters/lines directly rather than looking up
103// a resource.
104void GetWidgetSizeFromCharacters(GtkWidget* widget,
105                                 double width_chars, double height_lines,
106                                 int* width, int* height);
107
108// Calculates the size of given widget based on the size specified in number of
109// characters/lines (in locale specific resource file) and font metrics.
110// NOTE: Make sure to realize |widget| before using this method, or a default
111// font size will be used instead of the actual font size.
112void GetWidgetSizeFromResources(GtkWidget* widget,
113                                int width_chars, int height_lines,
114                                int* width, int* height);
115
116// As above, but a convenience method for configuring dialog size.
117// |width_id| and |height_id| are resource IDs for the size.  If either of these
118// are set to -1, the respective size will be set to the widget default.
119// |resizable| also controls whether the dialog will be resizable
120// (this info is also necessary for getting the width-setting code
121// right).
122void SetWindowSizeFromResources(GtkWindow* window,
123                                int width_id, int height_id, bool resizable);
124
125// Places |window| approximately over center of |parent|, it also moves window
126// to parent's desktop. Use this only for non-modal dialogs, such as the
127// options window and content settings window; otherwise you should be using
128// transient_for.
129void CenterOverWindow(GtkWindow* window, GtkWindow* parent);
130
131// Puts all browser windows in one window group; this will make any dialog
132// spawned app modal.
133void MakeAppModalWindowGroup();
134
135// Called after an app modal dialog that used MakeAppModalWindowGroup() was
136// dismissed. Returns each browser window to its own window group.
137void AppModalDismissedUngroupWindows();
138
139// Remove all children from this container.
140void RemoveAllChildren(GtkWidget* container);
141
142// Force the font size of the widget to |size_pixels|.
143void ForceFontSizePixels(GtkWidget* widget, double size_pixels);
144
145// Undoes the effects of a previous ForceFontSizePixels() call. Safe to call
146// even if ForceFontSizePixels() was never called.
147void UndoForceFontSize(GtkWidget* widget);
148
149// Gets the position of a gtk widget in screen coordinates.
150gfx::Point GetWidgetScreenPosition(GtkWidget* widget);
151
152// Returns the bounds of the specified widget in screen coordinates.
153gfx::Rect GetWidgetScreenBounds(GtkWidget* widget);
154
155// Retuns size of the |widget| without window manager decorations.
156gfx::Size GetWidgetSize(GtkWidget* widget);
157
158// Converts a point in a widget to screen coordinates.  The point |p| is
159// relative to the widget's top-left origin.
160void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p);
161
162// Initialize some GTK settings so that our dialogs are consistent.
163void InitRCStyles();
164
165// Stick the widget in the given hbox without expanding vertically. The widget
166// is packed at the start of the hbox. This is useful for widgets that would
167// otherwise expand to fill the vertical space of the hbox
168// (e.g. buttons). Returns the vbox that widget was packed in.
169GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget,
170                              bool pack_at_end, int padding);
171
172// Returns true if the screen is composited, false otherwise.
173bool IsScreenComposited();
174
175// Enumerates the top-level gdk windows of the current display.
176void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate);
177
178// Set that clicking the button with the given mouse buttons will cause a click
179// event.
180// NOTE: If you need to connect to the button-press-event or
181// button-release-event signals, do so before calling this function.
182void SetButtonClickableByMouseButtons(GtkWidget* button,
183                                      bool left, bool middle, bool right);
184
185// Set that a button causes a page navigation. In particular, it will accept
186// middle clicks. Warning: only call this *after* you have connected your
187// own handlers for button-press and button-release events, or you will not get
188// those events.
189void SetButtonTriggersNavigation(GtkWidget* button);
190
191// Returns the mirrored x value for |bounds| if the layout is RTL; otherwise,
192// the original value is returned unchanged.
193int MirroredLeftPointForRect(GtkWidget* widget, const gfx::Rect& bounds);
194
195// Returns the mirrored x value for the point |x| if the layout is RTL;
196// otherwise, the original value is returned unchanged.
197int MirroredXCoordinate(GtkWidget* widget, int x);
198
199// Returns true if the pointer is currently inside the widget.
200bool WidgetContainsCursor(GtkWidget* widget);
201
202// Sets the icon of |window| to the product icon (potentially used in window
203// border or alt-tab list).
204void SetWindowIcon(GtkWindow* window);
205
206// Sets the default window icon for all windows created in this app. |window|
207// is used to determine if a themed icon exists. If so, we use that icon,
208// otherwise we use the icon packaged with Chrome.
209void SetDefaultWindowIcon(GtkWindow* window);
210
211// Adds an action button with the given text to the dialog. Only useful when you
212// want a stock icon but not the stock text to go with it. Returns the button.
213GtkWidget* AddButtonToDialog(GtkWidget* dialog, const gchar* text,
214                             const gchar* stock_id, gint response_id);
215
216GtkWidget* BuildDialogButton(GtkWidget* dialog, int ids_id,
217                             const gchar* stock_id);
218
219GtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image);
220
221// Sets all the foreground color states of |label| to |color|.
222void SetLabelColor(GtkWidget* label, const GdkColor* color);
223
224// Adds the given widget to an alignment identing it by |kGroupIndent|.
225GtkWidget* IndentWidget(GtkWidget* content);
226
227// Sets (or resets) the font settings in |prefs| (used when creating new
228// renderers) based on GtkSettings (which itself comes from XSETTINGS).
229void UpdateGtkFontSettings(RendererPreferences* prefs);
230
231// Get the current location of the mouse cursor relative to the screen.
232gfx::Point ScreenPoint(GtkWidget* widget);
233
234// Get the current location of the mouse cursor relative to the widget.
235gfx::Point ClientPoint(GtkWidget* widget);
236
237// Reverses a point in RTL mode. Used in making vectors of GdkPoints for window
238// shapes.
239GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr);
240
241// Draws a GTK text entry with the style parameters of GtkEntry
242// |offscreen_entry| onto |widget_to_draw_on| in the rectangle |rec|. Drawing
243// is only done in the clip rectangle |dirty_rec|.
244void DrawTextEntryBackground(GtkWidget* offscreen_entry,
245                             GtkWidget* widget_to_draw_on,
246                             GdkRectangle* dirty_rec,
247                             GdkRectangle* rec);
248
249// Draws the background of the toolbar area subject to the expose rectangle
250// |event| and starting image tiling from |tabstrip_origin|.
251void DrawThemedToolbarBackground(GtkWidget* widget,
252                                 cairo_t* cr,
253                                 GdkEventExpose* event,
254                                 const gfx::Point& tabstrip_origin,
255                                 GtkThemeService* provider);
256
257// Returns the two colors averaged together.
258GdkColor AverageColors(GdkColor color_one, GdkColor color_two);
259
260// Show the image for the given menu item, even if the user's default is to not
261// show images. Only to be used for favicons or other menus where the image is
262// crucial to its functionality.
263void SetAlwaysShowImage(GtkWidget* image_menu_item);
264
265// Get a rectangle corresponding to a widget's allocation relative to its
266// toplevel window's origin.
267gfx::Rect GetWidgetRectRelativeToToplevel(GtkWidget* widget);
268
269// Don't allow the widget to paint anything, and instead propagate the expose
270// to its children. This is similar to calling
271//
272//   gtk_widget_set_app_paintable(container, TRUE);
273//
274// except that it will always work, and it should be called after any custom
275// expose events are connected.
276void SuppressDefaultPainting(GtkWidget* container);
277
278// Get the window open disposition from the state in gtk_get_current_event().
279// This is designed to be called inside a "clicked" event handler. It is an
280// error to call it when gtk_get_current_event() won't return a GdkEventButton*.
281WindowOpenDisposition DispositionForCurrentButtonPressEvent();
282
283// Safely grabs all input (with X grabs and an application grab), returning true
284// for success.
285bool GrabAllInput(GtkWidget* widget);
286
287// Returns a rectangle that represents the widget's bounds. The rectangle it
288// returns is the same as widget->allocation, but anchored at (0, 0).
289gfx::Rect WidgetBounds(GtkWidget* widget);
290
291// Update the timestamp for the given window. This is usually the time of the
292// last user event, but on rare occasions we wish to update it despite not
293// receiving a user event.
294void SetWMLastUserActionTime(GtkWindow* window);
295
296// The current system time, using the format expected by the X server, but not
297// retrieved from the X server. NOTE: You should almost never need to use this
298// function, instead using the timestamp from the latest GDK event.
299guint32 XTimeNow();
300
301// Uses the autocomplete controller for |profile| to convert the contents of the
302// PRIMARY selection to a parsed URL. Returns true and sets |url| on success,
303// otherwise returns false.
304bool URLFromPrimarySelection(Profile* profile, GURL* url);
305
306// Set the colormap of the given window to rgba to allow transparency.
307bool AddWindowAlphaChannel(GtkWidget* window);
308
309// Get the default colors for a text entry.  Parameters may be NULL.
310void GetTextColors(GdkColor* normal_base,
311                   GdkColor* selected_base,
312                   GdkColor* normal_text,
313                   GdkColor* selected_text);
314
315// Wrappers to show a GtkDialog. On Linux, it merely calls gtk_widget_show_all.
316// On ChromeOs, it calls ShowNativeDialog which hosts the its vbox
317// in a view based Window.
318void ShowDialog(GtkWidget* dialog);
319void ShowDialogWithLocalizedSize(GtkWidget* dialog,
320                                 int width_id,
321                                 int height_id,
322                                 bool resizeable);
323void ShowDialogWithMinLocalizedWidth(GtkWidget* dialog,
324                                     int width_id);
325
326// Wrapper to present a window. On Linux, it just calls gtk_window_present or
327// gtk_window_present_with_time for non-zero timestamp. For ChromeOS, it first
328// finds the host window of the dialog contents and then present it.
329void PresentWindow(GtkWidget* window, int timestamp);
330
331// Get real window for given dialog. On ChromeOS, this gives the native dialog
332// host window. On Linux, it merely returns the passed in dialog.
333GtkWindow* GetDialogWindow(GtkWidget* dialog);
334
335// Gets dialog window bounds.
336gfx::Rect GetDialogBounds(GtkWidget* dialog);
337
338// Returns the stock menu item label for the "preferences" item - returns an
339// empty string if no stock item found.
340string16 GetStockPreferencesMenuLabel();
341
342// Checks whether a widget is actually visible, i.e. whether it and all its
343// ancestors up to its toplevel are visible.
344bool IsWidgetAncestryVisible(GtkWidget* widget);
345
346// Sets the given label's size request to |pixel_width|. This will cause the
347// label to wrap if it needs to. The reason for this function is that some
348// versions of GTK mis-align labels that have a size request and line wrapping,
349// and this function hides the complexity of the workaround.
350void SetLabelWidth(GtkWidget* label, int pixel_width);
351
352// Make the |label| shrinkable within a GthChromeShrinkableHBox
353// It calculates the real size request of a label and set its ellipsize mode to
354// PANGO_ELLIPSIZE_END.
355// It must be done when the label is mapped (become visible on the screen),
356// to make sure the pango can get correct font information for the calculation.
357void InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label);
358
359// Convenience methods for converting between web drag operations and the GDK
360// equivalent.
361GdkDragAction WebDragOpToGdkDragAction(WebKit::WebDragOperationsMask op);
362WebKit::WebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action);
363
364// A helper function for gtk_message_dialog_new() to work around a few KDE 3
365// window manager bugs. You should always call it after creating a dialog with
366// gtk_message_dialog_new.
367void ApplyMessageDialogQuirks(GtkWidget* dialog);
368
369// Performs Cut/Copy/Paste operation on the |window|.
370void DoCut(BrowserWindow* window);
371void DoCopy(BrowserWindow* window);
372void DoPaste(BrowserWindow* window);
373
374}  // namespace gtk_util
375
376#endif  // CHROME_BROWSER_UI_GTK_GTK_UTIL_H_
377