1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11 #include "nsLookAndFeel.h"
16 #include <pango/pango.h>
17 #include <pango/pango-fontmap.h>
19 #include <fontconfig/fontconfig.h>
20 #include "gfxPlatformGtk.h"
22 #include "gtkdrawing.h"
23 #include "nsStyleConsts.h"
24 #include "gfxFontConstants.h"
25 #include "mozilla/gfx/2D.h"
27 using mozilla::LookAndFeel
;
29 #define GDK_COLOR_TO_NS_RGB(c) \
30 ((nscolor) NS_RGB(c.red>>8, c.green>>8, c.blue>>8))
31 #define GDK_RGBA_TO_NS_RGBA(c) \
32 ((nscolor) NS_RGBA((int)((c).red*255), (int)((c).green*255), \
33 (int)((c).blue*255), (int)((c).alpha*255)))
35 nsLookAndFeel::nsLookAndFeel()
37 #if (MOZ_WIDGET_GTK == 2)
40 mBackgroundStyle(nullptr),
41 mButtonStyle(nullptr),
43 mDefaultFontCached(false), mButtonFontCached(false),
44 mFieldFontCached(false), mMenuFontCached(false)
49 nsLookAndFeel::~nsLookAndFeel()
51 #if (MOZ_WIDGET_GTK == 2)
52 g_object_unref(mStyle
);
54 g_object_unref(mBackgroundStyle
);
55 g_object_unref(mButtonStyle
);
60 nsLookAndFeel::NativeGetColor(ColorID aID
, nscolor
& aColor
)
62 #if (MOZ_WIDGET_GTK == 3)
68 // These colors don't seem to be used for anything anymore in Mozilla
69 // (except here at least TextSelectBackground and TextSelectForeground)
70 // The CSS2 colors below are used.
71 #if (MOZ_WIDGET_GTK == 2)
72 case eColorID_WindowBackground
:
73 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->base
[GTK_STATE_NORMAL
]);
75 case eColorID_WindowForeground
:
76 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->text
[GTK_STATE_NORMAL
]);
78 case eColorID_WidgetBackground
:
79 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_NORMAL
]);
81 case eColorID_WidgetForeground
:
82 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->fg
[GTK_STATE_NORMAL
]);
84 case eColorID_WidgetSelectBackground
:
85 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_SELECTED
]);
87 case eColorID_WidgetSelectForeground
:
88 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->fg
[GTK_STATE_SELECTED
]);
91 case eColorID_WindowBackground
:
92 case eColorID_WidgetBackground
:
93 case eColorID_TextBackground
:
94 case eColorID_activecaption
: // active window caption background
95 case eColorID_appworkspace
: // MDI background color
96 case eColorID_background
: // desktop background
98 case eColorID_windowframe
:
99 case eColorID__moz_dialog
:
100 aColor
= sMozWindowBackground
;
102 case eColorID_WindowForeground
:
103 case eColorID_WidgetForeground
:
104 case eColorID_TextForeground
:
105 case eColorID_captiontext
: // text in active window caption, size box, and scrollbar arrow box (!)
106 case eColorID_windowtext
:
107 case eColorID__moz_dialogtext
:
108 aColor
= sMozWindowText
;
110 case eColorID_WidgetSelectBackground
:
111 case eColorID_TextSelectBackground
:
112 case eColorID_IMESelectedRawTextBackground
:
113 case eColorID_IMESelectedConvertedTextBackground
:
114 case eColorID__moz_dragtargetzone
:
115 case eColorID__moz_cellhighlight
:
116 case eColorID__moz_html_cellhighlight
:
117 case eColorID_highlight
: // preference selected item,
118 aColor
= sTextSelectedBackground
;
120 case eColorID_WidgetSelectForeground
:
121 case eColorID_TextSelectForeground
:
122 case eColorID_IMESelectedRawTextForeground
:
123 case eColorID_IMESelectedConvertedTextForeground
:
124 case eColorID_highlighttext
:
125 case eColorID__moz_cellhighlighttext
:
126 case eColorID__moz_html_cellhighlighttext
:
127 aColor
= sTextSelectedText
;
130 case eColorID_Widget3DHighlight
:
131 aColor
= NS_RGB(0xa0,0xa0,0xa0);
133 case eColorID_Widget3DShadow
:
134 aColor
= NS_RGB(0x40,0x40,0x40);
136 #if (MOZ_WIDGET_GTK == 2)
137 case eColorID_TextBackground
:
139 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->base
[GTK_STATE_NORMAL
]);
141 case eColorID_TextForeground
:
143 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->text
[GTK_STATE_NORMAL
]);
145 case eColorID_TextSelectBackground
:
146 case eColorID_IMESelectedRawTextBackground
:
147 case eColorID_IMESelectedConvertedTextBackground
:
149 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->base
[GTK_STATE_SELECTED
]);
151 case eColorID_TextSelectForeground
:
152 case eColorID_IMESelectedRawTextForeground
:
153 case eColorID_IMESelectedConvertedTextForeground
:
155 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->text
[GTK_STATE_SELECTED
]);
158 case eColorID_IMERawInputBackground
:
159 case eColorID_IMEConvertedTextBackground
:
160 aColor
= NS_TRANSPARENT
;
162 case eColorID_IMERawInputForeground
:
163 case eColorID_IMEConvertedTextForeground
:
164 aColor
= NS_SAME_AS_FOREGROUND_COLOR
;
166 case eColorID_IMERawInputUnderline
:
167 case eColorID_IMEConvertedTextUnderline
:
168 aColor
= NS_SAME_AS_FOREGROUND_COLOR
;
170 case eColorID_IMESelectedRawTextUnderline
:
171 case eColorID_IMESelectedConvertedTextUnderline
:
172 aColor
= NS_TRANSPARENT
;
174 case eColorID_SpellCheckerUnderline
:
175 aColor
= NS_RGB(0xff, 0, 0);
178 #if (MOZ_WIDGET_GTK == 2)
179 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
180 case eColorID_activeborder
:
181 // active window border
182 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_NORMAL
]);
184 case eColorID_activecaption
:
185 // active window caption background
186 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_NORMAL
]);
188 case eColorID_appworkspace
:
189 // MDI background color
190 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_NORMAL
]);
192 case eColorID_background
:
193 // desktop background
194 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_NORMAL
]);
196 case eColorID_captiontext
:
197 // text in active window caption, size box, and scrollbar arrow box (!)
198 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->fg
[GTK_STATE_NORMAL
]);
200 case eColorID_graytext
:
201 // disabled text in windows, menus, etc.
202 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->fg
[GTK_STATE_INSENSITIVE
]);
204 case eColorID_highlight
:
205 // background of selected item
206 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->base
[GTK_STATE_SELECTED
]);
208 case eColorID_highlighttext
:
209 // text of selected item
210 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->text
[GTK_STATE_SELECTED
]);
212 case eColorID_inactiveborder
:
213 // inactive window border
214 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_NORMAL
]);
216 case eColorID_inactivecaption
:
217 // inactive window caption
218 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_INSENSITIVE
]);
220 case eColorID_inactivecaptiontext
:
221 // text in inactive window caption
222 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->fg
[GTK_STATE_INSENSITIVE
]);
225 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
226 case eColorID_activeborder
:
227 // active window border
228 gtk_style_context_get_border_color(mBackgroundStyle
,
229 GTK_STATE_FLAG_NORMAL
, &gdk_color
);
230 aColor
= GDK_RGBA_TO_NS_RGBA(gdk_color
);
232 case eColorID_inactiveborder
:
233 // inactive window border
234 gtk_style_context_get_border_color(mBackgroundStyle
,
235 GTK_STATE_FLAG_INSENSITIVE
,
237 aColor
= GDK_RGBA_TO_NS_RGBA(gdk_color
);
239 case eColorID_graytext
: // disabled text in windows, menus, etc.
240 case eColorID_inactivecaptiontext
: // text in inactive window caption
241 gtk_style_context_get_color(mBackgroundStyle
,
242 GTK_STATE_FLAG_INSENSITIVE
, &gdk_color
);
243 aColor
= GDK_RGBA_TO_NS_RGBA(gdk_color
);
245 case eColorID_inactivecaption
:
246 // inactive window caption
247 gtk_style_context_get_background_color(mBackgroundStyle
,
248 GTK_STATE_FLAG_INSENSITIVE
,
250 aColor
= GDK_RGBA_TO_NS_RGBA(gdk_color
);
253 case eColorID_infobackground
:
254 // tooltip background color
255 aColor
= sInfoBackground
;
257 case eColorID_infotext
:
258 // tooltip text color
263 aColor
= sMenuBackground
;
265 case eColorID_menutext
:
269 case eColorID_scrollbar
:
270 // scrollbar gray area
271 #if (MOZ_WIDGET_GTK == 2)
272 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_ACTIVE
]);
274 aColor
= sMozScrollbar
;
278 case eColorID_threedlightshadow
:
279 // 3-D highlighted inner edge color
280 // always same as background in GTK code
281 case eColorID_threedface
:
282 case eColorID_buttonface
:
284 #if (MOZ_WIDGET_GTK == 3)
285 aColor
= sMozWindowBackground
;
287 aColor
= sButtonBackground
;
291 case eColorID_buttontext
:
292 // text on push buttons
293 aColor
= sButtonText
;
296 case eColorID_buttonhighlight
:
297 // 3-D highlighted edge color
298 case eColorID_threedhighlight
:
299 // 3-D highlighted outer edge color
300 aColor
= sFrameOuterLightBorder
;
303 case eColorID_buttonshadow
:
304 // 3-D shadow edge color
305 case eColorID_threedshadow
:
306 // 3-D shadow inner edge color
307 aColor
= sFrameInnerDarkBorder
;
310 #if (MOZ_WIDGET_GTK == 2)
311 case eColorID_threeddarkshadow
:
312 // 3-D shadow outer edge color
313 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->black
);
316 case eColorID_window
:
317 case eColorID_windowframe
:
318 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_NORMAL
]);
321 case eColorID_windowtext
:
322 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->fg
[GTK_STATE_NORMAL
]);
325 case eColorID__moz_eventreerow
:
326 case eColorID__moz_field
:
327 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->base
[GTK_STATE_NORMAL
]);
329 case eColorID__moz_fieldtext
:
330 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->text
[GTK_STATE_NORMAL
]);
332 case eColorID__moz_dialog
:
333 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_NORMAL
]);
335 case eColorID__moz_dialogtext
:
336 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->fg
[GTK_STATE_NORMAL
]);
338 case eColorID__moz_dragtargetzone
:
339 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_SELECTED
]);
341 case eColorID__moz_buttondefault
:
342 // default button border color
343 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->black
);
345 case eColorID__moz_buttonhoverface
:
346 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->bg
[GTK_STATE_PRELIGHT
]);
348 case eColorID__moz_buttonhovertext
:
349 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->fg
[GTK_STATE_PRELIGHT
]);
351 case eColorID__moz_cellhighlight
:
352 case eColorID__moz_html_cellhighlight
:
353 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->base
[GTK_STATE_ACTIVE
]);
355 case eColorID__moz_cellhighlighttext
:
356 case eColorID__moz_html_cellhighlighttext
:
357 aColor
= GDK_COLOR_TO_NS_RGB(mStyle
->text
[GTK_STATE_ACTIVE
]);
360 case eColorID_threeddarkshadow
:
362 aColor
= NS_RGB(0x00,0x00,0x00);;
365 case eColorID__moz_eventreerow
:
366 case eColorID__moz_field
:
367 aColor
= sMozFieldBackground
;
369 case eColorID__moz_fieldtext
:
370 aColor
= sMozFieldText
;
372 case eColorID__moz_buttondefault
:
373 // default button border color
374 gtk_style_context_get_border_color(mButtonStyle
,
375 GTK_STATE_FLAG_NORMAL
, &gdk_color
);
376 aColor
= GDK_RGBA_TO_NS_RGBA(gdk_color
);
378 case eColorID__moz_buttonhoverface
:
379 gtk_style_context_get_background_color(mButtonStyle
,
380 GTK_STATE_FLAG_PRELIGHT
,
382 aColor
= GDK_RGBA_TO_NS_RGBA(gdk_color
);
384 case eColorID__moz_buttonhovertext
:
385 aColor
= sButtonHoverText
;
388 case eColorID__moz_menuhover
:
391 case eColorID__moz_menuhovertext
:
392 aColor
= sMenuHoverText
;
394 case eColorID__moz_oddtreerow
:
395 aColor
= sOddCellBackground
;
397 case eColorID__moz_nativehyperlinktext
:
398 aColor
= sNativeHyperLinkText
;
400 case eColorID__moz_comboboxtext
:
401 aColor
= sComboBoxText
;
403 case eColorID__moz_combobox
:
404 aColor
= sComboBoxBackground
;
406 case eColorID__moz_menubartext
:
407 aColor
= sMenuBarText
;
409 case eColorID__moz_menubarhovertext
:
410 aColor
= sMenuBarHoverText
;
413 /* default color is BLACK */
415 res
= NS_ERROR_FAILURE
;
422 #if (MOZ_WIDGET_GTK == 2)
423 static void darken_gdk_color(GdkColor
*src
, GdkColor
*dest
)
429 red
= (gdouble
) src
->red
/ 65535.0;
430 green
= (gdouble
) src
->green
/ 65535.0;
431 blue
= (gdouble
) src
->blue
/ 65535.0;
437 dest
->red
= red
* 65535.0;
438 dest
->green
= green
* 65535.0;
439 dest
->blue
= blue
* 65535.0;
443 static int32_t CheckWidgetStyle(GtkWidget
* aWidget
, const char* aStyle
, int32_t aResult
) {
444 gboolean value
= FALSE
;
445 gtk_widget_style_get(aWidget
, aStyle
, &value
, nullptr);
446 return value
? aResult
: 0;
449 static int32_t ConvertGTKStepperStyleToMozillaScrollArrowStyle(GtkWidget
* aWidget
)
452 return mozilla::LookAndFeel::eScrollArrowStyle_Single
;
455 CheckWidgetStyle(aWidget
, "has-backward-stepper",
456 mozilla::LookAndFeel::eScrollArrow_StartBackward
) |
457 CheckWidgetStyle(aWidget
, "has-forward-stepper",
458 mozilla::LookAndFeel::eScrollArrow_EndForward
) |
459 CheckWidgetStyle(aWidget
, "has-secondary-backward-stepper",
460 mozilla::LookAndFeel::eScrollArrow_EndBackward
) |
461 CheckWidgetStyle(aWidget
, "has-secondary-forward-stepper",
462 mozilla::LookAndFeel::eScrollArrow_StartForward
);
466 nsLookAndFeel::GetIntImpl(IntID aID
, int32_t &aResult
)
468 nsresult res
= NS_OK
;
470 // Set these before they can get overrided in the nsXPLookAndFeel.
472 case eIntID_ScrollButtonLeftMouseButtonAction
:
475 case eIntID_ScrollButtonMiddleMouseButtonAction
:
478 case eIntID_ScrollButtonRightMouseButtonAction
:
485 res
= nsXPLookAndFeel::GetIntImpl(aID
, aResult
);
486 if (NS_SUCCEEDED(res
))
491 case eIntID_CaretBlinkTime
:
493 GtkSettings
*settings
;
497 settings
= gtk_settings_get_default ();
498 g_object_get (settings
,
499 "gtk-cursor-blink-time", &blink_time
,
500 "gtk-cursor-blink", &blink
,
504 aResult
= (int32_t) blink_time
;
509 case eIntID_CaretWidth
:
512 case eIntID_ShowCaretDuringSelection
:
515 case eIntID_SelectTextfieldsOnKeyFocus
:
518 GtkSettings
*settings
;
519 gboolean select_on_focus
;
521 entry
= gtk_entry_new();
522 g_object_ref_sink(entry
);
523 settings
= gtk_widget_get_settings(entry
);
524 g_object_get(settings
,
525 "gtk-entry-select-on-focus",
534 gtk_widget_destroy(entry
);
535 g_object_unref(entry
);
538 case eIntID_ScrollToClick
:
540 GtkSettings
*settings
;
541 gboolean warps_slider
= FALSE
;
543 settings
= gtk_settings_get_default ();
544 if (g_object_class_find_property (G_OBJECT_GET_CLASS(settings
),
545 "gtk-primary-button-warps-slider")) {
546 g_object_get (settings
,
547 "gtk-primary-button-warps-slider",
558 case eIntID_SubmenuDelay
:
560 GtkSettings
*settings
;
563 settings
= gtk_settings_get_default ();
564 g_object_get (settings
, "gtk-menu-popup-delay", &delay
, nullptr);
565 aResult
= (int32_t) delay
;
568 case eIntID_TooltipDelay
:
573 case eIntID_MenusCanOverlapOSBar
:
574 // we want XUL popups to be able to overlap the task bar.
577 case eIntID_SkipNavigatingDisabledMenuItem
:
580 case eIntID_DragThresholdX
:
581 case eIntID_DragThresholdY
:
583 GtkWidget
* box
= gtk_hbox_new(FALSE
, 5);
585 g_object_get(gtk_widget_get_settings(box
),
586 "gtk-dnd-drag-threshold", &threshold
,
588 g_object_ref_sink(box
);
593 case eIntID_ScrollArrowStyle
:
596 ConvertGTKStepperStyleToMozillaScrollArrowStyle(moz_gtk_get_scrollbar_widget());
598 case eIntID_ScrollSliderStyle
:
599 aResult
= eScrollThumbStyle_Proportional
;
601 case eIntID_TreeOpenDelay
:
604 case eIntID_TreeCloseDelay
:
607 case eIntID_TreeLazyScrollDelay
:
610 case eIntID_TreeScrollDelay
:
613 case eIntID_TreeScrollLinesMax
:
616 case eIntID_DWMCompositor
:
617 case eIntID_WindowsClassic
:
618 case eIntID_WindowsDefaultTheme
:
619 case eIntID_WindowsThemeIdentifier
:
620 case eIntID_OperatingSystemVersionIdentifier
:
622 res
= NS_ERROR_NOT_IMPLEMENTED
;
624 case eIntID_TouchEnabled
:
626 res
= NS_ERROR_NOT_IMPLEMENTED
;
628 case eIntID_MacGraphiteTheme
:
629 case eIntID_MacLionTheme
:
631 res
= NS_ERROR_NOT_IMPLEMENTED
;
633 case eIntID_AlertNotificationOrigin
:
634 aResult
= NS_ALERT_TOP
;
636 case eIntID_IMERawInputUnderlineStyle
:
637 case eIntID_IMEConvertedTextUnderlineStyle
:
638 aResult
= NS_STYLE_TEXT_DECORATION_STYLE_SOLID
;
640 case eIntID_IMESelectedRawTextUnderlineStyle
:
641 case eIntID_IMESelectedConvertedTextUnderline
:
642 aResult
= NS_STYLE_TEXT_DECORATION_STYLE_NONE
;
644 case eIntID_SpellCheckerUnderlineStyle
:
645 aResult
= NS_STYLE_TEXT_DECORATION_STYLE_WAVY
;
647 case eIntID_ImagesInMenus
:
648 aResult
= moz_gtk_images_in_menus();
650 case eIntID_ImagesInButtons
:
651 aResult
= moz_gtk_images_in_buttons();
653 case eIntID_MenuBarDrag
:
654 aResult
= sMenuSupportsDrag
;
656 case eIntID_ScrollbarButtonAutoRepeatBehavior
:
659 case eIntID_SwipeAnimationEnabled
:
662 case eIntID_ColorPickerAvailable
:
667 res
= NS_ERROR_FAILURE
;
674 nsLookAndFeel::GetFloatImpl(FloatID aID
, float &aResult
)
676 nsresult res
= NS_OK
;
677 res
= nsXPLookAndFeel::GetFloatImpl(aID
, aResult
);
678 if (NS_SUCCEEDED(res
))
683 case eFloatID_IMEUnderlineRelativeSize
:
686 case eFloatID_SpellCheckerUnderlineRelativeSize
:
689 case eFloatID_CaretAspectRatio
:
690 aResult
= sCaretRatio
;
694 res
= NS_ERROR_FAILURE
;
700 GetSystemFontInfo(GtkWidget
*aWidget
,
702 gfxFontStyle
*aFontStyle
)
704 GtkSettings
*settings
= gtk_widget_get_settings(aWidget
);
706 aFontStyle
->style
= NS_FONT_STYLE_NORMAL
;
709 g_object_get(settings
, "gtk-font-name", &fontname
, nullptr);
711 PangoFontDescription
*desc
;
712 desc
= pango_font_description_from_string(fontname
);
714 aFontStyle
->systemFont
= true;
718 NS_NAMED_LITERAL_STRING(quote
, "\"");
719 NS_ConvertUTF8toUTF16
family(pango_font_description_get_family(desc
));
720 *aFontName
= quote
+ family
+ quote
;
722 aFontStyle
->weight
= pango_font_description_get_weight(desc
);
724 // FIXME: Set aFontStyle->stretch correctly!
725 aFontStyle
->stretch
= NS_FONT_STRETCH_NORMAL
;
727 float size
= float(pango_font_description_get_size(desc
)) / PANGO_SCALE
;
729 // |size| is now either pixels or pango-points (not Mozilla-points!)
731 if (!pango_font_description_get_size_is_absolute(desc
)) {
732 // |size| is in pango-points, so convert to pixels.
733 size
*= float(gfxPlatformGtk::GetDPI()) / POINTS_PER_INCH_FLOAT
;
736 // |size| is now pixels
738 aFontStyle
->size
= size
;
740 pango_font_description_free(desc
);
744 GetSystemFontInfo(LookAndFeel::FontID aID
,
746 gfxFontStyle
*aFontStyle
)
748 if (aID
== LookAndFeel::eFont_Widget
) {
749 GtkWidget
*label
= gtk_label_new("M");
750 GtkWidget
*parent
= gtk_fixed_new();
751 GtkWidget
*window
= gtk_window_new(GTK_WINDOW_POPUP
);
753 gtk_container_add(GTK_CONTAINER(parent
), label
);
754 gtk_container_add(GTK_CONTAINER(window
), parent
);
756 gtk_widget_ensure_style(label
);
757 GetSystemFontInfo(label
, aFontName
, aFontStyle
);
758 gtk_widget_destroy(window
); // no unref, windows are different
760 } else if (aID
== LookAndFeel::eFont_Button
) {
761 GtkWidget
*label
= gtk_label_new("M");
762 GtkWidget
*parent
= gtk_fixed_new();
763 GtkWidget
*button
= gtk_button_new();
764 GtkWidget
*window
= gtk_window_new(GTK_WINDOW_POPUP
);
766 gtk_container_add(GTK_CONTAINER(button
), label
);
767 gtk_container_add(GTK_CONTAINER(parent
), button
);
768 gtk_container_add(GTK_CONTAINER(window
), parent
);
770 gtk_widget_ensure_style(label
);
771 GetSystemFontInfo(label
, aFontName
, aFontStyle
);
772 gtk_widget_destroy(window
); // no unref, windows are different
774 } else if (aID
== LookAndFeel::eFont_Field
) {
775 GtkWidget
*entry
= gtk_entry_new();
776 GtkWidget
*parent
= gtk_fixed_new();
777 GtkWidget
*window
= gtk_window_new(GTK_WINDOW_POPUP
);
779 gtk_container_add(GTK_CONTAINER(parent
), entry
);
780 gtk_container_add(GTK_CONTAINER(window
), parent
);
782 gtk_widget_ensure_style(entry
);
783 GetSystemFontInfo(entry
, aFontName
, aFontStyle
);
784 gtk_widget_destroy(window
); // no unref, windows are different
787 NS_ABORT_IF_FALSE(aID
== LookAndFeel::eFont_Menu
, "unexpected font ID");
788 GtkWidget
*accel_label
= gtk_accel_label_new("M");
789 GtkWidget
*menuitem
= gtk_menu_item_new();
790 GtkWidget
*menu
= gtk_menu_new();
791 g_object_ref_sink(menu
);
793 gtk_container_add(GTK_CONTAINER(menuitem
), accel_label
);
794 gtk_menu_shell_append((GtkMenuShell
*)GTK_MENU(menu
), menuitem
);
796 gtk_widget_ensure_style(accel_label
);
797 GetSystemFontInfo(accel_label
, aFontName
, aFontStyle
);
798 g_object_unref(menu
);
803 nsLookAndFeel::GetFontImpl(FontID aID
, nsString
& aFontName
,
804 gfxFontStyle
& aFontStyle
,
805 float aDevPixPerCSSPixel
)
807 nsString
*cachedFontName
= nullptr;
808 gfxFontStyle
*cachedFontStyle
= nullptr;
809 bool *isCached
= nullptr;
812 case eFont_Menu
: // css2
813 case eFont_PullDownMenu
: // css3
814 cachedFontName
= &mMenuFontName
;
815 cachedFontStyle
= &mMenuFontStyle
;
816 isCached
= &mMenuFontCached
;
820 case eFont_Field
: // css3
821 case eFont_List
: // css3
822 cachedFontName
= &mFieldFontName
;
823 cachedFontStyle
= &mFieldFontStyle
;
824 isCached
= &mFieldFontCached
;
828 case eFont_Button
: // css3
829 cachedFontName
= &mButtonFontName
;
830 cachedFontStyle
= &mButtonFontStyle
;
831 isCached
= &mButtonFontCached
;
834 case eFont_Caption
: // css2
835 case eFont_Icon
: // css2
836 case eFont_MessageBox
: // css2
837 case eFont_SmallCaption
: // css2
838 case eFont_StatusBar
: // css2
839 case eFont_Window
: // css3
840 case eFont_Document
: // css3
841 case eFont_Workspace
: // css3
842 case eFont_Desktop
: // css3
843 case eFont_Info
: // css3
844 case eFont_Dialog
: // css3
845 case eFont_Tooltips
: // moz
846 case eFont_Widget
: // moz
847 cachedFontName
= &mDefaultFontName
;
848 cachedFontStyle
= &mDefaultFontStyle
;
849 isCached
= &mDefaultFontCached
;
855 GetSystemFontInfo(aID
, cachedFontName
, cachedFontStyle
);
859 aFontName
= *cachedFontName
;
860 aFontStyle
= *cachedFontStyle
;
864 #if (MOZ_WIDGET_GTK == 3)
865 static GtkStyleContext
*
866 create_context(GtkWidgetPath
*path
)
868 GtkStyleContext
*style
= gtk_style_context_new();
869 gtk_style_context_set_path(style
, path
);
875 nsLookAndFeel::Init()
878 GdkColor
*colorValuePtr
;
880 #if (MOZ_WIDGET_GTK == 2)
881 NS_ASSERTION(!mStyle
, "already initialized");
882 // GtkInvisibles come with a refcount that is not floating
883 // (since their initialization code calls g_object_ref_sink) and
884 // their destroy code releases that reference (which means they
885 // have to be explicitly destroyed, since calling unref enough
886 // to cause destruction would lead to *another* unref).
887 // However, this combination means that it's actually still ok
888 // to use the normal pattern, which is to g_object_ref_sink
889 // after construction, and then destroy *and* unref when we're
890 // done. (Though we could skip the g_object_ref_sink and the
891 // corresponding g_object_unref, but that's particular to
892 // GtkInvisibles and GtkWindows.)
893 GtkWidget
*widget
= gtk_invisible_new();
894 g_object_ref_sink(widget
); // effectively g_object_ref (see above)
896 gtk_widget_ensure_style(widget
);
897 mStyle
= gtk_style_copy(gtk_widget_get_style(widget
));
899 gtk_widget_destroy(widget
);
900 g_object_unref(widget
);
902 // tooltip foreground and background
903 GtkStyle
*style
= gtk_rc_get_style_by_paths(gtk_settings_get_default(),
904 "gtk-tooltips", "GtkWindow",
907 sInfoBackground
= GDK_COLOR_TO_NS_RGB(style
->bg
[GTK_STATE_NORMAL
]);
908 sInfoText
= GDK_COLOR_TO_NS_RGB(style
->fg
[GTK_STATE_NORMAL
]);
911 // menu foreground & menu background
912 GtkWidget
*accel_label
= gtk_accel_label_new("M");
913 GtkWidget
*menuitem
= gtk_menu_item_new();
914 GtkWidget
*menu
= gtk_menu_new();
916 g_object_ref_sink(menu
);
918 gtk_container_add(GTK_CONTAINER(menuitem
), accel_label
);
919 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
921 gtk_widget_set_style(accel_label
, nullptr);
922 gtk_widget_set_style(menu
, nullptr);
923 gtk_widget_realize(menu
);
924 gtk_widget_realize(accel_label
);
926 style
= gtk_widget_get_style(accel_label
);
928 sMenuText
= GDK_COLOR_TO_NS_RGB(style
->fg
[GTK_STATE_NORMAL
]);
931 style
= gtk_widget_get_style(menu
);
933 sMenuBackground
= GDK_COLOR_TO_NS_RGB(style
->bg
[GTK_STATE_NORMAL
]);
936 style
= gtk_widget_get_style(menuitem
);
938 sMenuHover
= GDK_COLOR_TO_NS_RGB(style
->bg
[GTK_STATE_PRELIGHT
]);
939 sMenuHoverText
= GDK_COLOR_TO_NS_RGB(style
->fg
[GTK_STATE_PRELIGHT
]);
942 g_object_unref(menu
);
945 GtkStyleContext
*style
;
947 // Gtk manages a screen's CSS in the settings object so we
948 // ask Gtk to create it explicitly. Otherwise we may end up
949 // with wrong color theme, see Bug 972382
950 (void)gtk_settings_get_for_screen(gdk_screen_get_default());
952 GtkWidgetPath
*path
= gtk_widget_path_new();
953 gtk_widget_path_append_type(path
, GTK_TYPE_WINDOW
);
955 mBackgroundStyle
= create_context(path
);
956 gtk_style_context_add_class(mBackgroundStyle
, GTK_STYLE_CLASS_BACKGROUND
);
958 mButtonStyle
= create_context(path
);
959 gtk_style_context_add_class(mButtonStyle
, GTK_STYLE_CLASS_BUTTON
);
962 style
= create_context(path
);
963 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_SCROLLBAR
);
964 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_TROUGH
);
965 gtk_style_context_get_background_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
966 sMozScrollbar
= GDK_RGBA_TO_NS_RGBA(color
);
967 g_object_unref(style
);
970 style
= create_context(path
);
971 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_VIEW
);
972 gtk_style_context_get_background_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
973 sMozFieldBackground
= GDK_RGBA_TO_NS_RGBA(color
);
974 gtk_style_context_get_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
975 sMozFieldText
= GDK_RGBA_TO_NS_RGBA(color
);
977 // Selected text and background
978 gtk_style_context_get_background_color(style
,
979 static_cast<GtkStateFlags
>(GTK_STATE_FLAG_FOCUSED
|GTK_STATE_FLAG_SELECTED
),
981 sTextSelectedBackground
= GDK_RGBA_TO_NS_RGBA(color
);
982 gtk_style_context_get_color(style
,
983 static_cast<GtkStateFlags
>(GTK_STATE_FLAG_FOCUSED
|GTK_STATE_FLAG_SELECTED
),
985 sTextSelectedText
= GDK_RGBA_TO_NS_RGBA(color
);
986 g_object_unref(style
);
989 style
= create_context(path
);
990 gtk_style_context_save(style
);
991 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_BACKGROUND
);
992 gtk_style_context_get_background_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
993 sMozWindowBackground
= GDK_RGBA_TO_NS_RGBA(color
);
994 gtk_style_context_get_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
995 sMozWindowText
= GDK_RGBA_TO_NS_RGBA(color
);
996 gtk_style_context_restore(style
);
998 // tooltip foreground and background
999 gtk_style_context_add_class(style
, GTK_STYLE_CLASS_TOOLTIP
);
1000 gtk_style_context_get_background_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1001 sInfoBackground
= GDK_RGBA_TO_NS_RGBA(color
);
1002 gtk_style_context_get_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1003 sInfoText
= GDK_RGBA_TO_NS_RGBA(color
);
1004 g_object_unref(style
);
1006 // menu foreground & menu background
1007 GtkWidget
*accel_label
= gtk_accel_label_new("M");
1008 GtkWidget
*menuitem
= gtk_menu_item_new();
1009 GtkWidget
*menu
= gtk_menu_new();
1011 g_object_ref_sink(menu
);
1013 gtk_container_add(GTK_CONTAINER(menuitem
), accel_label
);
1014 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
1016 style
= gtk_widget_get_style_context(accel_label
);
1017 gtk_style_context_get_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1018 sMenuText
= GDK_RGBA_TO_NS_RGBA(color
);
1020 style
= gtk_widget_get_style_context(menu
);
1021 gtk_style_context_get_background_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1022 sMenuBackground
= GDK_RGBA_TO_NS_RGBA(color
);
1024 style
= gtk_widget_get_style_context(menuitem
);
1025 gtk_style_context_get_background_color(style
, GTK_STATE_FLAG_PRELIGHT
, &color
);
1026 sMenuHover
= GDK_RGBA_TO_NS_RGBA(color
);
1027 gtk_style_context_get_color(style
, GTK_STATE_FLAG_PRELIGHT
, &color
);
1028 sMenuHoverText
= GDK_RGBA_TO_NS_RGBA(color
);
1030 g_object_unref(menu
);
1034 GtkWidget
*parent
= gtk_fixed_new();
1035 GtkWidget
*button
= gtk_button_new();
1036 GtkWidget
*label
= gtk_label_new("M");
1037 #if (MOZ_WIDGET_GTK == 2)
1038 GtkWidget
*combobox
= gtk_combo_box_new();
1039 GtkWidget
*comboboxLabel
= gtk_label_new("M");
1040 gtk_container_add(GTK_CONTAINER(combobox
), comboboxLabel
);
1042 GtkWidget
*combobox
= gtk_combo_box_new_with_entry();
1043 GtkWidget
*comboboxLabel
= gtk_bin_get_child(GTK_BIN(combobox
));
1045 GtkWidget
*window
= gtk_window_new(GTK_WINDOW_POPUP
);
1046 GtkWidget
*treeView
= gtk_tree_view_new();
1047 GtkWidget
*linkButton
= gtk_link_button_new("http://example.com/");
1048 GtkWidget
*menuBar
= gtk_menu_bar_new();
1049 GtkWidget
*entry
= gtk_entry_new();
1051 gtk_container_add(GTK_CONTAINER(button
), label
);
1052 gtk_container_add(GTK_CONTAINER(parent
), button
);
1053 gtk_container_add(GTK_CONTAINER(parent
), treeView
);
1054 gtk_container_add(GTK_CONTAINER(parent
), linkButton
);
1055 gtk_container_add(GTK_CONTAINER(parent
), combobox
);
1056 gtk_container_add(GTK_CONTAINER(parent
), menuBar
);
1057 gtk_container_add(GTK_CONTAINER(window
), parent
);
1058 gtk_container_add(GTK_CONTAINER(parent
), entry
);
1060 #if (MOZ_WIDGET_GTK == 2)
1061 gtk_widget_set_style(button
, nullptr);
1062 gtk_widget_set_style(label
, nullptr);
1063 gtk_widget_set_style(treeView
, nullptr);
1064 gtk_widget_set_style(linkButton
, nullptr);
1065 gtk_widget_set_style(combobox
, nullptr);
1066 gtk_widget_set_style(comboboxLabel
, nullptr);
1067 gtk_widget_set_style(menuBar
, nullptr);
1068 gtk_widget_set_style(entry
, nullptr);
1070 gtk_widget_realize(button
);
1071 gtk_widget_realize(label
);
1072 gtk_widget_realize(treeView
);
1073 gtk_widget_realize(linkButton
);
1074 gtk_widget_realize(combobox
);
1075 gtk_widget_realize(comboboxLabel
);
1076 gtk_widget_realize(menuBar
);
1077 gtk_widget_realize(entry
);
1079 style
= gtk_widget_get_style(label
);
1081 sButtonText
= GDK_COLOR_TO_NS_RGB(style
->fg
[GTK_STATE_NORMAL
]);
1084 style
= gtk_widget_get_style(comboboxLabel
);
1086 sComboBoxText
= GDK_COLOR_TO_NS_RGB(style
->fg
[GTK_STATE_NORMAL
]);
1088 style
= gtk_widget_get_style(combobox
);
1090 sComboBoxBackground
= GDK_COLOR_TO_NS_RGB(style
->bg
[GTK_STATE_NORMAL
]);
1093 style
= gtk_widget_get_style(menuBar
);
1095 sMenuBarText
= GDK_COLOR_TO_NS_RGB(style
->fg
[GTK_STATE_NORMAL
]);
1096 sMenuBarHoverText
= GDK_COLOR_TO_NS_RGB(style
->fg
[GTK_STATE_SELECTED
]);
1099 // GTK's guide to fancy odd row background colors:
1100 // 1) Check if a theme explicitly defines an odd row color
1101 // 2) If not, check if it defines an even row color, and darken it
1102 // slightly by a hardcoded value (gtkstyle.c)
1103 // 3) If neither are defined, take the base background color and
1104 // darken that by a hardcoded value
1105 colorValuePtr
= nullptr;
1106 gtk_widget_style_get(treeView
,
1107 "odd-row-color", &colorValuePtr
,
1110 if (colorValuePtr
) {
1111 colorValue
= *colorValuePtr
;
1113 gtk_widget_style_get(treeView
,
1114 "even-row-color", &colorValuePtr
,
1117 darken_gdk_color(colorValuePtr
, &colorValue
);
1119 darken_gdk_color(&treeView
->style
->base
[GTK_STATE_NORMAL
], &colorValue
);
1122 sOddCellBackground
= GDK_COLOR_TO_NS_RGB(colorValue
);
1124 gdk_color_free(colorValuePtr
);
1126 style
= gtk_widget_get_style(button
);
1128 sButtonBackground
= GDK_COLOR_TO_NS_RGB(style
->bg
[GTK_STATE_NORMAL
]);
1129 sFrameOuterLightBorder
=
1130 GDK_COLOR_TO_NS_RGB(style
->light
[GTK_STATE_NORMAL
]);
1131 sFrameInnerDarkBorder
=
1132 GDK_COLOR_TO_NS_RGB(style
->dark
[GTK_STATE_NORMAL
]);
1135 // Button text, background, border
1136 style
= gtk_widget_get_style_context(label
);
1137 gtk_style_context_get_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1138 sButtonText
= GDK_RGBA_TO_NS_RGBA(color
);
1139 gtk_style_context_get_color(style
, GTK_STATE_FLAG_PRELIGHT
, &color
);
1140 sButtonHoverText
= GDK_RGBA_TO_NS_RGBA(color
);
1142 // Combobox label and background colors
1143 style
= gtk_widget_get_style_context(comboboxLabel
);
1144 gtk_style_context_get_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1145 sComboBoxText
= GDK_RGBA_TO_NS_RGBA(color
);
1147 style
= gtk_widget_get_style_context(combobox
);
1148 gtk_style_context_get_background_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1149 sComboBoxBackground
= GDK_RGBA_TO_NS_RGBA(color
);
1151 // Menubar text and hover text colors
1152 style
= gtk_widget_get_style_context(menuBar
);
1153 gtk_style_context_get_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1154 sMenuBarText
= GDK_RGBA_TO_NS_RGBA(color
);
1155 gtk_style_context_get_color(style
, GTK_STATE_FLAG_PRELIGHT
, &color
);
1156 sMenuBarHoverText
= GDK_RGBA_TO_NS_RGBA(color
);
1158 // GTK's guide to fancy odd row background colors:
1159 // 1) Check if a theme explicitly defines an odd row color
1160 // 2) If not, check if it defines an even row color, and darken it
1161 // slightly by a hardcoded value (gtkstyle.c)
1162 // 3) If neither are defined, take the base background color and
1163 // darken that by a hardcoded value
1164 style
= gtk_widget_get_style_context(treeView
);
1166 // Get odd row background color
1167 gtk_style_context_save(style
);
1168 gtk_style_context_add_region(style
, GTK_STYLE_REGION_ROW
, GTK_REGION_ODD
);
1169 gtk_style_context_get_background_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1170 sOddCellBackground
= GDK_RGBA_TO_NS_RGBA(color
);
1171 gtk_style_context_restore(style
);
1173 GtkWidget
*frame
= gtk_frame_new(nullptr);
1174 gtk_container_add(GTK_CONTAINER(parent
), frame
);
1176 // TODO GTK3 - update sFrameOuterLightBorder
1177 // for GTK_BORDER_STYLE_INSET/OUTSET/GROVE/RIDGE border styles (Bug 978172).
1178 style
= gtk_widget_get_style_context(frame
);
1179 gtk_style_context_get_border_color(style
, GTK_STATE_FLAG_NORMAL
, &color
);
1180 sFrameInnerDarkBorder
= sFrameOuterLightBorder
= GDK_RGBA_TO_NS_RGBA(color
);
1182 // Some themes have a unified menu bar, and support window dragging on it
1183 gboolean supports_menubar_drag
= FALSE
;
1184 GParamSpec
*param_spec
=
1185 gtk_widget_class_find_style_property(GTK_WIDGET_GET_CLASS(menuBar
),
1188 if (g_type_is_a(G_PARAM_SPEC_VALUE_TYPE(param_spec
), G_TYPE_BOOLEAN
)) {
1189 gtk_widget_style_get(menuBar
,
1190 "window-dragging", &supports_menubar_drag
,
1194 sMenuSupportsDrag
= supports_menubar_drag
;
1196 colorValuePtr
= nullptr;
1197 gtk_widget_style_get(linkButton
, "link-color", &colorValuePtr
, nullptr);
1198 if (colorValuePtr
) {
1199 colorValue
= *colorValuePtr
; // we can't pass deref pointers to GDK_COLOR_TO_NS_RGB
1200 sNativeHyperLinkText
= GDK_COLOR_TO_NS_RGB(colorValue
);
1201 gdk_color_free(colorValuePtr
);
1203 sNativeHyperLinkText
= NS_RGB(0x00,0x00,0xEE);
1206 // invisible character styles
1208 g_object_get (entry
, "invisible-char", &value
, nullptr);
1209 sInvisibleCharacter
= char16_t(value
);
1212 gtk_widget_style_get(entry
,
1213 "cursor-aspect-ratio", &sCaretRatio
,
1216 gtk_widget_destroy(window
);
1221 nsLookAndFeel::GetPasswordCharacterImpl()
1223 return sInvisibleCharacter
;
1227 nsLookAndFeel::RefreshImpl()
1229 nsXPLookAndFeel::RefreshImpl();
1231 mDefaultFontCached
= false;
1232 mButtonFontCached
= false;
1233 mFieldFontCached
= false;
1234 mMenuFontCached
= false;
1236 #if (MOZ_WIDGET_GTK == 2)
1237 g_object_unref(mStyle
);
1240 g_object_unref(mBackgroundStyle
);
1241 g_object_unref(mButtonStyle
);
1243 mBackgroundStyle
= nullptr;
1244 mButtonStyle
= nullptr;
1251 nsLookAndFeel::GetEchoPasswordImpl() {