mozilla-gtk3_20.patch
branchfirefox49
changeset 930 fdfd88b0c2d7
parent 929 9fc2ebe6d7f1
child 931 c5f980be6e8b
equal deleted inserted replaced
929:9fc2ebe6d7f1 930:fdfd88b0c2d7
     1 diff -up firefox-48.0/widget/gtk/gtk3drawing.cpp.gtk3-20 firefox-48.0/widget/gtk/gtk3drawing.cpp
       
     2 --- firefox-48.0/widget/gtk/gtk3drawing.cpp.gtk3-20	2016-07-25 22:22:07.000000000 +0200
       
     3 +++ firefox-48.0/widget/gtk/gtk3drawing.cpp	2016-07-29 09:15:11.822285857 +0200
       
     4 @@ -18,15 +18,9 @@
       
     5  
       
     6  #include <math.h>
       
     7  
       
     8 -static GtkWidget* gProtoWindow;
       
     9  static GtkWidget* gProtoLayout;
       
    10 -static GtkWidget* gButtonWidget;
       
    11 -static GtkWidget* gToggleButtonWidget;
       
    12 -static GtkWidget* gButtonArrowWidget;
       
    13 -static GtkWidget* gSpinWidget;
       
    14  static GtkWidget* gHScaleWidget;
       
    15  static GtkWidget* gVScaleWidget;
       
    16 -static GtkWidget* gEntryWidget;
       
    17  static GtkWidget* gComboBoxWidget;
       
    18  static GtkWidget* gComboBoxButtonWidget;
       
    19  static GtkWidget* gComboBoxArrowWidget;
       
    20 @@ -35,30 +29,15 @@ static GtkWidget* gComboBoxEntryWidget;
       
    21  static GtkWidget* gComboBoxEntryTextareaWidget;
       
    22  static GtkWidget* gComboBoxEntryButtonWidget;
       
    23  static GtkWidget* gComboBoxEntryArrowWidget;
       
    24 -static GtkWidget* gHandleBoxWidget;
       
    25 -static GtkWidget* gToolbarWidget;
       
    26 -static GtkWidget* gFrameWidget;
       
    27 -static GtkWidget* gProgressWidget;
       
    28  static GtkWidget* gTabWidget;
       
    29 -static GtkWidget* gTextViewWidget;
       
    30 -static GtkWidget* gTooltipWidget;
       
    31 -static GtkWidget* gMenuBarWidget;
       
    32 -static GtkWidget* gMenuBarItemWidget;
       
    33 -static GtkWidget* gMenuPopupWidget;
       
    34 -static GtkWidget* gMenuItemWidget;
       
    35  static GtkWidget* gImageMenuItemWidget;
       
    36  static GtkWidget* gCheckMenuItemWidget;
       
    37  static GtkWidget* gTreeViewWidget;
       
    38  static GtkTreeViewColumn* gMiddleTreeViewColumn;
       
    39  static GtkWidget* gTreeHeaderCellWidget;
       
    40  static GtkWidget* gTreeHeaderSortArrowWidget;
       
    41 -static GtkWidget* gExpanderWidget;
       
    42 -static GtkWidget* gToolbarSeparatorWidget;
       
    43 -static GtkWidget* gMenuSeparatorWidget;
       
    44  static GtkWidget* gHPanedWidget;
       
    45  static GtkWidget* gVPanedWidget;
       
    46 -static GtkWidget* gScrolledWindowWidget;
       
    47 -static GtkWidget* gInfoBar;
       
    48  
       
    49  static style_prop_t style_prop_func;
       
    50  static gboolean have_arrow_scaling;
       
    51 @@ -94,15 +73,6 @@ GetStateFlagsFromGtkWidgetState(GtkWidge
       
    52      return stateFlags;
       
    53  }
       
    54  
       
    55 -/* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine
       
    56 -   that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific
       
    57 -   things they may want to do. */
       
    58 -static void
       
    59 -moz_gtk_set_widget_name(GtkWidget* widget)
       
    60 -{
       
    61 -    gtk_widget_set_name(widget, "MozillaGtkWidget");
       
    62 -}
       
    63 -
       
    64  gint
       
    65  moz_gtk_enable_style_props(style_prop_t styleGetProp)
       
    66  {
       
    67 @@ -111,15 +81,6 @@ moz_gtk_enable_style_props(style_prop_t
       
    68  }
       
    69  
       
    70  static gint
       
    71 -ensure_window_widget()
       
    72 -{
       
    73 -    if (!gProtoWindow) {
       
    74 -        gProtoWindow = GetWidget(MOZ_GTK_WINDOW);
       
    75 -    }
       
    76 -    return MOZ_GTK_SUCCESS;
       
    77 -}
       
    78 -
       
    79 -static gint
       
    80  setup_widget_prototype(GtkWidget* widget)
       
    81  {
       
    82      if (!gProtoLayout) {
       
    83 @@ -130,16 +91,6 @@ setup_widget_prototype(GtkWidget* widget
       
    84  }
       
    85  
       
    86  static gint
       
    87 -ensure_button_widget()
       
    88 -{
       
    89 -    if (!gButtonWidget) {
       
    90 -        gButtonWidget = gtk_button_new_with_label("M");
       
    91 -        setup_widget_prototype(gButtonWidget);
       
    92 -    }
       
    93 -    return MOZ_GTK_SUCCESS;
       
    94 -}
       
    95 -
       
    96 -static gint
       
    97  ensure_hpaned_widget()
       
    98  {
       
    99      if (!gHPanedWidget) {
       
   100 @@ -160,40 +111,6 @@ ensure_vpaned_widget()
       
   101  }
       
   102  
       
   103  static gint
       
   104 -ensure_toggle_button_widget()
       
   105 -{
       
   106 -    if (!gToggleButtonWidget) {
       
   107 -        gToggleButtonWidget = gtk_toggle_button_new();
       
   108 -        setup_widget_prototype(gToggleButtonWidget);
       
   109 -  }
       
   110 -  return MOZ_GTK_SUCCESS;
       
   111 -}
       
   112 -
       
   113 -static gint
       
   114 -ensure_button_arrow_widget()
       
   115 -{
       
   116 -    if (!gButtonArrowWidget) {
       
   117 -        ensure_toggle_button_widget();
       
   118 -
       
   119 -        gButtonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
       
   120 -        gtk_container_add(GTK_CONTAINER(gToggleButtonWidget), gButtonArrowWidget);
       
   121 -        gtk_widget_realize(gButtonArrowWidget);
       
   122 -        gtk_widget_show(gButtonArrowWidget);
       
   123 -    }
       
   124 -    return MOZ_GTK_SUCCESS;
       
   125 -}
       
   126 -
       
   127 -static gint
       
   128 -ensure_spin_widget()
       
   129 -{
       
   130 -  if (!gSpinWidget) {
       
   131 -    gSpinWidget = gtk_spin_button_new(NULL, 1, 0);
       
   132 -    setup_widget_prototype(gSpinWidget);
       
   133 -  }
       
   134 -  return MOZ_GTK_SUCCESS;
       
   135 -}
       
   136 -
       
   137 -static gint
       
   138  ensure_scale_widget()
       
   139  {
       
   140    if (!gHScaleWidget) {
       
   141 @@ -207,16 +124,6 @@ ensure_scale_widget()
       
   142    return MOZ_GTK_SUCCESS;
       
   143  }
       
   144  
       
   145 -static gint
       
   146 -ensure_entry_widget()
       
   147 -{
       
   148 -    if (!gEntryWidget) {
       
   149 -        gEntryWidget = gtk_entry_new();
       
   150 -        setup_widget_prototype(gEntryWidget);
       
   151 -    }
       
   152 -    return MOZ_GTK_SUCCESS;
       
   153 -}
       
   154 -
       
   155  /* We need to have pointers to the inner widgets (button, separator, arrow)
       
   156   * of the ComboBox to get the correct rendering from theme engines which
       
   157   * special cases their look. Since the inner layout can change, we ask GTK
       
   158 @@ -225,7 +132,7 @@ ensure_entry_widget()
       
   159   * g_object_add_weak_pointer().
       
   160   * Note that if we don't find the inner widgets (which shouldn't happen), we
       
   161   * fallback to use generic "non-inner" widgets, and they don't need that kind
       
   162 - * of weak pointer since they are explicit children of gProtoWindow and as
       
   163 + * of weak pointer since they are explicit children of gProtoLayout and as
       
   164   * such GTK holds a strong reference to them. */
       
   165  static void
       
   166  moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data)
       
   167 @@ -297,16 +204,14 @@ ensure_combo_box_widgets()
       
   168          /* Shouldn't be reached with current internal gtk implementation; we
       
   169           * use a generic toggle button as last resort fallback to avoid
       
   170           * crashing. */
       
   171 -        ensure_toggle_button_widget();
       
   172 -        gComboBoxButtonWidget = gToggleButtonWidget;
       
   173 +        gComboBoxButtonWidget = GetWidget(MOZ_GTK_TOGGLE_BUTTON);
       
   174      }
       
   175  
       
   176      if (!gComboBoxArrowWidget) {
       
   177          /* Shouldn't be reached with current internal gtk implementation;
       
   178           * we gButtonArrowWidget as last resort fallback to avoid
       
   179           * crashing. */
       
   180 -        ensure_button_arrow_widget();
       
   181 -        gComboBoxArrowWidget = gButtonArrowWidget;
       
   182 +        gComboBoxArrowWidget = GetWidget(MOZ_GTK_BUTTON_ARROW);
       
   183      }
       
   184  
       
   185      /* We don't test the validity of gComboBoxSeparatorWidget since there
       
   186 @@ -316,15 +221,6 @@ ensure_combo_box_widgets()
       
   187      return MOZ_GTK_SUCCESS;
       
   188  }
       
   189  
       
   190 -static void
       
   191 -ensure_info_bar()
       
   192 -{
       
   193 -  if (!gInfoBar) {
       
   194 -      gInfoBar = gtk_info_bar_new();
       
   195 -      setup_widget_prototype(gInfoBar);
       
   196 -  }
       
   197 -}
       
   198 -
       
   199  /* We need to have pointers to the inner widgets (entry, button, arrow) of
       
   200   * the ComboBoxEntry to get the correct rendering from theme engines which
       
   201   * special cases their look. Since the inner layout can change, we ask GTK
       
   202 @@ -333,7 +229,7 @@ ensure_info_bar()
       
   203   * g_object_add_weak_pointer().
       
   204   * Note that if we don't find the inner widgets (which shouldn't happen), we
       
   205   * fallback to use generic "non-inner" widgets, and they don't need that kind
       
   206 - * of weak pointer since they are explicit children of gProtoWindow and as
       
   207 + * of weak pointer since they are explicit children of gProtoLayout and as
       
   208   * such GTK holds a strong reference to them. */
       
   209  static void
       
   210  moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
       
   211 @@ -385,8 +281,7 @@ ensure_combo_box_entry_widgets()
       
   212                           NULL);
       
   213  
       
   214      if (!gComboBoxEntryTextareaWidget) {
       
   215 -        ensure_entry_widget();
       
   216 -        gComboBoxEntryTextareaWidget = gEntryWidget;
       
   217 +        gComboBoxEntryTextareaWidget = GetWidget(MOZ_GTK_ENTRY);
       
   218      }
       
   219  
       
   220      if (gComboBoxEntryButtonWidget) {
       
   221 @@ -412,68 +307,19 @@ ensure_combo_box_entry_widgets()
       
   222          /* Shouldn't be reached with current internal gtk implementation;
       
   223           * we use a generic toggle button as last resort fallback to avoid
       
   224           * crashing. */
       
   225 -        ensure_toggle_button_widget();
       
   226 -        gComboBoxEntryButtonWidget = gToggleButtonWidget;
       
   227 +        gComboBoxEntryButtonWidget = GetWidget(MOZ_GTK_TOGGLE_BUTTON);
       
   228      }
       
   229  
       
   230      if (!gComboBoxEntryArrowWidget) {
       
   231          /* Shouldn't be reached with current internal gtk implementation;
       
   232           * we gButtonArrowWidget as last resort fallback to avoid
       
   233           * crashing. */
       
   234 -        ensure_button_arrow_widget();
       
   235 -        gComboBoxEntryArrowWidget = gButtonArrowWidget;
       
   236 +        gComboBoxEntryArrowWidget = GetWidget(MOZ_GTK_BUTTON_ARROW);
       
   237      }
       
   238  
       
   239      return MOZ_GTK_SUCCESS;
       
   240  }
       
   241  
       
   242 -
       
   243 -static gint
       
   244 -ensure_handlebox_widget()
       
   245 -{
       
   246 -    if (!gHandleBoxWidget) {
       
   247 -        gHandleBoxWidget = gtk_handle_box_new();
       
   248 -        setup_widget_prototype(gHandleBoxWidget);
       
   249 -    }
       
   250 -    return MOZ_GTK_SUCCESS;
       
   251 -}
       
   252 -
       
   253 -static gint
       
   254 -ensure_toolbar_widget()
       
   255 -{
       
   256 -    if (!gToolbarWidget) {
       
   257 -        ensure_handlebox_widget();
       
   258 -        gToolbarWidget = gtk_toolbar_new();
       
   259 -        gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
       
   260 -        gtk_widget_realize(gToolbarWidget);
       
   261 -    }
       
   262 -    return MOZ_GTK_SUCCESS;
       
   263 -}
       
   264 -
       
   265 -static gint
       
   266 -ensure_toolbar_separator_widget()
       
   267 -{
       
   268 -    if (!gToolbarSeparatorWidget) {
       
   269 -        ensure_toolbar_widget();
       
   270 -        gToolbarSeparatorWidget = GTK_WIDGET(gtk_separator_tool_item_new());
       
   271 -        setup_widget_prototype(gToolbarSeparatorWidget);
       
   272 -    }
       
   273 -    return MOZ_GTK_SUCCESS;
       
   274 -}
       
   275 -
       
   276 -static gint
       
   277 -ensure_tooltip_widget()
       
   278 -{
       
   279 -    if (!gTooltipWidget) {
       
   280 -        gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP);
       
   281 -        GtkStyleContext* style = gtk_widget_get_style_context(gTooltipWidget);
       
   282 -        gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP);
       
   283 -        gtk_widget_realize(gTooltipWidget);
       
   284 -        moz_gtk_set_widget_name(gTooltipWidget);
       
   285 -    }
       
   286 -    return MOZ_GTK_SUCCESS;
       
   287 -}
       
   288 -
       
   289  static gint
       
   290  ensure_tab_widget()
       
   291  {
       
   292 @@ -485,81 +331,11 @@ ensure_tab_widget()
       
   293  }
       
   294  
       
   295  static gint
       
   296 -ensure_progress_widget()
       
   297 -{
       
   298 -    if (!gProgressWidget) {
       
   299 -        gProgressWidget = gtk_progress_bar_new();
       
   300 -        setup_widget_prototype(gProgressWidget);
       
   301 -    }
       
   302 -    return MOZ_GTK_SUCCESS;
       
   303 -}
       
   304 -
       
   305 -static gint
       
   306 -ensure_frame_widget()
       
   307 -{
       
   308 -    if (!gFrameWidget) {
       
   309 -        gFrameWidget = gtk_frame_new(NULL);
       
   310 -        setup_widget_prototype(gFrameWidget);
       
   311 -    }
       
   312 -    return MOZ_GTK_SUCCESS;
       
   313 -}
       
   314 -
       
   315 -static gint
       
   316 -ensure_menu_bar_widget()
       
   317 -{
       
   318 -    if (!gMenuBarWidget) {
       
   319 -        gMenuBarWidget = gtk_menu_bar_new();
       
   320 -        setup_widget_prototype(gMenuBarWidget);
       
   321 -    }
       
   322 -    return MOZ_GTK_SUCCESS;
       
   323 -}
       
   324 -
       
   325 -static gint
       
   326 -ensure_menu_bar_item_widget()
       
   327 -{
       
   328 -    if (!gMenuBarItemWidget) {
       
   329 -        ensure_menu_bar_widget();
       
   330 -        gMenuBarItemWidget = gtk_menu_item_new();
       
   331 -        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget),
       
   332 -                              gMenuBarItemWidget);
       
   333 -        gtk_widget_realize(gMenuBarItemWidget);
       
   334 -    }
       
   335 -    return MOZ_GTK_SUCCESS;
       
   336 -}
       
   337 -
       
   338 -static gint
       
   339 -ensure_menu_popup_widget()
       
   340 -{
       
   341 -    if (!gMenuPopupWidget) {
       
   342 -        ensure_window_widget();
       
   343 -        gMenuPopupWidget = gtk_menu_new();
       
   344 -        gtk_menu_attach_to_widget(GTK_MENU(gMenuPopupWidget), gProtoWindow,
       
   345 -                                  NULL);
       
   346 -        gtk_widget_realize(gMenuPopupWidget);
       
   347 -    }
       
   348 -    return MOZ_GTK_SUCCESS;
       
   349 -}
       
   350 -
       
   351 -static gint
       
   352 -ensure_menu_item_widget()
       
   353 -{
       
   354 -    if (!gMenuItemWidget) {
       
   355 -        ensure_menu_popup_widget();
       
   356 -        gMenuItemWidget = gtk_menu_item_new_with_label("M");
       
   357 -        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
       
   358 -                              gMenuItemWidget);
       
   359 -        gtk_widget_realize(gMenuItemWidget);
       
   360 -    }
       
   361 -    return MOZ_GTK_SUCCESS;
       
   362 -}
       
   363 -
       
   364 -static gint
       
   365  ensure_image_menu_item_widget()
       
   366  {
       
   367      if (!gImageMenuItemWidget) {
       
   368 -        ensure_menu_popup_widget();
       
   369          gImageMenuItemWidget = gtk_image_menu_item_new();
       
   370 -        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
       
   371 +        gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
       
   372                                gImageMenuItemWidget);
       
   373          gtk_widget_realize(gImageMenuItemWidget);
       
   374      }
       
   375 @@ -567,25 +343,11 @@ ensure_image_menu_item_widget()
       
   376  }
       
   377  
       
   378  static gint
       
   379 -ensure_menu_separator_widget()
       
   380 -{
       
   381 -    if (!gMenuSeparatorWidget) {
       
   382 -        ensure_menu_popup_widget();
       
   383 -        gMenuSeparatorWidget = gtk_separator_menu_item_new();
       
   384 -        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
       
   385 -                              gMenuSeparatorWidget);
       
   386 -        gtk_widget_realize(gMenuSeparatorWidget);
       
   387 -    }
       
   388 -    return MOZ_GTK_SUCCESS;
       
   389 -}
       
   390 -
       
   391 -static gint
       
   392  ensure_check_menu_item_widget()
       
   393  {
       
   394      if (!gCheckMenuItemWidget) {
       
   395 -        ensure_menu_popup_widget();
       
   396 -        gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M");
       
   397 -        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
       
   398 +        gCheckMenuItemWidget = gtk_check_menu_item_new();
       
   399 +        gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
       
   400                                gCheckMenuItemWidget);
       
   401          gtk_widget_realize(gCheckMenuItemWidget);
       
   402      }
       
   403 @@ -646,37 +408,6 @@ ensure_tree_header_cell_widget()
       
   404      return MOZ_GTK_SUCCESS;
       
   405  }
       
   406  
       
   407 -static gint
       
   408 -ensure_expander_widget()
       
   409 -{
       
   410 -    if (!gExpanderWidget) {
       
   411 -        gExpanderWidget = gtk_expander_new("M");
       
   412 -        setup_widget_prototype(gExpanderWidget);
       
   413 -    }
       
   414 -    return MOZ_GTK_SUCCESS;
       
   415 -}
       
   416 -
       
   417 -static gint
       
   418 -ensure_scrolled_window_widget()
       
   419 -{
       
   420 -    if (!gScrolledWindowWidget) {
       
   421 -        gScrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL);
       
   422 -        setup_widget_prototype(gScrolledWindowWidget);
       
   423 -    }
       
   424 -    return MOZ_GTK_SUCCESS;
       
   425 -}
       
   426 -
       
   427 -static void
       
   428 -ensure_text_view_widget()
       
   429 -{
       
   430 -    if (gTextViewWidget)
       
   431 -        return;
       
   432 -
       
   433 -    gTextViewWidget = gtk_text_view_new();
       
   434 -    ensure_scrolled_window_widget();
       
   435 -    gtk_container_add(GTK_CONTAINER(gScrolledWindowWidget), gTextViewWidget);
       
   436 -}
       
   437 -
       
   438  gint
       
   439  moz_gtk_init()
       
   440  {
       
   441 @@ -729,26 +460,21 @@ moz_gtk_get_focus_outline_size(gint* foc
       
   442  {
       
   443      GtkBorder border;
       
   444      GtkBorder padding;
       
   445 -    GtkStyleContext *style;
       
   446 -
       
   447 -    ensure_entry_widget();
       
   448 -    style = gtk_widget_get_style_context(gEntryWidget);
       
   449 -
       
   450 +    GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_ENTRY);
       
   451      gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border);
       
   452      gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
       
   453      *focus_h_width = border.left + padding.left;
       
   454      *focus_v_width = border.top + padding.top;
       
   455 +    ReleaseStyleContext(style);
       
   456      return MOZ_GTK_SUCCESS;
       
   457  }
       
   458  
       
   459  gint
       
   460  moz_gtk_menuitem_get_horizontal_padding(gint* horizontal_padding)
       
   461  {
       
   462 -    ensure_menu_item_widget();
       
   463 -
       
   464 -    gtk_style_context_get_style(gtk_widget_get_style_context(gMenuItemWidget),
       
   465 -                                "horizontal-padding", horizontal_padding,
       
   466 -                                NULL);
       
   467 +    gtk_widget_style_get(GetWidget(MOZ_GTK_MENUITEM),
       
   468 +                         "horizontal-padding", horizontal_padding,
       
   469 +                         nullptr);
       
   470  
       
   471      return MOZ_GTK_SUCCESS;
       
   472  }
       
   473 @@ -771,10 +497,11 @@ moz_gtk_button_get_default_overflow(gint
       
   474  {
       
   475      GtkBorder* default_outside_border;
       
   476  
       
   477 -    ensure_button_widget();
       
   478 -    gtk_style_context_get_style(gtk_widget_get_style_context(gButtonWidget),
       
   479 +    GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON);
       
   480 +    gtk_style_context_get_style(style,
       
   481                                  "default-outside-border", &default_outside_border,
       
   482                                  NULL);
       
   483 +    ReleaseStyleContext(style);
       
   484  
       
   485      if (default_outside_border) {
       
   486          *border_top = default_outside_border->top;
       
   487 @@ -794,10 +521,11 @@ moz_gtk_button_get_default_border(gint*
       
   488  {
       
   489      GtkBorder* default_border;
       
   490  
       
   491 -    ensure_button_widget();
       
   492 -    gtk_style_context_get_style(gtk_widget_get_style_context(gButtonWidget),
       
   493 +    GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON);
       
   494 +    gtk_style_context_get_style(style,
       
   495                                  "default-border", &default_border,
       
   496                                  NULL);
       
   497 +    ReleaseStyleContext(style);
       
   498  
       
   499      if (default_border) {
       
   500          *border_top = default_border->top;
       
   501 @@ -831,17 +559,15 @@ static gint
       
   502  moz_gtk_window_paint(cairo_t *cr, GdkRectangle* rect,
       
   503                       GtkTextDirection direction)
       
   504  {
       
   505 -    GtkStyleContext* style;
       
   506 -
       
   507 -    ensure_window_widget();
       
   508 -    gtk_widget_set_direction(gProtoWindow, direction);
       
   509 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_WINDOW, direction);
       
   510  
       
   511 -    style = gtk_widget_get_style_context(gProtoWindow);	
       
   512      gtk_style_context_save(style);
       
   513      gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND);
       
   514      gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   515      gtk_style_context_restore(style);
       
   516  
       
   517 +    ReleaseStyleContext(style);
       
   518 +
       
   519      return MOZ_GTK_SUCCESS;
       
   520  }
       
   521  
       
   522 @@ -1118,6 +844,36 @@ moz_gtk_scrollbar_button_paint(cairo_t *
       
   523      return MOZ_GTK_SUCCESS;
       
   524  }
       
   525  
       
   526 +static void
       
   527 +moz_gtk_update_scrollbar_style(GtkStyleContext* style,
       
   528 +                               WidgetNodeType widget,
       
   529 +                               GtkTextDirection direction)
       
   530 +{
       
   531 +    if (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) {
       
   532 +        gtk_style_context_add_class(style, GTK_STYLE_CLASS_BOTTOM);
       
   533 +    } else {
       
   534 +        if (direction == GTK_TEXT_DIR_LTR) {
       
   535 +            gtk_style_context_add_class(style, GTK_STYLE_CLASS_RIGHT);
       
   536 +            gtk_style_context_remove_class(style, GTK_STYLE_CLASS_LEFT);
       
   537 +        } else {
       
   538 +            gtk_style_context_add_class(style, GTK_STYLE_CLASS_LEFT);
       
   539 +            gtk_style_context_remove_class(style, GTK_STYLE_CLASS_RIGHT);
       
   540 +        }
       
   541 +    }
       
   542 +}
       
   543 +
       
   544 +static void
       
   545 +moz_gtk_draw_styled_frame(GtkStyleContext* style, cairo_t *cr,
       
   546 +                          GdkRectangle* rect, bool drawFocus)
       
   547 +{
       
   548 +    gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   549 +    gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   550 +    if (drawFocus) {
       
   551 +        gtk_render_focus(style, cr,
       
   552 +                         rect->x, rect->y, rect->width, rect->height);
       
   553 +    }
       
   554 +}
       
   555 +
       
   556  static gint
       
   557  moz_gtk_scrollbar_trough_paint(WidgetNodeType widget,
       
   558                                 cairo_t *cr, GdkRectangle* rect,
       
   559 @@ -1126,26 +882,34 @@ moz_gtk_scrollbar_trough_paint(WidgetNod
       
   560                                 GtkTextDirection direction)
       
   561  {
       
   562      if (flags & MOZ_GTK_TRACK_OPAQUE) {
       
   563 -        GtkStyleContext* style =
       
   564 -            gtk_widget_get_style_context(GTK_WIDGET(gProtoWindow));
       
   565 -        gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   566 +        GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_WINDOW, direction);
       
   567 +        gtk_render_background(style, cr,
       
   568 +                              rect->x, rect->y, rect->width, rect->height);
       
   569 +        ReleaseStyleContext(style);
       
   570      }
       
   571  
       
   572 -    GtkStyleContext* style =
       
   573 -        ClaimStyleContext(widget == MOZ_GTK_SCROLLBAR_HORIZONTAL ?
       
   574 -                          MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL :
       
   575 -                          MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL,
       
   576 -                          direction);
       
   577 -    // TODO - integate with ClaimStyleContext()?
       
   578 -    gtk_style_context_set_direction(style, direction);
       
   579 +    bool isHorizontal = (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL);
       
   580 +    GtkStyleContext* style;
       
   581  
       
   582 -    gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   583 -    gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   584 +    // Draw all child CSS Nodes for Gtk >= 3.20
       
   585 +    if (gtk_check_version(3, 20, 0) == nullptr) {
       
   586 +        style = ClaimStyleContext(widget, direction);
       
   587 +        moz_gtk_update_scrollbar_style(style, widget, direction);
       
   588 +        moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
       
   589 +        ReleaseStyleContext(style);
       
   590  
       
   591 -    if (state->focused) {
       
   592 -        gtk_render_focus(style, cr,
       
   593 -                         rect->x, rect->y, rect->width, rect->height);
       
   594 +        style = ClaimStyleContext(isHorizontal ?
       
   595 +                                  MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL :
       
   596 +                                  MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL,
       
   597 +                                  direction);
       
   598 +        moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
       
   599 +        ReleaseStyleContext(style);
       
   600      }
       
   601 +    style = ClaimStyleContext(isHorizontal ?
       
   602 +                              MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL :
       
   603 +                              MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL,
       
   604 +                              direction);
       
   605 +    moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
       
   606      ReleaseStyleContext(style);
       
   607  
       
   608      return MOZ_GTK_SUCCESS;
       
   609 @@ -1160,12 +924,7 @@ moz_gtk_scrollbar_thumb_paint(WidgetNode
       
   610      GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
       
   611      GtkBorder margin;
       
   612  
       
   613 -    GtkStyleContext* style = ClaimStyleContext(widget, direction);
       
   614 -
       
   615 -    // TODO - integate those with ClaimStyleContext()?
       
   616 -    gtk_style_context_set_state(style, state_flags);
       
   617 -    gtk_style_context_set_direction(style, direction);
       
   618 -
       
   619 +    GtkStyleContext* style = ClaimStyleContext(widget, direction, state_flags);
       
   620      gtk_style_context_get_margin (style, state_flags, &margin);
       
   621  
       
   622      gtk_render_slider(style, cr,
       
   623 @@ -1185,17 +944,10 @@ static gint
       
   624  moz_gtk_spin_paint(cairo_t *cr, GdkRectangle* rect,
       
   625                     GtkTextDirection direction)
       
   626  {
       
   627 -    GtkStyleContext* style;
       
   628 -
       
   629 -    ensure_spin_widget();
       
   630 -    gtk_widget_set_direction(gSpinWidget, direction);
       
   631 -    style = gtk_widget_get_style_context(gSpinWidget);
       
   632 -    gtk_style_context_save(style);
       
   633 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_SPINBUTTON);
       
   634 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SPINBUTTON, direction);
       
   635      gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   636      gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   637 -    gtk_style_context_restore(style);
       
   638 -
       
   639 +    ReleaseStyleContext(style);
       
   640      return MOZ_GTK_SUCCESS;
       
   641  }
       
   642  
       
   643 @@ -1204,21 +956,14 @@ moz_gtk_spin_updown_paint(cairo_t *cr, G
       
   644                            gboolean isDown, GtkWidgetState* state,
       
   645                            GtkTextDirection direction)
       
   646  {
       
   647 -    GdkRectangle arrow_rect;
       
   648 -    GtkStyleContext* style;
       
   649 -
       
   650 -    ensure_spin_widget();
       
   651 -    style = gtk_widget_get_style_context(gSpinWidget);
       
   652 -    gtk_style_context_save(style);
       
   653 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_SPINBUTTON);
       
   654 -    gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
       
   655 -    gtk_widget_set_direction(gSpinWidget, direction);
       
   656 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SPINBUTTON, direction,
       
   657 +                                 GetStateFlagsFromGtkWidgetState(state));
       
   658  
       
   659      gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   660      gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   661  
       
   662 -
       
   663      /* hard code these values */
       
   664 +    GdkRectangle arrow_rect;
       
   665      arrow_rect.width = 6;
       
   666      arrow_rect.height = 6;
       
   667      arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
       
   668 @@ -1229,7 +974,8 @@ moz_gtk_spin_updown_paint(cairo_t *cr, G
       
   669                      isDown ? ARROW_DOWN : ARROW_UP,
       
   670                      arrow_rect.x, arrow_rect.y,
       
   671                      arrow_rect.width);
       
   672 -    gtk_style_context_restore(style);
       
   673 +
       
   674 +    ReleaseStyleContext(style);
       
   675      return MOZ_GTK_SUCCESS;
       
   676  }
       
   677  
       
   678 @@ -1295,8 +1041,8 @@ moz_gtk_scale_thumb_paint(cairo_t *cr, G
       
   679    gtk_widget_set_direction(widget, direction);
       
   680  
       
   681    style = gtk_widget_get_style_context(widget);
       
   682 -  gtk_style_context_add_class(style, GTK_STYLE_CLASS_SLIDER);
       
   683    gtk_style_context_save(style);
       
   684 +  gtk_style_context_add_class(style, GTK_STYLE_CLASS_SLIDER);
       
   685    gtk_style_context_set_state(style, state_flags);
       
   686    /* determine the thumb size, and position the thumb in the center in the opposite axis 
       
   687    */
       
   688 @@ -1321,20 +1067,12 @@ moz_gtk_gripper_paint(cairo_t *cr, GdkRe
       
   689                        GtkWidgetState* state,
       
   690                        GtkTextDirection direction)
       
   691  {
       
   692 -    GtkStyleContext* style;
       
   693 -
       
   694 -    ensure_handlebox_widget();
       
   695 -    gtk_widget_set_direction(gHandleBoxWidget, direction);
       
   696 -
       
   697 -    style = gtk_widget_get_style_context(gHandleBoxWidget);
       
   698 -    gtk_style_context_save(style);
       
   699 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP);
       
   700 -    gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
       
   701 -
       
   702 +    GtkStyleContext* style =
       
   703 +            ClaimStyleContext(MOZ_GTK_GRIPPER, direction,
       
   704 +                              GetStateFlagsFromGtkWidgetState(state));
       
   705      gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   706      gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   707 -    gtk_style_context_restore(style);
       
   708 -
       
   709 +    ReleaseStyleContext(style);
       
   710      return MOZ_GTK_SUCCESS;
       
   711  }
       
   712  
       
   713 @@ -1435,6 +1173,38 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRect
       
   714      return MOZ_GTK_SUCCESS;
       
   715  }
       
   716  
       
   717 +static gint
       
   718 +moz_gtk_text_view_paint(cairo_t *cr, GdkRectangle* rect,
       
   719 +                        GtkWidgetState* state,
       
   720 +                        GtkTextDirection direction)
       
   721 +{
       
   722 +    GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
       
   723 +
       
   724 +    GtkStyleContext* style_frame =
       
   725 +        ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction, state_flags);
       
   726 +    gtk_render_frame(style_frame, cr, rect->x, rect->y, rect->width, rect->height);
       
   727 +
       
   728 +    GtkBorder border, padding;
       
   729 +    gtk_style_context_get_border(style_frame, state_flags, &border);
       
   730 +    gtk_style_context_get_padding(style_frame, state_flags, &padding);
       
   731 +    ReleaseStyleContext(style_frame);
       
   732 +
       
   733 +    GtkStyleContext* style =
       
   734 +        ClaimStyleContext(MOZ_GTK_TEXT_VIEW, direction, state_flags);
       
   735 +
       
   736 +    gint xthickness = border.left + padding.left;
       
   737 +    gint ythickness = border.top + padding.top;
       
   738 +
       
   739 +    gtk_render_background(style, cr,
       
   740 +                          rect->x + xthickness, rect->y + ythickness,
       
   741 +                          rect->width - 2 * xthickness,
       
   742 +                          rect->height - 2 * ythickness);
       
   743 +
       
   744 +    ReleaseStyleContext(style);
       
   745 +
       
   746 +    return MOZ_GTK_SUCCESS;
       
   747 +}
       
   748 +
       
   749  static gint 
       
   750  moz_gtk_treeview_paint(cairo_t *cr, GdkRectangle* rect,
       
   751                         GtkWidgetState* state,
       
   752 @@ -1447,18 +1217,13 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkR
       
   753      GtkBorder border;
       
   754  
       
   755      ensure_tree_view_widget();
       
   756 -    ensure_scrolled_window_widget();
       
   757 -
       
   758      gtk_widget_set_direction(gTreeViewWidget, direction);
       
   759 -    gtk_widget_set_direction(gScrolledWindowWidget, direction);
       
   760  
       
   761      /* only handle disabled and normal states, otherwise the whole background
       
   762       * area will be painted differently with other states */
       
   763      state_flags = state->disabled ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
       
   764  
       
   765 -    style = gtk_widget_get_style_context(gScrolledWindowWidget);
       
   766 -    gtk_style_context_save(style);
       
   767 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME);    
       
   768 +    style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction);
       
   769      gtk_style_context_get_border(style, state_flags, &border);
       
   770      xthickness = border.left;
       
   771      ythickness = border.top;    
       
   772 @@ -1473,7 +1238,7 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkR
       
   773                            rect->height - 2 * ythickness);
       
   774      gtk_render_frame(style, cr, 
       
   775                       rect->x, rect->y, rect->width, rect->height); 
       
   776 -    gtk_style_context_restore(style);
       
   777 +    ReleaseStyleContext(style);
       
   778      gtk_style_context_restore(style_tree);
       
   779      return MOZ_GTK_SUCCESS;
       
   780  }
       
   781 @@ -1648,20 +1413,9 @@ moz_gtk_arrow_paint(cairo_t *cr, GdkRect
       
   782                      GtkWidgetState* state,
       
   783                      GtkArrowType arrow_type, GtkTextDirection direction)
       
   784  {
       
   785 -    GtkStyleContext* style;
       
   786 -    GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
       
   787      GdkRectangle arrow_rect;
       
   788      gdouble arrow_angle;
       
   789  
       
   790 -    ensure_button_arrow_widget();
       
   791 -    style = gtk_widget_get_style_context(gButtonArrowWidget);
       
   792 -    gtk_style_context_save(style);
       
   793 -    gtk_style_context_set_state(style, state_flags);
       
   794 -    gtk_widget_set_direction(gButtonArrowWidget, direction);
       
   795 -
       
   796 -    calculate_arrow_rect(gButtonArrowWidget, rect, &arrow_rect,
       
   797 -                         direction);
       
   798 -
       
   799      if (direction == GTK_TEXT_DIR_RTL) {
       
   800          arrow_type = (arrow_type == GTK_ARROW_LEFT) ?
       
   801                           GTK_ARROW_RIGHT : GTK_ARROW_LEFT;
       
   802 @@ -1680,10 +1434,17 @@ moz_gtk_arrow_paint(cairo_t *cr, GdkRect
       
   803          arrow_angle = ARROW_UP;
       
   804          break;
       
   805      }
       
   806 -    if (arrow_type != GTK_ARROW_NONE)
       
   807 -        gtk_render_arrow(style, cr, arrow_angle,
       
   808 -                         arrow_rect.x, arrow_rect.y, arrow_rect.width);                    
       
   809 -    gtk_style_context_restore(style);
       
   810 +    if (arrow_type == GTK_ARROW_NONE)
       
   811 +        return MOZ_GTK_SUCCESS;
       
   812 +
       
   813 +    calculate_arrow_rect(GetWidget(MOZ_GTK_BUTTON_ARROW), rect, &arrow_rect,
       
   814 +                         direction);
       
   815 +    GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
       
   816 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_BUTTON_ARROW,
       
   817 +                                               direction, state_flags);
       
   818 +    gtk_render_arrow(style, cr, arrow_angle,
       
   819 +                     arrow_rect.x, arrow_rect.y, arrow_rect.width);
       
   820 +    ReleaseStyleContext(style);
       
   821      return MOZ_GTK_SUCCESS;
       
   822  }
       
   823  
       
   824 @@ -1776,19 +1537,10 @@ static gint
       
   825  moz_gtk_toolbar_paint(cairo_t *cr, GdkRectangle* rect,
       
   826                        GtkTextDirection direction)
       
   827  {
       
   828 -    GtkStyleContext* style;
       
   829 -
       
   830 -    ensure_toolbar_widget();
       
   831 -    gtk_widget_set_direction(gToolbarWidget, direction);
       
   832 -
       
   833 -    style = gtk_widget_get_style_context(gToolbarWidget);
       
   834 -    gtk_style_context_save(style);
       
   835 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLBAR);
       
   836 -
       
   837 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR, direction);
       
   838      gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   839      gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   840 -    gtk_style_context_restore(style);
       
   841 -
       
   842 +    ReleaseStyleContext(style);
       
   843      return MOZ_GTK_SUCCESS;
       
   844  }
       
   845  
       
   846 @@ -1798,7 +1550,6 @@ static gint
       
   847  moz_gtk_toolbar_separator_paint(cairo_t *cr, GdkRectangle* rect,
       
   848                                  GtkTextDirection direction)
       
   849  {
       
   850 -    GtkStyleContext* style;
       
   851      gint     separator_width;
       
   852      gint     paint_width;
       
   853      gboolean wide_separators;
       
   854 @@ -1807,16 +1558,14 @@ moz_gtk_toolbar_separator_paint(cairo_t
       
   855      const double start_fraction = 0.2;
       
   856      const double end_fraction = 0.8;
       
   857  
       
   858 -    ensure_toolbar_separator_widget();
       
   859 -    gtk_widget_set_direction(gToolbarSeparatorWidget, direction);
       
   860 -
       
   861 -    style = gtk_widget_get_style_context(gToolbarSeparatorWidget);
       
   862 -
       
   863 -    gtk_style_context_get_style(gtk_widget_get_style_context(gToolbarWidget),
       
   864 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR);
       
   865 +    gtk_style_context_get_style(style,
       
   866                                  "wide-separators", &wide_separators,
       
   867                                  "separator-width", &separator_width,
       
   868                                  NULL);
       
   869 +    ReleaseStyleContext(style);
       
   870  
       
   871 +    style = ClaimStyleContext(MOZ_GTK_TOOLBAR_SEPARATOR, direction);
       
   872      if (wide_separators) {
       
   873          if (separator_width > rect->width)
       
   874              separator_width = rect->width;
       
   875 @@ -1840,7 +1589,7 @@ moz_gtk_toolbar_separator_paint(cairo_t
       
   876                          rect->x + (rect->width - paint_width) / 2,
       
   877                          rect->y + rect->height * end_fraction);
       
   878      }
       
   879 -
       
   880 +    ReleaseStyleContext(style);
       
   881      return MOZ_GTK_SUCCESS;
       
   882  }
       
   883  
       
   884 @@ -1848,14 +1597,10 @@ static gint
       
   885  moz_gtk_tooltip_paint(cairo_t *cr, GdkRectangle* rect,
       
   886                        GtkTextDirection direction)
       
   887  {
       
   888 -    GtkStyleContext* style;
       
   889 -
       
   890 -    ensure_tooltip_widget();
       
   891 -    gtk_widget_set_direction(gTooltipWidget, direction);
       
   892 -
       
   893 -    style = gtk_widget_get_style_context(gTooltipWidget);
       
   894 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLTIP, direction);
       
   895      gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   896      gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   897 +    ReleaseStyleContext(style);
       
   898      return MOZ_GTK_SUCCESS;
       
   899  }
       
   900  
       
   901 @@ -1870,14 +1615,11 @@ moz_gtk_resizer_paint(cairo_t *cr, GdkRe
       
   902      // GTK_STYLE_CLASS_VIEW to match the background with textarea elements.
       
   903      // The resizer is drawn with shaded variants of the background color, and
       
   904      // so a transparent background would lead to a transparent resizer.
       
   905 -    ensure_text_view_widget();
       
   906 -    gtk_widget_set_direction(gTextViewWidget, GTK_TEXT_DIR_LTR);
       
   907 -
       
   908 -    style = gtk_widget_get_style_context(gTextViewWidget);
       
   909 -    gtk_style_context_save(style);
       
   910 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_VIEW);
       
   911 +    style = ClaimStyleContext(MOZ_GTK_TEXT_VIEW, GTK_TEXT_DIR_LTR,
       
   912 +                              GetStateFlagsFromGtkWidgetState(state));
       
   913 +    // TODO - we need to save/restore style when gtk 3.20 CSS node path
       
   914 +    // is used
       
   915      gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP);
       
   916 -    gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
       
   917  
       
   918      // Workaround unico not respecting the text direction for resizers.
       
   919      // See bug 1174248.
       
   920 @@ -1891,7 +1633,7 @@ moz_gtk_resizer_paint(cairo_t *cr, GdkRe
       
   921  
       
   922      gtk_render_handle(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   923      cairo_restore(cr);
       
   924 -    gtk_style_context_restore(style);
       
   925 +    ReleaseStyleContext(style);
       
   926  
       
   927      return MOZ_GTK_SUCCESS;
       
   928  }
       
   929 @@ -1900,16 +1642,9 @@ static gint
       
   930  moz_gtk_frame_paint(cairo_t *cr, GdkRectangle* rect,
       
   931                      GtkTextDirection direction)
       
   932  {
       
   933 -    GtkStyleContext* style;
       
   934 -
       
   935 -    ensure_frame_widget();
       
   936 -    gtk_widget_set_direction(gFrameWidget, direction);
       
   937 -    style = gtk_widget_get_style_context(gFrameWidget);
       
   938 -    gtk_style_context_save(style);
       
   939 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME);
       
   940 -
       
   941 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_FRAME, direction);
       
   942      gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   943 -    gtk_style_context_restore(style);
       
   944 +    ReleaseStyleContext(style);
       
   945      return MOZ_GTK_SUCCESS;
       
   946  }
       
   947  
       
   948 @@ -1917,18 +1652,11 @@ static gint
       
   949  moz_gtk_progressbar_paint(cairo_t *cr, GdkRectangle* rect,
       
   950                            GtkTextDirection direction)
       
   951  {
       
   952 -    GtkStyleContext* style;
       
   953 -
       
   954 -    ensure_progress_widget();
       
   955 -    gtk_widget_set_direction(gProgressWidget, direction);
       
   956 -
       
   957 -    style = gtk_widget_get_style_context(gProgressWidget);
       
   958 -    gtk_style_context_save(style);
       
   959 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_TROUGH);
       
   960 -    
       
   961 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_PROGRESS_TROUGH,
       
   962 +                                               direction);
       
   963      gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   964      gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   965 -    gtk_style_context_restore(style);
       
   966 +    ReleaseStyleContext(style);
       
   967  
       
   968      return MOZ_GTK_SUCCESS;
       
   969  }
       
   970 @@ -1940,13 +1668,15 @@ moz_gtk_progress_chunk_paint(cairo_t *cr
       
   971  {
       
   972      GtkStyleContext* style;
       
   973  
       
   974 -    ensure_progress_widget();
       
   975 -    gtk_widget_set_direction(gProgressWidget, direction);
       
   976 -
       
   977 -    style = gtk_widget_get_style_context(gProgressWidget);
       
   978 -    gtk_style_context_save(style);
       
   979 -    gtk_style_context_remove_class(style, GTK_STYLE_CLASS_TROUGH);
       
   980 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_PROGRESSBAR);
       
   981 +    if (gtk_check_version(3, 20, 0) != nullptr) {
       
   982 +      /* Ask for MOZ_GTK_PROGRESS_TROUGH instead of MOZ_GTK_PROGRESSBAR
       
   983 +       * because ClaimStyleContext() saves/restores that style */
       
   984 +      style = ClaimStyleContext(MOZ_GTK_PROGRESS_TROUGH, direction);
       
   985 +      gtk_style_context_remove_class(style, GTK_STYLE_CLASS_TROUGH);
       
   986 +      gtk_style_context_add_class(style, GTK_STYLE_CLASS_PROGRESSBAR);
       
   987 +    } else {
       
   988 +      style = ClaimStyleContext(MOZ_GTK_PROGRESS_CHUNK, direction);
       
   989 +    }
       
   990  
       
   991      if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE ||
       
   992          widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) {
       
   993 @@ -1990,7 +1720,7 @@ moz_gtk_progress_chunk_paint(cairo_t *cr
       
   994      } else {
       
   995        gtk_render_activity(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   996      }
       
   997 -    gtk_style_context_restore(style);
       
   998 +    ReleaseStyleContext(style);
       
   999  
       
  1000      return MOZ_GTK_SUCCESS;
       
  1001  }
       
  1002 @@ -2324,10 +2054,10 @@ moz_gtk_menu_bar_paint(cairo_t *cr, GdkR
       
  1003  {
       
  1004      GtkStyleContext* style;
       
  1005  
       
  1006 -    ensure_menu_bar_widget();
       
  1007 -    gtk_widget_set_direction(gMenuBarWidget, direction);
       
  1008 +    GtkWidget* widget = GetWidget(MOZ_GTK_MENUBAR);
       
  1009 +    gtk_widget_set_direction(widget, direction);
       
  1010  
       
  1011 -    style = gtk_widget_get_style_context(gMenuBarWidget);
       
  1012 +    style = gtk_widget_get_style_context(widget);
       
  1013      gtk_style_context_save(style);
       
  1014      gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
       
  1015      gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
  1016 @@ -2343,14 +2073,14 @@ moz_gtk_menu_popup_paint(cairo_t *cr, Gd
       
  1017  {
       
  1018      GtkStyleContext* style;
       
  1019  
       
  1020 -    ensure_menu_popup_widget();
       
  1021 -    gtk_widget_set_direction(gMenuPopupWidget, direction);
       
  1022 +    GtkWidget* widget = GetWidget(MOZ_GTK_MENUPOPUP);
       
  1023 +    gtk_widget_set_direction(widget, direction);
       
  1024  
       
  1025      // Draw a backing toplevel. This fixes themes that don't provide a menu
       
  1026      // background, and depend on the GtkMenu's implementation window to provide it.
       
  1027      moz_gtk_window_paint(cr, rect, direction);
       
  1028  
       
  1029 -    style = gtk_widget_get_style_context(gMenuPopupWidget);
       
  1030 +    style = gtk_widget_get_style_context(widget);
       
  1031      gtk_style_context_save(style);
       
  1032      gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENU);
       
  1033  
       
  1034 @@ -2373,12 +2103,10 @@ moz_gtk_menu_separator_paint(cairo_t *cr
       
  1035      gint x, y, w;
       
  1036      GtkBorder padding;
       
  1037  
       
  1038 -    ensure_menu_separator_widget();
       
  1039 -    gtk_widget_set_direction(gMenuSeparatorWidget, direction);
       
  1040 -
       
  1041 -    border_width = gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget));
       
  1042 -
       
  1043 -    style = gtk_widget_get_style_context(gMenuSeparatorWidget);
       
  1044 +    border_width =
       
  1045 +        gtk_container_get_border_width(GTK_CONTAINER(
       
  1046 +                                       GetWidget(MOZ_GTK_MENUSEPARATOR)));
       
  1047 +    style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR, direction);
       
  1048      gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
       
  1049  
       
  1050      x = rect->x + border_width;
       
  1051 @@ -2408,42 +2136,36 @@ moz_gtk_menu_separator_paint(cairo_t *cr
       
  1052      }
       
  1053  
       
  1054      gtk_style_context_restore(style);
       
  1055 +    ReleaseStyleContext(style);
       
  1056  
       
  1057      return MOZ_GTK_SUCCESS;
       
  1058  }
       
  1059  
       
  1060  // See gtk_menu_item_draw() for reference.
       
  1061  static gint
       
  1062 -moz_gtk_menu_item_paint(cairo_t *cr, GdkRectangle* rect,
       
  1063 -                        GtkWidgetState* state,
       
  1064 -                        gint flags, GtkTextDirection direction)
       
  1065 +moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect,
       
  1066 +                        GtkWidgetState* state, GtkTextDirection direction)
       
  1067  {
       
  1068 -    GtkStyleContext* style;
       
  1069 -    GtkWidget* item_widget;
       
  1070 -    guint border_width;
       
  1071      gint x, y, w, h;
       
  1072  
       
  1073      if (state->inHover && !state->disabled) {   
       
  1074 -        if (flags & MOZ_TOPLEVEL_MENU_ITEM) {
       
  1075 -            ensure_menu_bar_item_widget();
       
  1076 -            item_widget = gMenuBarItemWidget;
       
  1077 -        } else {
       
  1078 -            ensure_menu_item_widget();
       
  1079 -            item_widget = gMenuItemWidget;
       
  1080 -        }
       
  1081 -        style = gtk_widget_get_style_context(item_widget);
       
  1082 -        gtk_style_context_save(style);
       
  1083 +        guint border_width =
       
  1084 +            gtk_container_get_border_width(GTK_CONTAINER(GetWidget(widget)));
       
  1085 +        GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
       
  1086 +        GtkStyleContext* style =
       
  1087 +            ClaimStyleContext(widget, direction, state_flags);
       
  1088  
       
  1089 -        if (flags & MOZ_TOPLEVEL_MENU_ITEM) {
       
  1090 -            gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
       
  1091 +        bool pre_3_6 = gtk_check_version(3, 6, 0) != nullptr;
       
  1092 +        if (pre_3_6) {
       
  1093 +            // GTK+ 3.4 saves the style context and adds the menubar class to
       
  1094 +            // menubar children, but does each of these only when drawing, not
       
  1095 +            // during layout.
       
  1096 +            gtk_style_context_save(style);
       
  1097 +            if (widget == MOZ_GTK_MENUBARITEM) {
       
  1098 +                gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
       
  1099 +            }
       
  1100          }
       
  1101  
       
  1102 -        gtk_widget_set_direction(item_widget, direction);
       
  1103 -        gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUITEM);
       
  1104 -        gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
       
  1105 -
       
  1106 -        border_width = gtk_container_get_border_width(GTK_CONTAINER(item_widget));
       
  1107 -
       
  1108          x = rect->x + border_width;
       
  1109          y = rect->y + border_width;
       
  1110          w = rect->width - border_width * 2;
       
  1111 @@ -2451,7 +2173,11 @@ moz_gtk_menu_item_paint(cairo_t *cr, Gdk
       
  1112  
       
  1113          gtk_render_background(style, cr, x, y, w, h);
       
  1114          gtk_render_frame(style, cr, x, y, w, h);
       
  1115 -        gtk_style_context_restore(style);
       
  1116 +
       
  1117 +        if (pre_3_6) {
       
  1118 +            gtk_style_context_restore(style);
       
  1119 +        }
       
  1120 +        ReleaseStyleContext(style);
       
  1121      }
       
  1122  
       
  1123      return MOZ_GTK_SUCCESS;
       
  1124 @@ -2462,21 +2188,13 @@ moz_gtk_menu_arrow_paint(cairo_t *cr, Gd
       
  1125                           GtkWidgetState* state,
       
  1126                           GtkTextDirection direction)
       
  1127  {
       
  1128 -    GtkStyleContext* style;
       
  1129      GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
       
  1130 -
       
  1131 -    ensure_menu_item_widget();
       
  1132 -    gtk_widget_set_direction(gMenuItemWidget, direction);
       
  1133 -
       
  1134 -    style = gtk_widget_get_style_context(gMenuItemWidget);
       
  1135 -    gtk_style_context_save(style);
       
  1136 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUITEM);
       
  1137 -    gtk_style_context_set_state(style, state_flags);
       
  1138 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_MENUITEM,
       
  1139 +                                               direction, state_flags);
       
  1140      gtk_render_arrow(style, cr,
       
  1141                      (direction == GTK_TEXT_DIR_LTR) ? ARROW_RIGHT : ARROW_LEFT,
       
  1142                      rect->x, rect->y, rect->width);
       
  1143 -    gtk_style_context_restore(style);
       
  1144 -
       
  1145 +    ReleaseStyleContext(style);
       
  1146      return MOZ_GTK_SUCCESS;
       
  1147  }
       
  1148  
       
  1149 @@ -2494,7 +2212,7 @@ moz_gtk_check_menu_item_paint(cairo_t *c
       
  1150      gint indicator_size, horizontal_padding;
       
  1151      gint x, y;
       
  1152  
       
  1153 -    moz_gtk_menu_item_paint(cr, rect, state, FALSE, direction);
       
  1154 +    moz_gtk_menu_item_paint(MOZ_GTK_MENUITEM, cr, rect, state, direction);
       
  1155  
       
  1156      ensure_check_menu_item_widget();
       
  1157      gtk_widget_set_direction(gCheckMenuItemWidget, direction);
       
  1158 @@ -2545,21 +2263,13 @@ static gint
       
  1159  moz_gtk_info_bar_paint(cairo_t *cr, GdkRectangle* rect,
       
  1160                         GtkWidgetState* state)
       
  1161  {
       
  1162 -    GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
       
  1163 -    GtkStyleContext *style;
       
  1164 -    ensure_info_bar();
       
  1165 -
       
  1166 -    style = gtk_widget_get_style_context(gInfoBar);
       
  1167 -    gtk_style_context_save(style);
       
  1168 -
       
  1169 -    gtk_style_context_set_state(style, state_flags);
       
  1170 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_INFO);
       
  1171 -
       
  1172 +    GtkStyleContext *style =
       
  1173 +        ClaimStyleContext(MOZ_GTK_INFO_BAR, GTK_TEXT_DIR_LTR,
       
  1174 +                          GetStateFlagsFromGtkWidgetState(state));
       
  1175      gtk_render_background(style, cr, rect->x, rect->y, rect->width,
       
  1176                            rect->height);
       
  1177      gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
  1178 -
       
  1179 -    gtk_style_context_restore(style);
       
  1180 +    ReleaseStyleContext(style);
       
  1181  
       
  1182      return MOZ_GTK_SUCCESS;
       
  1183  }
       
  1184 @@ -2605,18 +2315,18 @@ moz_gtk_get_widget_border(WidgetNodeType
       
  1185      case MOZ_GTK_BUTTON:
       
  1186      case MOZ_GTK_TOOLBAR_BUTTON:
       
  1187          {
       
  1188 -            ensure_button_widget();
       
  1189 -            style = gtk_widget_get_style_context(gButtonWidget);
       
  1190 +            style = ClaimStyleContext(MOZ_GTK_BUTTON);
       
  1191  
       
  1192 -            *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(gButtonWidget));
       
  1193 +            *left = *top = *right = *bottom =
       
  1194 +                gtk_container_get_border_width(GTK_CONTAINER(GetWidget(MOZ_GTK_BUTTON)));
       
  1195  
       
  1196              if (widget == MOZ_GTK_TOOLBAR_BUTTON) {
       
  1197                  gtk_style_context_save(style);
       
  1198                  gtk_style_context_add_class(style, "image-button");
       
  1199              }
       
  1200 -              
       
  1201 +
       
  1202              moz_gtk_add_style_padding(style, left, top, right, bottom);
       
  1203 -                
       
  1204 +
       
  1205              if (widget == MOZ_GTK_TOOLBAR_BUTTON)
       
  1206                  gtk_style_context_restore(style);
       
  1207  
       
  1208 @@ -2624,12 +2334,13 @@ moz_gtk_get_widget_border(WidgetNodeType
       
  1209              // -moz-focus-inner border (Bug 1228281).
       
  1210              *left -= 1; *top -= 1; *right -= 1; *bottom -= 1;
       
  1211              moz_gtk_add_style_border(style, left, top, right, bottom);
       
  1212 +
       
  1213 +            ReleaseStyleContext(style);
       
  1214              return MOZ_GTK_SUCCESS;
       
  1215          }
       
  1216      case MOZ_GTK_ENTRY:
       
  1217          {
       
  1218 -            ensure_entry_widget();
       
  1219 -            style = gtk_widget_get_style_context(gEntryWidget);
       
  1220 +            style = ClaimStyleContext(MOZ_GTK_ENTRY);
       
  1221  
       
  1222              // XXX: Subtract 1 pixel from the padding to account for the default
       
  1223              // padding in forms.css. See bug 1187385.
       
  1224 @@ -2637,16 +2348,15 @@ moz_gtk_get_widget_border(WidgetNodeType
       
  1225              moz_gtk_add_style_padding(style, left, top, right, bottom);
       
  1226              moz_gtk_add_style_border(style, left, top, right, bottom);
       
  1227  
       
  1228 +            ReleaseStyleContext(style);
       
  1229              return MOZ_GTK_SUCCESS;
       
  1230          }
       
  1231 +    case MOZ_GTK_TEXT_VIEW:
       
  1232      case MOZ_GTK_TREEVIEW:
       
  1233          {
       
  1234 -            ensure_scrolled_window_widget();
       
  1235 -            style = gtk_widget_get_style_context(gScrolledWindowWidget);
       
  1236 -            gtk_style_context_save(style);
       
  1237 -            gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME);
       
  1238 +            style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW);
       
  1239              moz_gtk_add_style_border(style, left, top, right, bottom);
       
  1240 -            gtk_style_context_restore(style);
       
  1241 +            ReleaseStyleContext(style);
       
  1242              return MOZ_GTK_SUCCESS;
       
  1243          }
       
  1244      case MOZ_GTK_TREE_HEADER_CELL:
       
  1245 @@ -2726,14 +2436,12 @@ moz_gtk_get_widget_border(WidgetNodeType
       
  1246          w = gTabWidget;
       
  1247          break;
       
  1248      case MOZ_GTK_PROGRESSBAR:
       
  1249 -        ensure_progress_widget();
       
  1250 -        w = gProgressWidget;
       
  1251 +        w = GetWidget(MOZ_GTK_PROGRESSBAR);
       
  1252          break;
       
  1253      case MOZ_GTK_SPINBUTTON_ENTRY:
       
  1254      case MOZ_GTK_SPINBUTTON_UP:
       
  1255      case MOZ_GTK_SPINBUTTON_DOWN:
       
  1256 -        ensure_spin_widget();
       
  1257 -        w = gSpinWidget;
       
  1258 +        w = GetWidget(MOZ_GTK_SPINBUTTON);
       
  1259          break;
       
  1260      case MOZ_GTK_SCALE_HORIZONTAL:
       
  1261          ensure_scale_widget();
       
  1262 @@ -2744,8 +2452,7 @@ moz_gtk_get_widget_border(WidgetNodeType
       
  1263          w = gVScaleWidget;
       
  1264          break;
       
  1265      case MOZ_GTK_FRAME:
       
  1266 -        ensure_frame_widget();
       
  1267 -        w = gFrameWidget;
       
  1268 +        w = GetWidget(MOZ_GTK_FRAME);
       
  1269          break;
       
  1270      case MOZ_GTK_CHECKBUTTON_CONTAINER:
       
  1271      case MOZ_GTK_RADIOBUTTON_CONTAINER:
       
  1272 @@ -2761,19 +2468,17 @@ moz_gtk_get_widget_border(WidgetNodeType
       
  1273              return MOZ_GTK_SUCCESS;
       
  1274          }
       
  1275      case MOZ_GTK_MENUPOPUP:
       
  1276 -        ensure_menu_popup_widget();
       
  1277 -        w = gMenuPopupWidget;
       
  1278 +        w = GetWidget(MOZ_GTK_MENUPOPUP);
       
  1279          break;
       
  1280 +    case MOZ_GTK_MENUBARITEM:
       
  1281      case MOZ_GTK_MENUITEM:
       
  1282      case MOZ_GTK_CHECKMENUITEM:
       
  1283      case MOZ_GTK_RADIOMENUITEM:
       
  1284          {
       
  1285 -            if (widget == MOZ_GTK_MENUITEM) {
       
  1286 -                ensure_menu_item_widget();
       
  1287 -                ensure_menu_bar_item_widget();
       
  1288 -                w = gMenuItemWidget;
       
  1289 -            }
       
  1290 -            else {
       
  1291 +            if (widget == MOZ_GTK_MENUBARITEM || widget == MOZ_GTK_MENUITEM) {
       
  1292 +                // Bug 1274143 for MOZ_GTK_MENUBARITEM
       
  1293 +                w = GetWidget(MOZ_GTK_MENUITEM);
       
  1294 +            } else {
       
  1295                  ensure_check_menu_item_widget();
       
  1296                  w = gCheckMenuItemWidget;
       
  1297              }
       
  1298 @@ -2784,9 +2489,16 @@ moz_gtk_get_widget_border(WidgetNodeType
       
  1299              return MOZ_GTK_SUCCESS;
       
  1300          }
       
  1301      case MOZ_GTK_INFO_BAR:
       
  1302 -        ensure_info_bar();
       
  1303 -        w = gInfoBar;
       
  1304 +        w = GetWidget(MOZ_GTK_INFO_BAR);
       
  1305          break;
       
  1306 +    case MOZ_GTK_TOOLTIP:
       
  1307 +        {
       
  1308 +            style = ClaimStyleContext(MOZ_GTK_TOOLTIP);
       
  1309 +            moz_gtk_add_style_border(style, left, top, right, bottom);
       
  1310 +            moz_gtk_add_style_padding(style, left, top, right, bottom);
       
  1311 +            ReleaseStyleContext(style);
       
  1312 +            return MOZ_GTK_SUCCESS;
       
  1313 +        }
       
  1314      /* These widgets have no borders, since they are not containers. */
       
  1315      case MOZ_GTK_CHECKBUTTON_LABEL:
       
  1316      case MOZ_GTK_RADIOBUTTON_LABEL:
       
  1317 @@ -2810,7 +2522,6 @@ moz_gtk_get_widget_border(WidgetNodeType
       
  1318      case MOZ_GTK_MENUSEPARATOR:
       
  1319      /* These widgets have no borders.*/
       
  1320      case MOZ_GTK_SPINBUTTON:
       
  1321 -    case MOZ_GTK_TOOLTIP:
       
  1322      case MOZ_GTK_WINDOW:
       
  1323      case MOZ_GTK_RESIZER:
       
  1324      case MOZ_GTK_MENUARROW:
       
  1325 @@ -2908,8 +2619,7 @@ moz_gtk_get_arrow_size(WidgetNodeType wi
       
  1326              widget = gComboBoxArrowWidget;
       
  1327              break;
       
  1328          default:
       
  1329 -            ensure_button_arrow_widget();
       
  1330 -            widget = gButtonArrowWidget;
       
  1331 +            widget = GetWidget(MOZ_GTK_BUTTON_ARROW);
       
  1332              break;
       
  1333      }
       
  1334  
       
  1335 @@ -2924,11 +2634,9 @@ moz_gtk_get_toolbar_separator_width(gint
       
  1336  {
       
  1337      gboolean wide_separators;
       
  1338      gint separator_width;
       
  1339 -    GtkStyleContext* style;
       
  1340      GtkBorder border;
       
  1341  
       
  1342 -    ensure_toolbar_widget();
       
  1343 -    style = gtk_widget_get_style_context(gToolbarWidget);
       
  1344 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR);
       
  1345      gtk_style_context_get_style(style,
       
  1346                                  "space-size", size,
       
  1347                                  "wide-separators",  &wide_separators,
       
  1348 @@ -2937,17 +2645,18 @@ moz_gtk_get_toolbar_separator_width(gint
       
  1349      /* Just in case... */
       
  1350      gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border);
       
  1351      *size = MAX(*size, (wide_separators ? separator_width : border.left));
       
  1352 +    ReleaseStyleContext(style);
       
  1353      return MOZ_GTK_SUCCESS;
       
  1354  }
       
  1355  
       
  1356  gint
       
  1357  moz_gtk_get_expander_size(gint* size)
       
  1358  {
       
  1359 -    ensure_expander_widget();
       
  1360 -    gtk_style_context_get_style(gtk_widget_get_style_context(gExpanderWidget),
       
  1361 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_EXPANDER);
       
  1362 +    gtk_style_context_get_style(style,
       
  1363                                  "expander-size", size,
       
  1364                                  NULL);
       
  1365 -
       
  1366 +    ReleaseStyleContext(style);
       
  1367      return MOZ_GTK_SUCCESS;
       
  1368  }
       
  1369  
       
  1370 @@ -2972,11 +2681,11 @@ moz_gtk_get_menu_separator_height(gint *
       
  1371      GtkStyleContext* style;
       
  1372      guint border_width;
       
  1373  
       
  1374 -    ensure_menu_separator_widget();
       
  1375 -
       
  1376 -    border_width = gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget));
       
  1377 +    border_width =
       
  1378 +        gtk_container_get_border_width(GTK_CONTAINER(
       
  1379 +                                       GetWidget(MOZ_GTK_MENUSEPARATOR)));
       
  1380  
       
  1381 -    style = gtk_widget_get_style_context(gMenuSeparatorWidget);
       
  1382 +    style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR);
       
  1383      gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
       
  1384  
       
  1385      gtk_style_context_save(style);
       
  1386 @@ -2988,6 +2697,7 @@ moz_gtk_get_menu_separator_height(gint *
       
  1387                                  NULL);
       
  1388  
       
  1389      gtk_style_context_restore(style);
       
  1390 +    ReleaseStyleContext(style);
       
  1391  
       
  1392      *size = padding.top + padding.bottom + border_width*2;
       
  1393      *size += (wide_separators) ? separator_height : 1;
       
  1394 @@ -2998,8 +2708,7 @@ moz_gtk_get_menu_separator_height(gint *
       
  1395  void
       
  1396  moz_gtk_get_entry_min_height(gint* height)
       
  1397  {
       
  1398 -    ensure_entry_widget();
       
  1399 -    GtkStyleContext* style = gtk_widget_get_style_context(gEntryWidget);
       
  1400 +    GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_ENTRY);
       
  1401      if (!gtk_check_version(3, 20, 0)) {
       
  1402          gtk_style_context_get(style, gtk_style_context_get_state(style),
       
  1403                                "min-height", height,
       
  1404 @@ -3014,6 +2723,7 @@ moz_gtk_get_entry_min_height(gint* heigh
       
  1405      gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
       
  1406  
       
  1407      *height += (border.top + border.bottom + padding.top + padding.bottom);
       
  1408 +    ReleaseStyleContext(style);
       
  1409  }
       
  1410  
       
  1411  void
       
  1412 @@ -3094,8 +2804,7 @@ moz_gtk_images_in_buttons()
       
  1413      gboolean result;
       
  1414      GtkSettings* settings;
       
  1415  
       
  1416 -    ensure_button_widget();
       
  1417 -    settings = gtk_widget_get_settings(gButtonWidget);
       
  1418 +    settings = gtk_widget_get_settings(GetWidget(MOZ_GTK_BUTTON));
       
  1419  
       
  1420      g_object_get(settings, "gtk-button-images", &result, NULL);
       
  1421      return result;
       
  1422 @@ -3116,14 +2825,14 @@ moz_gtk_widget_paint(WidgetNodeType widg
       
  1423      case MOZ_GTK_BUTTON:
       
  1424      case MOZ_GTK_TOOLBAR_BUTTON:
       
  1425          if (state->depressed) {
       
  1426 -            ensure_toggle_button_widget();
       
  1427              return moz_gtk_button_paint(cr, rect, state,
       
  1428                                          (GtkReliefStyle) flags,
       
  1429 -                                        gToggleButtonWidget, direction);
       
  1430 +                                        GetWidget(MOZ_GTK_TOGGLE_BUTTON),
       
  1431 +                                        direction);
       
  1432          }
       
  1433 -        ensure_button_widget();
       
  1434          return moz_gtk_button_paint(cr, rect, state,
       
  1435 -                                    (GtkReliefStyle) flags, gButtonWidget,
       
  1436 +                                    (GtkReliefStyle) flags,
       
  1437 +                                    GetWidget(MOZ_GTK_BUTTON),
       
  1438                                      direction);
       
  1439          break;
       
  1440      case MOZ_GTK_CHECKBUTTON:
       
  1441 @@ -3171,9 +2880,9 @@ moz_gtk_widget_paint(WidgetNodeType widg
       
  1442                                           state, direction);
       
  1443          break;
       
  1444      case MOZ_GTK_SPINBUTTON_ENTRY:
       
  1445 -        ensure_spin_widget();
       
  1446 +        // TODO - use MOZ_GTK_SPINBUTTON_ENTRY style directly
       
  1447          return moz_gtk_entry_paint(cr, rect, state,
       
  1448 -                                   gSpinWidget, direction);
       
  1449 +                                   GetWidget(MOZ_GTK_SPINBUTTON), direction);
       
  1450          break;
       
  1451      case MOZ_GTK_GRIPPER:
       
  1452          return moz_gtk_gripper_paint(cr, rect, state,
       
  1453 @@ -3198,9 +2907,11 @@ moz_gtk_widget_paint(WidgetNodeType widg
       
  1454                                                 (GtkExpanderStyle) flags, direction);
       
  1455          break;
       
  1456      case MOZ_GTK_ENTRY:
       
  1457 -        ensure_entry_widget();
       
  1458 -        return moz_gtk_entry_paint(cr, rect, state,
       
  1459 -                                   gEntryWidget, direction);
       
  1460 +        return moz_gtk_entry_paint(cr, rect, state, GetWidget(MOZ_GTK_ENTRY),
       
  1461 +                                   direction);
       
  1462 +        break;
       
  1463 +    case MOZ_GTK_TEXT_VIEW:
       
  1464 +        return moz_gtk_text_view_paint(cr, rect, state, direction);
       
  1465          break;
       
  1466      case MOZ_GTK_DROPDOWN:
       
  1467          return moz_gtk_combo_box_paint(cr, rect, state, direction);
       
  1468 @@ -3271,9 +2982,9 @@ moz_gtk_widget_paint(WidgetNodeType widg
       
  1469          return moz_gtk_menu_separator_paint(cr, rect,
       
  1470                                              direction);
       
  1471          break;
       
  1472 +    case MOZ_GTK_MENUBARITEM:
       
  1473      case MOZ_GTK_MENUITEM:
       
  1474 -        return moz_gtk_menu_item_paint(cr, rect, state, flags,
       
  1475 -                                       direction);
       
  1476 +        return moz_gtk_menu_item_paint(widget, cr, rect, state, direction);
       
  1477          break;
       
  1478      case MOZ_GTK_MENUARROW:
       
  1479          return moz_gtk_menu_arrow_paint(cr, rect, state,
       
  1480 @@ -3333,25 +3044,16 @@ gboolean moz_gtk_has_scrollbar_buttons(v
       
  1481  gint
       
  1482  moz_gtk_shutdown()
       
  1483  {
       
  1484 -    if (gTooltipWidget)
       
  1485 -        gtk_widget_destroy(gTooltipWidget);
       
  1486      /* This will destroy all of our widgets */
       
  1487 -
       
  1488      ResetWidgetCache();
       
  1489  
       
  1490      /* TODO - replace it with appropriate widget */
       
  1491      if (gTreeHeaderSortArrowWidget)
       
  1492          gtk_widget_destroy(gTreeHeaderSortArrowWidget);
       
  1493  
       
  1494 -    gProtoWindow = NULL;
       
  1495      gProtoLayout = NULL;
       
  1496 -    gButtonWidget = NULL;
       
  1497 -    gToggleButtonWidget = NULL;
       
  1498 -    gButtonArrowWidget = NULL;
       
  1499 -    gSpinWidget = NULL;
       
  1500      gHScaleWidget = NULL;
       
  1501      gVScaleWidget = NULL;
       
  1502 -    gEntryWidget = NULL;
       
  1503      gComboBoxWidget = NULL;
       
  1504      gComboBoxButtonWidget = NULL;
       
  1505      gComboBoxSeparatorWidget = NULL;
       
  1506 @@ -3360,29 +3062,15 @@ moz_gtk_shutdown()
       
  1507      gComboBoxEntryButtonWidget = NULL;
       
  1508      gComboBoxEntryArrowWidget = NULL;
       
  1509      gComboBoxEntryTextareaWidget = NULL;
       
  1510 -    gHandleBoxWidget = NULL;
       
  1511 -    gToolbarWidget = NULL;
       
  1512 -    gFrameWidget = NULL;
       
  1513 -    gProgressWidget = NULL;
       
  1514      gTabWidget = NULL;
       
  1515 -    gTextViewWidget = nullptr;
       
  1516 -    gTooltipWidget = NULL;
       
  1517 -    gMenuBarWidget = NULL;
       
  1518 -    gMenuBarItemWidget = NULL;
       
  1519 -    gMenuPopupWidget = NULL;
       
  1520 -    gMenuItemWidget = NULL;
       
  1521      gImageMenuItemWidget = NULL;
       
  1522      gCheckMenuItemWidget = NULL;
       
  1523      gTreeViewWidget = NULL;
       
  1524      gMiddleTreeViewColumn = NULL;
       
  1525      gTreeHeaderCellWidget = NULL;
       
  1526      gTreeHeaderSortArrowWidget = NULL;
       
  1527 -    gExpanderWidget = NULL;
       
  1528 -    gToolbarSeparatorWidget = NULL;
       
  1529 -    gMenuSeparatorWidget = NULL;
       
  1530      gHPanedWidget = NULL;
       
  1531      gVPanedWidget = NULL;
       
  1532 -    gScrolledWindowWidget = NULL;
       
  1533  
       
  1534      is_initialized = FALSE;
       
  1535  
       
  1536 diff -up firefox-48.0/widget/gtk/gtkdrawing.h.gtk3-20 firefox-48.0/widget/gtk/gtkdrawing.h
       
  1537 --- firefox-48.0/widget/gtk/gtkdrawing.h.gtk3-20	2016-07-25 22:22:07.000000000 +0200
       
  1538 +++ firefox-48.0/widget/gtk/gtkdrawing.h	2016-07-29 09:15:11.822285857 +0200
       
  1539 @@ -69,12 +69,6 @@ typedef enum {
       
  1540    MOZ_GTK_TAB_SELECTED        = 1 << 10
       
  1541  } GtkTabFlags;
       
  1542  
       
  1543 -/** flags for menuitems **/
       
  1544 -typedef enum {
       
  1545 -  /* menuitem is part of the menubar */
       
  1546 -  MOZ_TOPLEVEL_MENU_ITEM      = 1 << 0
       
  1547 -} GtkMenuItemFlags;
       
  1548 -
       
  1549  /* function type for moz_gtk_enable_style_props */
       
  1550  typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint);
       
  1551  
       
  1552 @@ -93,6 +87,10 @@ typedef enum {
       
  1553    MOZ_GTK_BUTTON,
       
  1554    /* Paints a button with image and no text */
       
  1555    MOZ_GTK_TOOLBAR_BUTTON,
       
  1556 +  /* Paints a toggle button */
       
  1557 +  MOZ_GTK_TOGGLE_BUTTON,
       
  1558 +  /* Paints a button arrow */
       
  1559 +  MOZ_GTK_BUTTON_ARROW,
       
  1560  
       
  1561    /* Paints the container part of a GtkCheckButton. */
       
  1562    MOZ_GTK_CHECKBUTTON_CONTAINER,
       
  1563 @@ -115,6 +113,7 @@ typedef enum {
       
  1564  
       
  1565    /* Horizontal GtkScrollbar counterparts */
       
  1566    MOZ_GTK_SCROLLBAR_HORIZONTAL,
       
  1567 +  MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL,
       
  1568    /* Paints the trough (track) of a GtkScrollbar. */
       
  1569    MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL,
       
  1570    /* Paints the slider (thumb) of a GtkScrollbar. */
       
  1571 @@ -122,6 +121,7 @@ typedef enum {
       
  1572  
       
  1573    /* Vertical GtkScrollbar counterparts */
       
  1574    MOZ_GTK_SCROLLBAR_VERTICAL,
       
  1575 +  MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL,
       
  1576    MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL,
       
  1577    MOZ_GTK_SCROLLBAR_THUMB_VERTICAL,
       
  1578  
       
  1579 @@ -140,6 +140,10 @@ typedef enum {
       
  1580    MOZ_GTK_GRIPPER,
       
  1581    /* Paints a GtkEntry. */
       
  1582    MOZ_GTK_ENTRY,
       
  1583 +  /* Paints a GtkExpander. */
       
  1584 +  MOZ_GTK_EXPANDER,
       
  1585 +  /* Paints a GtkTextView. */
       
  1586 +  MOZ_GTK_TEXT_VIEW,
       
  1587    /* Paints a GtkOptionMenu. */
       
  1588    MOZ_GTK_DROPDOWN,
       
  1589    /* Paints a dropdown arrow (a GtkButton containing a down GtkArrow). */
       
  1590 @@ -159,6 +163,8 @@ typedef enum {
       
  1591    MOZ_GTK_RESIZER,
       
  1592    /* Paints a GtkProgressBar. */
       
  1593    MOZ_GTK_PROGRESSBAR,
       
  1594 +  /* Paints a trough (track) of a GtkProgressBar */
       
  1595 +  MOZ_GTK_PROGRESS_TROUGH,
       
  1596    /* Paints a progress chunk of a GtkProgressBar. */
       
  1597    MOZ_GTK_PROGRESS_CHUNK,
       
  1598    /* Paints a progress chunk of an indeterminated GtkProgressBar. */
       
  1599 @@ -187,7 +193,9 @@ typedef enum {
       
  1600    MOZ_GTK_MENUARROW,
       
  1601    /* Paints an arrow in a toolbar button. flags is a GtkArrowType. */
       
  1602    MOZ_GTK_TOOLBARBUTTON_ARROW,
       
  1603 -  /* Paints items of menubar and popups. */
       
  1604 +  /* Paints items of menubar. */
       
  1605 +  MOZ_GTK_MENUBARITEM,
       
  1606 +  /* Paints items of popup menus. */
       
  1607    MOZ_GTK_MENUITEM,
       
  1608    MOZ_GTK_CHECKMENUITEM,
       
  1609    MOZ_GTK_RADIOMENUITEM,
       
  1610 @@ -202,6 +210,8 @@ typedef enum {
       
  1611    MOZ_GTK_WINDOW_CONTAINER,
       
  1612    /* Paints a GtkInfoBar, for notifications. */
       
  1613    MOZ_GTK_INFO_BAR,
       
  1614 +  /* Used for scrolled window shell. */
       
  1615 +  MOZ_GTK_SCROLLED_WINDOW,
       
  1616  
       
  1617    MOZ_GTK_WIDGET_NODE_COUNT
       
  1618  } WidgetNodeType;
       
  1619 diff -up firefox-48.0/widget/gtk/mozgtk/mozgtk.c.gtk3-20 firefox-48.0/widget/gtk/mozgtk/mozgtk.c
       
  1620 --- firefox-48.0/widget/gtk/mozgtk/mozgtk.c.gtk3-20	2016-07-25 22:22:07.000000000 +0200
       
  1621 +++ firefox-48.0/widget/gtk/mozgtk/mozgtk.c	2016-07-29 09:15:11.823285862 +0200
       
  1622 @@ -517,6 +517,7 @@ STUB(gdk_event_get_source_device)
       
  1623  STUB(gdk_window_get_type)
       
  1624  STUB(gdk_x11_window_get_xid)
       
  1625  STUB(gdk_x11_display_get_type)
       
  1626 +STUB(gtk_box_new)
       
  1627  STUB(gtk_cairo_should_draw_window)
       
  1628  STUB(gtk_cairo_transform_to_window)
       
  1629  STUB(gtk_combo_box_text_append)
       
  1630 @@ -570,6 +571,7 @@ STUB(gtk_tree_view_column_get_button)
       
  1631  STUB(gtk_widget_get_preferred_size)
       
  1632  STUB(gtk_widget_get_state_flags)
       
  1633  STUB(gtk_widget_get_style_context)
       
  1634 +STUB(gtk_widget_path_append_for_widget)
       
  1635  STUB(gtk_widget_path_append_type)
       
  1636  STUB(gtk_widget_path_copy)
       
  1637  STUB(gtk_widget_path_free)
       
  1638 @@ -587,6 +589,10 @@ STUB(gtk_color_chooser_get_type)
       
  1639  STUB(gtk_color_chooser_set_rgba)
       
  1640  STUB(gtk_color_chooser_get_rgba)
       
  1641  STUB(gtk_color_chooser_set_use_alpha)
       
  1642 +STUB(gtk_check_menu_item_new)
       
  1643 +STUB(gtk_style_context_get_direction)
       
  1644 +STUB(gtk_style_context_invalidate)
       
  1645 +STUB(gtk_tooltip_get_type)
       
  1646  #endif
       
  1647  
       
  1648  #ifdef GTK2_SYMBOLS
       
  1649 diff -up firefox-48.0/widget/gtk/nsLookAndFeel.cpp.gtk3-20 firefox-48.0/widget/gtk/nsLookAndFeel.cpp
       
  1650 --- firefox-48.0/widget/gtk/nsLookAndFeel.cpp.gtk3-20	2016-06-01 06:11:44.000000000 +0200
       
  1651 +++ firefox-48.0/widget/gtk/nsLookAndFeel.cpp	2016-07-29 09:15:54.943459700 +0200
       
  1652 @@ -31,6 +31,7 @@
       
  1653  
       
  1654  #if MOZ_WIDGET_GTK != 2
       
  1655  #include <cairo-gobject.h>
       
  1656 +#include "WidgetStyleCache.h"
       
  1657  #endif
       
  1658  
       
  1659  using mozilla::LookAndFeel;
       
  1660 @@ -1135,15 +1136,24 @@ nsLookAndFeel::Init()
       
  1661      gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color);
       
  1662      sMozWindowText = GDK_RGBA_TO_NS_RGBA(color);
       
  1663      gtk_style_context_restore(style);
       
  1664 +    g_object_unref(style);
       
  1665  
       
  1666      // tooltip foreground and background
       
  1667 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP);
       
  1668 -    gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND);
       
  1669 +    style = ClaimStyleContext(MOZ_GTK_TOOLTIP);
       
  1670      gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color);
       
  1671      sInfoBackground = GDK_RGBA_TO_NS_RGBA(color);
       
  1672 -    gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color);
       
  1673 +    {
       
  1674 +        GtkStyleContext* boxStyle =
       
  1675 +            CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0),
       
  1676 +                                 style);
       
  1677 +        GtkStyleContext* labelStyle =
       
  1678 +            CreateStyleForWidget(gtk_label_new(nullptr), boxStyle);
       
  1679 +        gtk_style_context_get_color(labelStyle, GTK_STATE_FLAG_NORMAL, &color);
       
  1680 +        g_object_unref(labelStyle);
       
  1681 +        g_object_unref(boxStyle);
       
  1682 +    }
       
  1683      sInfoText = GDK_RGBA_TO_NS_RGBA(color);
       
  1684 -    g_object_unref(style);
       
  1685 +    ReleaseStyleContext(style);
       
  1686  
       
  1687      // menu foreground & menu background
       
  1688      GtkWidget *accel_label = gtk_accel_label_new("M");
       
  1689 diff -up firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp.gtk3-20 firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp
       
  1690 --- firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp.gtk3-20	2016-07-25 22:22:07.000000000 +0200
       
  1691 +++ firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp	2016-07-29 09:15:11.824285865 +0200
       
  1692 @@ -354,10 +354,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
       
  1693  
       
  1694            if (isTopLevel) {
       
  1695              aState->inHover = menuFrame->IsOpen();
       
  1696 -            *aWidgetFlags |= MOZ_TOPLEVEL_MENU_ITEM;
       
  1697            } else {
       
  1698              aState->inHover = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
       
  1699 -            *aWidgetFlags &= ~MOZ_TOPLEVEL_MENU_ITEM;
       
  1700            }
       
  1701  
       
  1702            aState->active = FALSE;
       
  1703 @@ -510,8 +508,14 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
       
  1704      break;
       
  1705    case NS_THEME_NUMBER_INPUT:
       
  1706    case NS_THEME_TEXTFIELD:
       
  1707 +    aGtkWidgetType = MOZ_GTK_ENTRY;
       
  1708 +    break;
       
  1709    case NS_THEME_TEXTFIELD_MULTILINE:
       
  1710 +#if (MOZ_WIDGET_GTK == 3)
       
  1711 +    aGtkWidgetType = MOZ_GTK_TEXT_VIEW;
       
  1712 +#else
       
  1713      aGtkWidgetType = MOZ_GTK_ENTRY;
       
  1714 +#endif
       
  1715      break;
       
  1716    case NS_THEME_LISTBOX:
       
  1717    case NS_THEME_TREEVIEW:
       
  1718 @@ -673,6 +677,13 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
       
  1719      aGtkWidgetType = MOZ_GTK_MENUPOPUP;
       
  1720      break;
       
  1721    case NS_THEME_MENUITEM:
       
  1722 +    {
       
  1723 +      nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
       
  1724 +      if (menuFrame && menuFrame->IsOnMenuBar()) {
       
  1725 +        aGtkWidgetType = MOZ_GTK_MENUBARITEM;
       
  1726 +        break;
       
  1727 +      }
       
  1728 +    }
       
  1729      aGtkWidgetType = MOZ_GTK_MENUITEM;
       
  1730      break;
       
  1731    case NS_THEME_MENUSEPARATOR:
       
  1732 diff -up firefox-48.0/widget/gtk/WidgetStyleCache.cpp.gtk3-20 firefox-48.0/widget/gtk/WidgetStyleCache.cpp
       
  1733 --- firefox-48.0/widget/gtk/WidgetStyleCache.cpp.gtk3-20	2016-07-25 22:22:07.000000000 +0200
       
  1734 +++ firefox-48.0/widget/gtk/WidgetStyleCache.cpp	2016-07-29 09:15:11.825285869 +0200
       
  1735 @@ -22,7 +22,7 @@ static bool sStyleContextNeedsRestore;
       
  1736  static GtkStyleContext* sCurrentStyleContext;
       
  1737  #endif
       
  1738  static GtkStyleContext*
       
  1739 -GetStyleInternal(WidgetNodeType aNodeType);
       
  1740 +GetCssNodeStyleInternal(WidgetNodeType aNodeType);
       
  1741  
       
  1742  static GtkWidget*
       
  1743  CreateWindowWidget()
       
  1744 @@ -67,12 +67,175 @@ CreateCheckboxWidget()
       
  1745  static GtkWidget*
       
  1746  CreateRadiobuttonWidget()
       
  1747  {
       
  1748 -  GtkWidget* widget = gtk_radio_button_new_with_label(NULL, "M");
       
  1749 +  GtkWidget* widget = gtk_radio_button_new_with_label(nullptr, "M");
       
  1750    AddToWindowContainer(widget);
       
  1751    return widget;
       
  1752  }
       
  1753  
       
  1754  static GtkWidget*
       
  1755 +CreateMenuBarWidget()
       
  1756 +{
       
  1757 +  GtkWidget* widget = gtk_menu_bar_new();
       
  1758 +  AddToWindowContainer(widget);
       
  1759 +  return widget;
       
  1760 +}
       
  1761 +
       
  1762 +static GtkWidget*
       
  1763 +CreateMenuPopupWidget()
       
  1764 +{
       
  1765 +  GtkWidget* widget = gtk_menu_new();
       
  1766 +  gtk_menu_attach_to_widget(GTK_MENU(widget), GetWidget(MOZ_GTK_WINDOW),
       
  1767 +                            nullptr);
       
  1768 +  return widget;
       
  1769 +}
       
  1770 +
       
  1771 +static GtkWidget*
       
  1772 +CreateMenuItemWidget(WidgetNodeType aShellType)
       
  1773 +{
       
  1774 +  GtkWidget* widget = gtk_menu_item_new();
       
  1775 +  gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(aShellType)), widget);
       
  1776 +  return widget;
       
  1777 +}
       
  1778 +
       
  1779 +static GtkWidget*
       
  1780 +CreateProgressWidget()
       
  1781 +{
       
  1782 +  GtkWidget* widget = gtk_progress_bar_new();
       
  1783 +  AddToWindowContainer(widget);
       
  1784 +  return widget;
       
  1785 +}
       
  1786 +
       
  1787 +static GtkWidget*
       
  1788 +CreateTooltipWidget()
       
  1789 +{
       
  1790 +  MOZ_ASSERT(gtk_check_version(3, 20, 0) != nullptr,
       
  1791 +             "CreateTooltipWidget should be used for Gtk < 3.20 only.");
       
  1792 +  GtkWidget* widget = CreateWindowWidget();
       
  1793 +  GtkStyleContext* style = gtk_widget_get_style_context(widget);
       
  1794 +  gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP);
       
  1795 +  return widget;
       
  1796 +}
       
  1797 +
       
  1798 +static GtkWidget*
       
  1799 +CreateExpanderWidget()
       
  1800 +{
       
  1801 +  GtkWidget* widget = gtk_expander_new("M");
       
  1802 +  AddToWindowContainer(widget);
       
  1803 +  return widget;
       
  1804 +}
       
  1805 +
       
  1806 +static GtkWidget*
       
  1807 +CreateFrameWidget()
       
  1808 +{
       
  1809 +  GtkWidget* widget = gtk_frame_new(nullptr);
       
  1810 +  AddToWindowContainer(widget);
       
  1811 +  return widget;
       
  1812 +}
       
  1813 +
       
  1814 +static GtkWidget*
       
  1815 +CreateGripperWidget()
       
  1816 +{
       
  1817 +  GtkWidget* widget = gtk_handle_box_new();
       
  1818 +  AddToWindowContainer(widget);
       
  1819 +  return widget;
       
  1820 +}
       
  1821 +
       
  1822 +static GtkWidget*
       
  1823 +CreateToolbarWidget()
       
  1824 +{
       
  1825 +  GtkWidget* widget = gtk_toolbar_new();
       
  1826 +  gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_GRIPPER)), widget);
       
  1827 +  gtk_widget_realize(widget);
       
  1828 +  return widget;
       
  1829 +}
       
  1830 +
       
  1831 +static GtkWidget*
       
  1832 +CreateToolbarSeparatorWidget()
       
  1833 +{
       
  1834 +  GtkWidget* widget = GTK_WIDGET(gtk_separator_tool_item_new());
       
  1835 +  AddToWindowContainer(widget);
       
  1836 +  return widget;
       
  1837 +}
       
  1838 +
       
  1839 +static GtkWidget*
       
  1840 +CreateInfoBarWidget()
       
  1841 +{
       
  1842 +  GtkWidget* widget = gtk_info_bar_new();
       
  1843 +  AddToWindowContainer(widget);
       
  1844 +  return widget;
       
  1845 +}
       
  1846 +
       
  1847 +static GtkWidget*
       
  1848 +CreateButtonWidget()
       
  1849 +{
       
  1850 +  GtkWidget* widget = gtk_button_new_with_label("M");
       
  1851 +  AddToWindowContainer(widget);
       
  1852 +  return widget;
       
  1853 +}
       
  1854 +
       
  1855 +static GtkWidget*
       
  1856 +CreateToggleButtonWidget()
       
  1857 +{
       
  1858 +  GtkWidget* widget = gtk_toggle_button_new();
       
  1859 +  AddToWindowContainer(widget);
       
  1860 +  return widget;
       
  1861 +}
       
  1862 +
       
  1863 +static GtkWidget*
       
  1864 +CreateButtonArrowWidget()
       
  1865 +{
       
  1866 +  GtkWidget* widget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
       
  1867 +  gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_TOGGLE_BUTTON)), widget);
       
  1868 +  gtk_widget_realize(widget);
       
  1869 +  gtk_widget_show(widget);
       
  1870 +  return widget;
       
  1871 +}
       
  1872 +
       
  1873 +static GtkWidget*
       
  1874 +CreateSpinWidget()
       
  1875 +{
       
  1876 +  GtkWidget* widget = gtk_spin_button_new(nullptr, 1, 0);
       
  1877 +  AddToWindowContainer(widget);
       
  1878 +  return widget;
       
  1879 +}
       
  1880 +
       
  1881 +static GtkWidget*
       
  1882 +CreateEntryWidget()
       
  1883 +{
       
  1884 +  GtkWidget* widget = gtk_entry_new();
       
  1885 +  AddToWindowContainer(widget);
       
  1886 +  return widget;
       
  1887 +}
       
  1888 +
       
  1889 +static GtkWidget*
       
  1890 +CreateScrolledWindowWidget()
       
  1891 +{
       
  1892 +  GtkWidget* widget = gtk_scrolled_window_new(nullptr, nullptr);
       
  1893 +  AddToWindowContainer(widget);
       
  1894 +  return widget;
       
  1895 +}
       
  1896 +
       
  1897 +static GtkWidget*
       
  1898 +CreateTextViewWidget()
       
  1899 +{
       
  1900 +  GtkWidget* widget = gtk_text_view_new();
       
  1901 +  gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_SCROLLED_WINDOW)),
       
  1902 +                    widget);
       
  1903 +  return widget;
       
  1904 +}
       
  1905 +
       
  1906 +static GtkWidget*
       
  1907 +CreateMenuSeparatorWidget()
       
  1908 +{
       
  1909 +  GtkWidget* widget = gtk_separator_menu_item_new();
       
  1910 +  gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
       
  1911 +                        widget);
       
  1912 +  gtk_widget_realize(widget);
       
  1913 +  return widget;
       
  1914 +}
       
  1915 +
       
  1916 +
       
  1917 +static GtkWidget*
       
  1918  CreateWidget(WidgetNodeType aWidgetType)
       
  1919  {
       
  1920    switch (aWidgetType) {
       
  1921 @@ -80,16 +243,54 @@ CreateWidget(WidgetNodeType aWidgetType)
       
  1922        return CreateWindowWidget();
       
  1923      case MOZ_GTK_WINDOW_CONTAINER:
       
  1924        return CreateWindowContainerWidget();
       
  1925 +    case MOZ_GTK_CHECKBUTTON_CONTAINER:
       
  1926 +      return CreateCheckboxWidget();
       
  1927 +    case MOZ_GTK_PROGRESSBAR:
       
  1928 +      return CreateProgressWidget();
       
  1929 +    case MOZ_GTK_RADIOBUTTON_CONTAINER:
       
  1930 +      return CreateRadiobuttonWidget();
       
  1931      case MOZ_GTK_SCROLLBAR_HORIZONTAL:
       
  1932        return CreateScrollbarWidget(aWidgetType,
       
  1933                                     GTK_ORIENTATION_HORIZONTAL);
       
  1934      case MOZ_GTK_SCROLLBAR_VERTICAL:
       
  1935        return CreateScrollbarWidget(aWidgetType,
       
  1936                                     GTK_ORIENTATION_VERTICAL);
       
  1937 -    case MOZ_GTK_CHECKBUTTON_CONTAINER:
       
  1938 -      return CreateCheckboxWidget();
       
  1939 -    case MOZ_GTK_RADIOBUTTON_CONTAINER:
       
  1940 -      return CreateRadiobuttonWidget();
       
  1941 +    case MOZ_GTK_MENUBAR:
       
  1942 +      return CreateMenuBarWidget();
       
  1943 +    case MOZ_GTK_MENUPOPUP:
       
  1944 +      return CreateMenuPopupWidget();
       
  1945 +    case MOZ_GTK_MENUBARITEM:
       
  1946 +      return CreateMenuItemWidget(MOZ_GTK_MENUBAR);
       
  1947 +    case MOZ_GTK_MENUITEM:
       
  1948 +      return CreateMenuItemWidget(MOZ_GTK_MENUPOPUP);
       
  1949 +    case MOZ_GTK_MENUSEPARATOR:
       
  1950 +      return CreateMenuSeparatorWidget();
       
  1951 +    case MOZ_GTK_EXPANDER:
       
  1952 +      return CreateExpanderWidget();
       
  1953 +    case MOZ_GTK_FRAME:
       
  1954 +      return CreateFrameWidget();
       
  1955 +    case MOZ_GTK_GRIPPER:
       
  1956 +      return CreateGripperWidget();
       
  1957 +    case MOZ_GTK_TOOLBAR:
       
  1958 +      return CreateToolbarWidget();
       
  1959 +    case MOZ_GTK_TOOLBAR_SEPARATOR:
       
  1960 +      return CreateToolbarSeparatorWidget();
       
  1961 +    case MOZ_GTK_INFO_BAR:
       
  1962 +      return CreateInfoBarWidget();
       
  1963 +    case MOZ_GTK_SPINBUTTON:
       
  1964 +      return CreateSpinWidget();
       
  1965 +    case MOZ_GTK_BUTTON:
       
  1966 +      return CreateButtonWidget();
       
  1967 +    case MOZ_GTK_TOGGLE_BUTTON:
       
  1968 +      return CreateToggleButtonWidget();
       
  1969 +    case MOZ_GTK_BUTTON_ARROW:
       
  1970 +      return CreateButtonArrowWidget();
       
  1971 +    case MOZ_GTK_ENTRY:
       
  1972 +      return CreateEntryWidget();
       
  1973 +    case MOZ_GTK_SCROLLED_WINDOW: 
       
  1974 +      return CreateScrolledWindowWidget();
       
  1975 +    case MOZ_GTK_TEXT_VIEW:
       
  1976 +      return CreateTextViewWidget();
       
  1977      default:
       
  1978        /* Not implemented */
       
  1979        return nullptr;
       
  1980 @@ -107,17 +308,42 @@ GetWidget(WidgetNodeType aWidgetType)
       
  1981    return widget;
       
  1982  }
       
  1983  
       
  1984 -static GtkStyleContext*
       
  1985 -CreateCSSNode(const char* aName, GtkStyleContext *aParentStyle)
       
  1986 +GtkStyleContext*
       
  1987 +CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle)
       
  1988 +{
       
  1989 +  GtkWidgetPath* path = aParentStyle ?
       
  1990 +    gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) :
       
  1991 +    gtk_widget_path_new();
       
  1992 +
       
  1993 +  // Work around https://bugzilla.gnome.org/show_bug.cgi?id=767312
       
  1994 +  // which exists in GTK+ 3.20.
       
  1995 +  gtk_widget_get_style_context(aWidget);
       
  1996 +
       
  1997 +  gtk_widget_path_append_for_widget(path, aWidget);
       
  1998 +  // Release any floating reference on aWidget.
       
  1999 +  g_object_ref_sink(aWidget);
       
  2000 +  g_object_unref(aWidget);
       
  2001 +
       
  2002 +  GtkStyleContext *context = gtk_style_context_new();
       
  2003 +  gtk_style_context_set_path(context, path);
       
  2004 +  gtk_style_context_set_parent(context, aParentStyle);
       
  2005 +  gtk_widget_path_unref(path);
       
  2006 +
       
  2007 +  return context;
       
  2008 +}
       
  2009 +
       
  2010 +GtkStyleContext*
       
  2011 +CreateCSSNode(const char* aName, GtkStyleContext* aParentStyle, GType aType)
       
  2012  {
       
  2013    static auto sGtkWidgetPathIterSetObjectName =
       
  2014      reinterpret_cast<void (*)(GtkWidgetPath *, gint, const char *)>
       
  2015      (dlsym(RTLD_DEFAULT, "gtk_widget_path_iter_set_object_name"));
       
  2016  
       
  2017 -  GtkWidgetPath* path =
       
  2018 -    gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle));
       
  2019 +  GtkWidgetPath* path = aParentStyle ?
       
  2020 +    gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) :
       
  2021 +    gtk_widget_path_new();
       
  2022  
       
  2023 -  gtk_widget_path_append_type(path, G_TYPE_NONE);
       
  2024 +  gtk_widget_path_append_type(path, aType);
       
  2025  
       
  2026    (*sGtkWidgetPathIterSetObjectName)(path, -1, aName);
       
  2027  
       
  2028 @@ -130,95 +356,168 @@ CreateCSSNode(const char* aName, GtkStyl
       
  2029  }
       
  2030  
       
  2031  static GtkStyleContext*
       
  2032 -GetChildNodeStyle(WidgetNodeType aStyleType,
       
  2033 -                  WidgetNodeType aWidgetType,
       
  2034 -                  const gchar*   aStyleClass,
       
  2035 -                  WidgetNodeType aParentNodeType)
       
  2036 +CreateChildCSSNode(const char* aName, WidgetNodeType aParentNodeType)
       
  2037  {
       
  2038 -  GtkStyleContext* style;
       
  2039 -
       
  2040 -  if (gtk_check_version(3, 20, 0) != nullptr) {
       
  2041 -    style = gtk_widget_get_style_context(sWidgetStorage[aWidgetType]);
       
  2042 -
       
  2043 -    gtk_style_context_save(style);
       
  2044 -    MOZ_ASSERT(!sStyleContextNeedsRestore);
       
  2045 -    sStyleContextNeedsRestore = true;
       
  2046 -
       
  2047 -    gtk_style_context_add_class(style, aStyleClass);
       
  2048 -  }
       
  2049 -  else {
       
  2050 -    style = sStyleStorage[aStyleType];
       
  2051 -    if (!style) {
       
  2052 -      style = CreateCSSNode(aStyleClass, GetStyleInternal(aParentNodeType));
       
  2053 -      MOZ_ASSERT(!sStyleContextNeedsRestore);
       
  2054 -      sStyleStorage[aStyleType] = style;
       
  2055 -    }
       
  2056 -  }
       
  2057 +  return CreateCSSNode(aName, GetCssNodeStyleInternal(aParentNodeType));
       
  2058 +}
       
  2059  
       
  2060 +static GtkStyleContext*
       
  2061 +GetWidgetStyleWithClass(WidgetNodeType aWidgetType, const gchar* aStyleClass)
       
  2062 +{
       
  2063 +  GtkStyleContext* style = gtk_widget_get_style_context(GetWidget(aWidgetType));
       
  2064 +  gtk_style_context_save(style);
       
  2065 +  MOZ_ASSERT(!sStyleContextNeedsRestore);
       
  2066 +  sStyleContextNeedsRestore = true;
       
  2067 +  gtk_style_context_add_class(style, aStyleClass);
       
  2068    return style;
       
  2069  }
       
  2070  
       
  2071 +/* GetCssNodeStyleInternal is used by Gtk >= 3.20 */
       
  2072  static GtkStyleContext*
       
  2073 -GetStyleInternal(WidgetNodeType aNodeType)
       
  2074 +GetCssNodeStyleInternal(WidgetNodeType aNodeType)
       
  2075  {
       
  2076 +  GtkStyleContext* style = sStyleStorage[aNodeType];
       
  2077 +  if (style)
       
  2078 +    return style;
       
  2079 +
       
  2080    switch (aNodeType) {
       
  2081 -    case MOZ_GTK_SCROLLBAR_HORIZONTAL:
       
  2082 -      /* Root CSS node / widget for scrollbars */
       
  2083 +    case MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL:
       
  2084 +      style = CreateChildCSSNode("contents",
       
  2085 +                                 MOZ_GTK_SCROLLBAR_HORIZONTAL);
       
  2086        break;
       
  2087      case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL:
       
  2088 -      return GetChildNodeStyle(aNodeType,
       
  2089 -                               MOZ_GTK_SCROLLBAR_HORIZONTAL,
       
  2090 -                               GTK_STYLE_CLASS_TROUGH,
       
  2091 -                               MOZ_GTK_SCROLLBAR_HORIZONTAL);
       
  2092 -
       
  2093 +      style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
       
  2094 +                                 MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL);
       
  2095 +      break;
       
  2096      case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
       
  2097 -      return GetChildNodeStyle(aNodeType,
       
  2098 -                               MOZ_GTK_SCROLLBAR_HORIZONTAL,
       
  2099 -                               GTK_STYLE_CLASS_SLIDER,
       
  2100 -                               MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL);
       
  2101 -
       
  2102 -    case MOZ_GTK_SCROLLBAR_VERTICAL:
       
  2103 -      /* Root CSS node / widget for scrollbars */
       
  2104 +      style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER,
       
  2105 +                                 MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL);
       
  2106 +      break;
       
  2107 +    case MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL:
       
  2108 +      style = CreateChildCSSNode("contents",
       
  2109 +                                 MOZ_GTK_SCROLLBAR_VERTICAL);
       
  2110        break;
       
  2111      case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL:
       
  2112 -      return GetChildNodeStyle(aNodeType,
       
  2113 -                               MOZ_GTK_SCROLLBAR_VERTICAL,
       
  2114 -                               GTK_STYLE_CLASS_TROUGH,
       
  2115 -                               MOZ_GTK_SCROLLBAR_VERTICAL);
       
  2116 -
       
  2117 +      style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
       
  2118 +                                 MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL);
       
  2119 +      break;
       
  2120      case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
       
  2121 -      return GetChildNodeStyle(aNodeType,
       
  2122 -                               MOZ_GTK_SCROLLBAR_VERTICAL,
       
  2123 -                               GTK_STYLE_CLASS_SLIDER,
       
  2124 -                               MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL);
       
  2125 -
       
  2126 -    case MOZ_GTK_RADIOBUTTON_CONTAINER:
       
  2127 -      /* Root CSS node / widget for checkboxes */
       
  2128 +      style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER,
       
  2129 +                                 MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL);
       
  2130        break;
       
  2131      case MOZ_GTK_RADIOBUTTON:
       
  2132 -      return GetChildNodeStyle(aNodeType,
       
  2133 -                               MOZ_GTK_RADIOBUTTON_CONTAINER,
       
  2134 -                               GTK_STYLE_CLASS_RADIO,
       
  2135 -                               MOZ_GTK_RADIOBUTTON_CONTAINER);
       
  2136 -    case MOZ_GTK_CHECKBUTTON_CONTAINER:
       
  2137 -      /* Root CSS node / widget for radiobuttons */
       
  2138 +      style = CreateChildCSSNode(GTK_STYLE_CLASS_RADIO,
       
  2139 +                                 MOZ_GTK_RADIOBUTTON_CONTAINER);
       
  2140        break;
       
  2141      case MOZ_GTK_CHECKBUTTON:
       
  2142 -      return GetChildNodeStyle(aNodeType,
       
  2143 -                               MOZ_GTK_CHECKBUTTON_CONTAINER,
       
  2144 -                               GTK_STYLE_CLASS_CHECK,
       
  2145 -                               MOZ_GTK_CHECKBUTTON_CONTAINER);
       
  2146 -    default:
       
  2147 +      style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK,
       
  2148 +                                 MOZ_GTK_CHECKBUTTON_CONTAINER);
       
  2149 +      break;
       
  2150 +    case MOZ_GTK_PROGRESS_TROUGH:
       
  2151 +      /* Progress bar background (trough) */
       
  2152 +      style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
       
  2153 +                                 MOZ_GTK_PROGRESSBAR);
       
  2154 +      break;
       
  2155 +    case MOZ_GTK_PROGRESS_CHUNK:
       
  2156 +      style = CreateChildCSSNode("progress",
       
  2157 +                                 MOZ_GTK_PROGRESS_TROUGH);
       
  2158        break;
       
  2159 +    case MOZ_GTK_TOOLTIP:
       
  2160 +      // We create this from the path because GtkTooltipWindow is not public.
       
  2161 +      style = CreateCSSNode("tooltip", nullptr, GTK_TYPE_TOOLTIP);
       
  2162 +      gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND);
       
  2163 +      break; 
       
  2164 +    case MOZ_GTK_GRIPPER:
       
  2165 +      // TODO - create from CSS node
       
  2166 +      return GetWidgetStyleWithClass(MOZ_GTK_GRIPPER,
       
  2167 +                                     GTK_STYLE_CLASS_GRIP);
       
  2168 +    case MOZ_GTK_INFO_BAR:
       
  2169 +      // TODO - create from CSS node
       
  2170 +      return GetWidgetStyleWithClass(MOZ_GTK_INFO_BAR,
       
  2171 +                                     GTK_STYLE_CLASS_INFO);
       
  2172 +    case MOZ_GTK_SPINBUTTON_ENTRY:
       
  2173 +      // TODO - create from CSS node
       
  2174 +      return GetWidgetStyleWithClass(MOZ_GTK_SPINBUTTON,
       
  2175 +                                     GTK_STYLE_CLASS_ENTRY);
       
  2176 +    case MOZ_GTK_SCROLLED_WINDOW:
       
  2177 +      // TODO - create from CSS node
       
  2178 +      return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW,
       
  2179 +                                     GTK_STYLE_CLASS_FRAME);
       
  2180 +    case MOZ_GTK_TEXT_VIEW:
       
  2181 +      // TODO - create from CSS node
       
  2182 +      return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
       
  2183 +                                     GTK_STYLE_CLASS_VIEW);
       
  2184 +    default:
       
  2185 +      // TODO - create style from style path
       
  2186 +      GtkWidget* widget = GetWidget(aNodeType);
       
  2187 +      return gtk_widget_get_style_context(widget);
       
  2188    }
       
  2189  
       
  2190 -  GtkWidget* widget = GetWidget(aNodeType);
       
  2191 -  if (widget) {
       
  2192 -    return gtk_widget_get_style_context(widget);
       
  2193 -  }
       
  2194 +  MOZ_ASSERT(style, "missing style context for node type");
       
  2195 +  sStyleStorage[aNodeType] = style;
       
  2196 +  return style;
       
  2197 +}
       
  2198  
       
  2199 -  MOZ_ASSERT_UNREACHABLE("missing style context for node type");
       
  2200 -  return nullptr;
       
  2201 +/* GetWidgetStyleInternal is used by Gtk < 3.20 */
       
  2202 +static GtkStyleContext*
       
  2203 +GetWidgetStyleInternal(WidgetNodeType aNodeType)
       
  2204 +{
       
  2205 +  switch (aNodeType) {
       
  2206 +    case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL:
       
  2207 +      return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_HORIZONTAL,
       
  2208 +                                     GTK_STYLE_CLASS_TROUGH);
       
  2209 +    case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
       
  2210 +      return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_HORIZONTAL,
       
  2211 +                                     GTK_STYLE_CLASS_SLIDER);
       
  2212 +    case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL:
       
  2213 +      return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_VERTICAL,
       
  2214 +                                     GTK_STYLE_CLASS_TROUGH);
       
  2215 +    case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
       
  2216 +      return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_VERTICAL,
       
  2217 +                                     GTK_STYLE_CLASS_SLIDER);
       
  2218 +    case MOZ_GTK_RADIOBUTTON:
       
  2219 +      return GetWidgetStyleWithClass(MOZ_GTK_RADIOBUTTON_CONTAINER,
       
  2220 +                                     GTK_STYLE_CLASS_RADIO);
       
  2221 +    case MOZ_GTK_CHECKBUTTON:
       
  2222 +      return GetWidgetStyleWithClass(MOZ_GTK_CHECKBUTTON_CONTAINER,
       
  2223 +                                     GTK_STYLE_CLASS_CHECK);
       
  2224 +    case MOZ_GTK_PROGRESS_TROUGH:
       
  2225 +      return GetWidgetStyleWithClass(MOZ_GTK_PROGRESSBAR,
       
  2226 +                                     GTK_STYLE_CLASS_TROUGH);
       
  2227 +    case MOZ_GTK_TOOLTIP: {
       
  2228 +      GtkStyleContext* style = sStyleStorage[aNodeType];
       
  2229 +      if (style)
       
  2230 +        return style;
       
  2231 +
       
  2232 +      // The tooltip style class is added first in CreateTooltipWidget() so
       
  2233 +      // that gtk_widget_path_append_for_widget() in CreateStyleForWidget()
       
  2234 +      // will find it.
       
  2235 +      GtkWidget* tooltipWindow = CreateTooltipWidget();
       
  2236 +      style = CreateStyleForWidget(tooltipWindow, nullptr);
       
  2237 +      gtk_widget_destroy(tooltipWindow); // Release GtkWindow self-reference.
       
  2238 +      sStyleStorage[aNodeType] = style;
       
  2239 +      return style;
       
  2240 +    }
       
  2241 +    case MOZ_GTK_GRIPPER:
       
  2242 +      return GetWidgetStyleWithClass(MOZ_GTK_GRIPPER,
       
  2243 +                                     GTK_STYLE_CLASS_GRIP);
       
  2244 +    case MOZ_GTK_INFO_BAR:
       
  2245 +      return GetWidgetStyleWithClass(MOZ_GTK_INFO_BAR,
       
  2246 +                                     GTK_STYLE_CLASS_INFO);
       
  2247 +    case MOZ_GTK_SPINBUTTON_ENTRY:
       
  2248 +      return GetWidgetStyleWithClass(MOZ_GTK_SPINBUTTON,
       
  2249 +                                     GTK_STYLE_CLASS_ENTRY);
       
  2250 +    case MOZ_GTK_SCROLLED_WINDOW:
       
  2251 +      return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW,
       
  2252 +                                     GTK_STYLE_CLASS_FRAME);
       
  2253 +    case MOZ_GTK_TEXT_VIEW:
       
  2254 +      return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
       
  2255 +                                     GTK_STYLE_CLASS_VIEW);
       
  2256 +    default:
       
  2257 +      GtkWidget* widget = GetWidget(aNodeType);
       
  2258 +      MOZ_ASSERT(widget);
       
  2259 +      return gtk_widget_get_style_context(widget);
       
  2260 +  }
       
  2261  }
       
  2262  
       
  2263  void
       
  2264 @@ -245,13 +544,39 @@ ResetWidgetCache(void)
       
  2265  
       
  2266  GtkStyleContext*
       
  2267  ClaimStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection,
       
  2268 -                  StyleFlags aFlags)
       
  2269 +                  GtkStateFlags aStateFlags, StyleFlags aFlags)
       
  2270  {
       
  2271 -  GtkStyleContext* style = GetStyleInternal(aNodeType);
       
  2272 +  MOZ_ASSERT(!sStyleContextNeedsRestore);
       
  2273 +  GtkStyleContext* style;
       
  2274 +  if (gtk_check_version(3, 20, 0) != nullptr) {
       
  2275 +    style = GetWidgetStyleInternal(aNodeType);
       
  2276 +  } else {
       
  2277 +    style = GetCssNodeStyleInternal(aNodeType);
       
  2278 +  }
       
  2279  #ifdef DEBUG
       
  2280    MOZ_ASSERT(!sCurrentStyleContext);
       
  2281    sCurrentStyleContext = style;
       
  2282  #endif
       
  2283 +  GtkStateFlags oldState = gtk_style_context_get_state(style);
       
  2284 +  GtkTextDirection oldDirection = gtk_style_context_get_direction(style);
       
  2285 +  if (oldState != aStateFlags || oldDirection != aDirection) {
       
  2286 +    // From GTK 3.8, set_state() will overwrite the direction, so set
       
  2287 +    // direction after state.
       
  2288 +    gtk_style_context_set_state(style, aStateFlags);
       
  2289 +    gtk_style_context_set_direction(style, aDirection);
       
  2290 +
       
  2291 +    // This invalidate is necessary for unsaved style contexts from GtkWidgets
       
  2292 +    // in pre-3.18 GTK, because automatic invalidation of such contexts
       
  2293 +    // was delayed until a resize event runs.
       
  2294 +    //
       
  2295 +    // https://bugzilla.mozilla.org/show_bug.cgi?id=1272194#c7
       
  2296 +    //
       
  2297 +    // Avoid calling invalidate on saved contexts to avoid performing
       
  2298 +    // build_properties() (in 3.16 stylecontext.c) unnecessarily early.
       
  2299 +    if (!sStyleContextNeedsRestore) {
       
  2300 +      gtk_style_context_invalidate(style);
       
  2301 +    }
       
  2302 +  }
       
  2303    return style;
       
  2304  }
       
  2305  
       
  2306 diff -up firefox-48.0/widget/gtk/WidgetStyleCache.h.gtk3-20 firefox-48.0/widget/gtk/WidgetStyleCache.h
       
  2307 --- firefox-48.0/widget/gtk/WidgetStyleCache.h.gtk3-20	2016-07-25 22:22:07.000000000 +0200
       
  2308 +++ firefox-48.0/widget/gtk/WidgetStyleCache.h	2016-07-29 09:15:11.825285869 +0200
       
  2309 @@ -21,10 +21,24 @@ enum : StyleFlags {
       
  2310  GtkWidget*
       
  2311  GetWidget(WidgetNodeType aNodeType);
       
  2312  
       
  2313 +/*
       
  2314 + * Return a new style context based on aWidget, as a child of aParentStyle.
       
  2315 + * If aWidget still has a floating reference, then it is sunk and released.
       
  2316 + */
       
  2317 +GtkStyleContext*
       
  2318 +CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle);
       
  2319 +
       
  2320 +// CreateCSSNode is implemented for gtk >= 3.20 only.
       
  2321 +GtkStyleContext*
       
  2322 +CreateCSSNode(const char*      aName,
       
  2323 +              GtkStyleContext* aParentStyle,
       
  2324 +              GType            aType = G_TYPE_NONE);
       
  2325 +
       
  2326  // Callers must call ReleaseStyleContext() on the returned context.
       
  2327  GtkStyleContext*
       
  2328  ClaimStyleContext(WidgetNodeType aNodeType,
       
  2329                    GtkTextDirection aDirection = GTK_TEXT_DIR_LTR,
       
  2330 +                  GtkStateFlags aStateFlags = GTK_STATE_FLAG_NORMAL,
       
  2331                    StyleFlags aFlags = NO_STYLE_FLAGS);
       
  2332  void
       
  2333  ReleaseStyleContext(GtkStyleContext* style);
       
  2334