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 20 typedef struct _cairo cairo_t; 21 typedef struct _GdkColor GdkColor; 22 typedef struct _GtkWidget GtkWidget; 23 24 class BrowserWindow; 25 class GtkThemeService; 26 class GURL; 27 class Profile; 28 struct RendererPreferences; // from common/renderer_preferences.h 29 30 const 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 38 namespace 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. 43 WindowOpenDisposition DispositionFromEventFlags(guint state); 44 45 } // namespace event_utils 46 47 namespace gtk_util { 48 49 extern const GdkColor kGdkWhite; 50 extern const GdkColor kGdkGray; 51 extern const GdkColor kGdkBlack; 52 extern 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. 58 const int kControlSpacing = 6; 59 60 // Horizontal spacing between a label and its control. 61 const int kLabelSpacing = 12; 62 63 // Indent of the controls within each group. 64 const int kGroupIndent = 12; 65 66 // Space around the outside of a dialog's contents. 67 const int kContentAreaBorder = 12; 68 69 // Spacing between groups of controls. 70 const int kContentAreaSpacing = 18; 71 72 // Horizontal Spacing between controls in a form. 73 const 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); 87 GtkWidget* 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. 93 GtkWidget* 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. 97 GtkWidget* LeftAlignMisc(GtkWidget* misc); 98 99 // Create a left-aligned label with the given text in bold. 100 GtkWidget* CreateBoldLabel(const std::string& text); 101 102 // As above, but uses number of characters/lines directly rather than looking up 103 // a resource. 104 void 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. 112 void 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). 122 void 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. 129 void CenterOverWindow(GtkWindow* window, GtkWindow* parent); 130 131 // Puts all browser windows in one window group; this will make any dialog 132 // spawned app modal. 133 void MakeAppModalWindowGroup(); 134 135 // Called after an app modal dialog that used MakeAppModalWindowGroup() was 136 // dismissed. Returns each browser window to its own window group. 137 void AppModalDismissedUngroupWindows(); 138 139 // Remove all children from this container. 140 void RemoveAllChildren(GtkWidget* container); 141 142 // Force the font size of the widget to |size_pixels|. 143 void 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. 147 void UndoForceFontSize(GtkWidget* widget); 148 149 // Gets the position of a gtk widget in screen coordinates. 150 gfx::Point GetWidgetScreenPosition(GtkWidget* widget); 151 152 // Returns the bounds of the specified widget in screen coordinates. 153 gfx::Rect GetWidgetScreenBounds(GtkWidget* widget); 154 155 // Retuns size of the |widget| without window manager decorations. 156 gfx::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. 160 void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p); 161 162 // Initialize some GTK settings so that our dialogs are consistent. 163 void 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. 169 GtkWidget* CenterWidgetInHBox(GtkWidget* hbox, GtkWidget* widget, 170 bool pack_at_end, int padding); 171 172 // Returns true if the screen is composited, false otherwise. 173 bool IsScreenComposited(); 174 175 // Enumerates the top-level gdk windows of the current display. 176 void 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. 182 void 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. 189 void 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. 193 int 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. 197 int MirroredXCoordinate(GtkWidget* widget, int x); 198 199 // Returns true if the pointer is currently inside the widget. 200 bool WidgetContainsCursor(GtkWidget* widget); 201 202 // Sets the icon of |window| to the product icon (potentially used in window 203 // border or alt-tab list). 204 void 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. 209 void 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. 213 GtkWidget* AddButtonToDialog(GtkWidget* dialog, const gchar* text, 214 const gchar* stock_id, gint response_id); 215 216 GtkWidget* BuildDialogButton(GtkWidget* dialog, int ids_id, 217 const gchar* stock_id); 218 219 GtkWidget* CreateEntryImageHBox(GtkWidget* entry, GtkWidget* image); 220 221 // Sets all the foreground color states of |label| to |color|. 222 void SetLabelColor(GtkWidget* label, const GdkColor* color); 223 224 // Adds the given widget to an alignment identing it by |kGroupIndent|. 225 GtkWidget* 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). 229 void UpdateGtkFontSettings(RendererPreferences* prefs); 230 231 // Get the current location of the mouse cursor relative to the screen. 232 gfx::Point ScreenPoint(GtkWidget* widget); 233 234 // Get the current location of the mouse cursor relative to the widget. 235 gfx::Point ClientPoint(GtkWidget* widget); 236 237 // Reverses a point in RTL mode. Used in making vectors of GdkPoints for window 238 // shapes. 239 GdkPoint 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|. 244 void 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|. 251 void 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. 258 GdkColor 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. 263 void SetAlwaysShowImage(GtkWidget* image_menu_item); 264 265 // Get a rectangle corresponding to a widget's allocation relative to its 266 // toplevel window's origin. 267 gfx::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. 276 void 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*. 281 WindowOpenDisposition DispositionForCurrentButtonPressEvent(); 282 283 // Safely grabs all input (with X grabs and an application grab), returning true 284 // for success. 285 bool 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). 289 gfx::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. 294 void 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. 299 guint32 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. 304 bool URLFromPrimarySelection(Profile* profile, GURL* url); 305 306 // Set the colormap of the given window to rgba to allow transparency. 307 bool AddWindowAlphaChannel(GtkWidget* window); 308 309 // Get the default colors for a text entry. Parameters may be NULL. 310 void 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. 318 void ShowDialog(GtkWidget* dialog); 319 void ShowDialogWithLocalizedSize(GtkWidget* dialog, 320 int width_id, 321 int height_id, 322 bool resizeable); 323 void 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. 329 void 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. 333 GtkWindow* GetDialogWindow(GtkWidget* dialog); 334 335 // Gets dialog window bounds. 336 gfx::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. 340 string16 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. 344 bool 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. 350 void 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. 357 void InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label); 358 359 // Convenience methods for converting between web drag operations and the GDK 360 // equivalent. 361 GdkDragAction WebDragOpToGdkDragAction(WebKit::WebDragOperationsMask op); 362 WebKit::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. 367 void ApplyMessageDialogQuirks(GtkWidget* dialog); 368 369 // Performs Cut/Copy/Paste operation on the |window|. 370 void DoCut(BrowserWindow* window); 371 void DoCopy(BrowserWindow* window); 372 void DoPaste(BrowserWindow* window); 373 374 } // namespace gtk_util 375 376 #endif // CHROME_BROWSER_UI_GTK_GTK_UTIL_H_ 377