1 // Copyright (c) 2012 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 8 #include <gtk/gtk.h> 9 #include <string> 10 #include <vector> 11 12 #include "base/strings/string16.h" 13 #include "ui/base/window_open_disposition.h" 14 #include "ui/base/x/x11_util.h" 15 #include "ui/gfx/point.h" 16 #include "ui/gfx/rect.h" 17 18 typedef struct _cairo cairo_t; 19 typedef struct _GtkWidget GtkWidget; 20 21 class BrowserWindow; 22 class GtkThemeService; 23 class GURL; 24 class Profile; 25 26 namespace gfx { 27 class Image; 28 } 29 30 namespace gtk_util { 31 32 // Create a table of labeled controls, using proper spacing and alignment. 33 // Arguments should be pairs of const char*, GtkWidget*, concluding with a 34 // NULL. The first argument is a vector in which to place all labels 35 // produced. It can be NULL if you don't need to keep track of the label 36 // widgets. The second argument is a color to force the label text to. It can 37 // be NULL to get the system default. 38 // 39 // For example: 40 // controls = CreateLabeledControlsGroup(NULL, 41 // "Name:", title_entry_, 42 // "Folder:", folder_combobox_, 43 // NULL); 44 GtkWidget* CreateLabeledControlsGroup( 45 std::vector<GtkWidget*>* labels, 46 const char* text, ...); 47 48 // Create a GtkBin with |child| as its child widget. This bin will paint a 49 // border of color |color| with the sizes specified in pixels. 50 GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color, 51 int top, int bottom, int left, int right); 52 53 // Left-align the given GtkMisc and return the same pointer. 54 GtkWidget* LeftAlignMisc(GtkWidget* misc); 55 56 // Create a left-aligned label with the given text in bold. 57 GtkWidget* CreateBoldLabel(const std::string& text); 58 59 // As above, but uses number of characters/lines directly rather than looking up 60 // a resource. 61 void GetWidgetSizeFromCharacters(GtkWidget* widget, 62 double width_chars, double height_lines, 63 int* width, int* height); 64 65 // Calculates the size of given widget based on the size specified in number of 66 // characters/lines (in locale specific resource file) and font metrics. 67 // NOTE: Make sure to realize |widget| before using this method, or a default 68 // font size will be used instead of the actual font size. 69 void GetWidgetSizeFromResources(GtkWidget* widget, 70 int width_chars, int height_lines, 71 int* width, int* height); 72 73 // As above, but a convenience method for configuring dialog size. 74 // |width_id| and |height_id| are resource IDs for the size. If either of these 75 // are set to -1, the respective size will be set to the widget default. 76 // |resizable| also controls whether the dialog will be resizable 77 // (this info is also necessary for getting the width-setting code 78 // right). 79 void SetWindowSizeFromResources(GtkWindow* window, 80 int width_id, int height_id, bool resizable); 81 82 // Puts all browser windows in one window group; this will make any dialog 83 // spawned app modal. 84 void MakeAppModalWindowGroup(); 85 86 // Called after an app modal dialog that used MakeAppModalWindowGroup() was 87 // dismissed. Returns each browser window to its own window group. 88 void AppModalDismissedUngroupWindows(); 89 90 // Remove all children from this container. 91 void RemoveAllChildren(GtkWidget* container); 92 93 // Force the font size of the widget to |size_pixels|. 94 void ForceFontSizePixels(GtkWidget* widget, double size_pixels); 95 96 // Undoes the effects of a previous ForceFontSizePixels() call. Safe to call 97 // even if ForceFontSizePixels() was never called. 98 void UndoForceFontSize(GtkWidget* widget); 99 100 // Retuns size of the |widget| without window manager decorations. 101 gfx::Size GetWidgetSize(GtkWidget* widget); 102 103 // Converts a point in a widget to screen coordinates. The point |p| is 104 // relative to the widget's top-left origin. 105 void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p); 106 107 // Stick the widget in the given hbox without expanding vertically. The widget 108 // is packed at the start of the hbox. This is useful for widgets that would 109 // otherwise expand to fill the vertical space of the hbox 110 // (e.g. buttons). Returns the vbox that widget was packed in. 111 GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget, 112 bool pack_at_end, int padding); 113 114 // Set that clicking the button with the given mouse buttons will cause a click 115 // event. 116 // NOTE: If you need to connect to the button-press-event or 117 // button-release-event signals, do so before calling this function. 118 void SetButtonClickableByMouseButtons(GtkWidget* button, 119 bool left, bool middle, bool right); 120 121 // Set that a button causes a page navigation. In particular, it will accept 122 // middle clicks. Warning: only call this *after* you have connected your 123 // own handlers for button-press and button-release events, or you will not get 124 // those events. 125 void SetButtonTriggersNavigation(GtkWidget* button); 126 127 // Returns the mirrored x value for |bounds| if the layout is RTL; otherwise, 128 // the original value is returned unchanged. 129 int MirroredLeftPointForRect(GtkWidget* widget, const gfx::Rect& bounds); 130 131 // Returns the mirrored right value for |bounds| if the layout is RTL; 132 // otherwise, the original value is returned unchanged. 133 int MirroredRightPointForRect(GtkWidget* widget, const gfx::Rect& bounds); 134 135 // Returns the mirrored x value for the point |x| if the layout is RTL; 136 // otherwise, the original value is returned unchanged. 137 int MirroredXCoordinate(GtkWidget* widget, int x); 138 139 // Returns true if the pointer is currently inside the widget. 140 bool WidgetContainsCursor(GtkWidget* widget); 141 142 // Sets the default window icon for all windows created in this app. This icon 143 // will only be used if a window has not explicitly been assigned an icon 144 // (e.g. by SetWindowIcon()). 145 // 146 // |window| is only used to determine if a themed icon exists. If so, we use 147 // that icon, otherwise we use the icon packaged with Chrome. 148 void SetDefaultWindowIcon(GtkWindow* window); 149 150 // Sets the icon of |window| to the Chrome product icon, overlaid with 151 // |profile|'s avatar icon (or the Incognito icon for Incognito windows). It 152 // first looks for a themed icon, then falls back to the product icons 153 // packaged with Chrome. 154 void SetWindowIcon(GtkWindow* window, Profile* profile); 155 156 // Sets the icon of |window| to |icon|, overlaid with |profile|'s avatar icon 157 // (or the Incognito icon for Incognito windows). It first looks for a themed 158 // icon, then falls back to the product icons packaged with Chrome. 159 // 160 // Note that |icon| will be modified by this function. 161 void SetWindowIcon(GtkWindow* window, Profile* profile, GdkPixbuf* icon); 162 163 // Adds an action button with the given text to the dialog. Only useful when you 164 // want a stock icon but not the stock text to go with it. Returns the button. 165 GtkWidget* AddButtonToDialog(GtkWidget* dialog, const gchar* text, 166 const gchar* stock_id, gint response_id); 167 168 GtkWidget* BuildDialogButton(GtkWidget* dialog, int ids_id, 169 const gchar* stock_id); 170 171 GtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image); 172 173 // Sets all the foreground color states of |label| to |color|. 174 void SetLabelColor(GtkWidget* label, const GdkColor* color); 175 176 // Adds the given widget to an alignment identing it by |kGroupIndent|. 177 GtkWidget* IndentWidget(GtkWidget* content); 178 179 // Reverses a point in RTL mode. Used in making vectors of GdkPoints for window 180 // shapes. 181 GdkPoint MakeBidiGdkPoint(gint x, gint y, gint width, bool ltr); 182 183 // Creates a tooltip string to be passed to gtk_widget_set_tooltip_markup from 184 // the title and URL. 185 std::string BuildTooltipTitleFor(base::string16 title, const GURL& url); 186 187 // Draws a GTK text entry with the style parameters of GtkEntry 188 // |offscreen_entry| onto |widget_to_draw_on| in the rectangle |rec|. Drawing 189 // is only done in the clip rectangle |dirty_rec|. 190 void DrawTextEntryBackground(GtkWidget* offscreen_entry, 191 GtkWidget* widget_to_draw_on, 192 GdkRectangle* dirty_rec, 193 GdkRectangle* rec); 194 195 // Set up the text to be displayed by |layout|. 196 void SetLayoutText(PangoLayout* layout, const base::string16& text); 197 198 // Draws the background of the toolbar area subject to the expose rectangle 199 // |event| and starting image tiling from |tabstrip_origin|. 200 void DrawThemedToolbarBackground(GtkWidget* widget, 201 cairo_t* cr, 202 GdkEventExpose* event, 203 const gfx::Point& tabstrip_origin, 204 GtkThemeService* provider); 205 206 // Draw an entire pixbuf without dithering. 207 void DrawFullImage(cairo_t* cr, 208 GtkWidget* widget, 209 const gfx::Image& image, 210 gint dest_x, 211 gint dest_y); 212 213 // Returns the two colors averaged together. 214 GdkColor AverageColors(GdkColor color_one, GdkColor color_two); 215 216 // Show the image for the given menu item, even if the user's default is to not 217 // show images. Only to be used for favicons or other menus where the image is 218 // crucial to its functionality. 219 void SetAlwaysShowImage(GtkWidget* image_menu_item); 220 221 // Get a rectangle corresponding to a widget's allocation relative to its 222 // toplevel window's origin. 223 gfx::Rect GetWidgetRectRelativeToToplevel(GtkWidget* widget); 224 225 // Don't allow the widget to paint anything, and instead propagate the expose 226 // to its children. This is similar to calling 227 // 228 // gtk_widget_set_app_paintable(container, TRUE); 229 // 230 // except that it will always work, and it should be called after any custom 231 // expose events are connected. 232 void SuppressDefaultPainting(GtkWidget* container); 233 234 // Safely grabs all input (with X grabs and an application grab), returning true 235 // for success. 236 bool GrabAllInput(GtkWidget* widget); 237 238 // Returns a rectangle that represents the widget's bounds. The rectangle it 239 // returns is the same as gtk_widget_get_allocation, but anchored at (0, 0). 240 gfx::Rect WidgetBounds(GtkWidget* widget); 241 242 // Update the timestamp for the given window. This is usually the time of the 243 // last user event, but on rare occasions we wish to update it despite not 244 // receiving a user event. 245 void SetWMLastUserActionTime(GtkWindow* window); 246 247 // The current system time, using the format expected by the X server, but not 248 // retrieved from the X server. NOTE: You should almost never need to use this 249 // function, instead using the timestamp from the latest GDK event. 250 guint32 XTimeNow(); 251 252 // Uses the autocomplete controller for |profile| to convert the contents of the 253 // PRIMARY selection to a parsed URL. Returns true and sets |url| on success, 254 // otherwise returns false. 255 bool URLFromPrimarySelection(Profile* profile, GURL* url); 256 257 // Set the colormap of the given window to rgba to allow transparency. 258 bool AddWindowAlphaChannel(GtkWidget* window); 259 260 // Get the default colors for a text entry. Parameters may be NULL. 261 void GetTextColors(GdkColor* normal_base, 262 GdkColor* selected_base, 263 GdkColor* normal_text, 264 GdkColor* selected_text); 265 266 // Wrappers to show a GtkDialog. On Linux, it merely calls gtk_widget_show_all. 267 // On ChromeOs, it calls ShowNativeDialog which hosts the its vbox 268 // in a view based Window. 269 void ShowDialog(GtkWidget* dialog); 270 void ShowDialogWithLocalizedSize(GtkWidget* dialog, 271 int width_id, 272 int height_id, 273 bool resizeable); 274 void ShowDialogWithMinLocalizedWidth(GtkWidget* dialog, 275 int width_id); 276 277 // Wrapper to present a window. On Linux, it just calls gtk_window_present or 278 // gtk_window_present_with_time for non-zero timestamp. 279 void PresentWindow(GtkWidget* window, int timestamp); 280 281 // Gets dialog window bounds. 282 gfx::Rect GetDialogBounds(GtkWidget* dialog); 283 284 // Returns the stock menu item label for the "preferences" item - returns an 285 // empty string if no stock item found. 286 base::string16 GetStockPreferencesMenuLabel(); 287 288 // Checks whether a widget is actually visible, i.e. whether it and all its 289 // ancestors up to its toplevel are visible. 290 bool IsWidgetAncestryVisible(GtkWidget* widget); 291 292 // Sets the given label's size request to |pixel_width|. This will cause the 293 // label to wrap if it needs to. The reason for this function is that some 294 // versions of GTK mis-align labels that have a size request and line wrapping, 295 // and this function hides the complexity of the workaround. 296 void SetLabelWidth(GtkWidget* label, int pixel_width); 297 298 // Make the |label| shrinkable within a GthChromeShrinkableHBox 299 // It calculates the real size request of a label and set its ellipsize mode to 300 // PANGO_ELLIPSIZE_END. 301 // It must be done when the label is mapped (become visible on the screen), 302 // to make sure the pango can get correct font information for the calculation. 303 void InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label); 304 305 // A helper function for gtk_message_dialog_new() to work around a few KDE 3 306 // window manager bugs. You should always call it after creating a dialog with 307 // gtk_message_dialog_new. 308 void ApplyMessageDialogQuirks(GtkWidget* dialog); 309 310 } // namespace gtk_util 311 312 #endif // CHROME_BROWSER_UI_GTK_GTK_UTIL_H_ 313