From e4e91bea579ce641148385f4922ef12b41a0baf4 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Nov 21 2018 18:35:56 +0000 Subject: Backported Wayland patches from Firefox 63, fixed crashes on display changes --- diff --git a/firefox-wayland-crash-mozbz1507475.patch b/firefox-wayland-crash-mozbz1507475.patch new file mode 100644 index 0000000..bab96bc --- /dev/null +++ b/firefox-wayland-crash-mozbz1507475.patch @@ -0,0 +1,94 @@ +diff -up firefox-63.0.3/widget/gtk/mozcontainer.cpp.mozbz1507475 firefox-63.0.3/widget/gtk/mozcontainer.cpp +--- firefox-63.0.3/widget/gtk/mozcontainer.cpp.mozbz1507475 2018-11-15 01:20:56.000000000 +0100 ++++ firefox-63.0.3/widget/gtk/mozcontainer.cpp 2018-11-21 15:41:41.858692640 +0100 +@@ -169,6 +169,8 @@ moz_container_class_init (MozContainerCl + } + + #if defined(MOZ_WAYLAND) ++static struct wl_subcompositor *subcompositor; ++ + static void + registry_handle_global (void *data, + struct wl_registry *registry, +@@ -176,9 +178,8 @@ registry_handle_global (void *data, + const char *interface, + uint32_t version) + { +- MozContainer *container = MOZ_CONTAINER(data); + if(strcmp(interface, "wl_subcompositor") == 0) { +- container->subcompositor = ++ subcompositor = + static_cast(wl_registry_bind(registry, + name, + &wl_subcompositor_interface, +@@ -197,6 +198,24 @@ static const struct wl_registry_listener + registry_handle_global, + registry_handle_global_remove + }; ++ ++struct wl_subcompositor* subcompositor_get(void) ++{ ++ if (!subcompositor) { ++ GdkDisplay *gdk_display = gdk_display_get_default(); ++ // Available as of GTK 3.8+ ++ static auto sGdkWaylandDisplayGetWlDisplay = ++ (wl_display *(*)(GdkDisplay *)) ++ dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display"); ++ ++ wl_display* display = sGdkWaylandDisplayGetWlDisplay(gdk_display); ++ wl_registry* registry = wl_display_get_registry(display); ++ wl_registry_add_listener(registry, ®istry_listener, nullptr); ++ wl_display_dispatch(display); ++ wl_display_roundtrip(display); ++ } ++ return subcompositor; ++} + #endif + + void +@@ -208,25 +227,10 @@ moz_container_init (MozContainer *contai + + #if defined(MOZ_WAYLAND) + { +- container->subcompositor = nullptr; + container->surface = nullptr; + container->subsurface = nullptr; + container->eglwindow = nullptr; + container->parent_surface_committed = false; +- +- GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container)); +- if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) { +- // Available as of GTK 3.8+ +- static auto sGdkWaylandDisplayGetWlDisplay = +- (wl_display *(*)(GdkDisplay *)) +- dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display"); +- +- wl_display* display = sGdkWaylandDisplayGetWlDisplay(gdk_display); +- wl_registry* registry = wl_display_get_registry(display); +- wl_registry_add_listener(registry, ®istry_listener, container); +- wl_display_dispatch(display); +- wl_display_roundtrip(display); +- } + } + #endif + } +@@ -298,7 +302,7 @@ moz_container_map_surface(MozContainer * + } + + container->subsurface = +- wl_subcompositor_get_subsurface (container->subcompositor, ++ wl_subcompositor_get_subsurface (subcompositor_get(), + container->surface, + gtk_surface); + gint x, y; +diff -up firefox-63.0.3/widget/gtk/mozcontainer.h.mozbz1507475 firefox-63.0.3/widget/gtk/mozcontainer.h +--- firefox-63.0.3/widget/gtk/mozcontainer.h.mozbz1507475 2018-11-15 01:20:56.000000000 +0100 ++++ firefox-63.0.3/widget/gtk/mozcontainer.h 2018-11-21 14:16:54.412397805 +0100 +@@ -69,7 +69,6 @@ struct _MozContainer + GList *children; + + #ifdef MOZ_WAYLAND +- struct wl_subcompositor *subcompositor; + struct wl_surface *surface; + struct wl_subsurface *subsurface; + struct wl_egl_window *eglwindow; diff --git a/firefox-wayland.patch b/firefox-wayland.patch index d5d1306..00b408c 100644 --- a/firefox-wayland.patch +++ b/firefox-wayland.patch @@ -1,523 +1,6 @@ -diff -up thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp.wayland thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp ---- thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp 2018-11-20 12:04:43.731787368 +0100 -@@ -24,7 +24,7 @@ static gboolean checkbox_check_state; - static gboolean notebook_has_tab_gap; - - static ScrollbarGTKMetrics sScrollbarMetrics[2]; --static ScrollbarGTKMetrics sScrollbarMetricsActive[2]; -+static ScrollbarGTKMetrics sActiveScrollbarMetrics[2]; - static ToggleGTKMetrics sCheckboxMetrics; - static ToggleGTKMetrics sRadioMetrics; - static ToolbarGTKMetrics sToolbarMetrics; -@@ -39,6 +39,28 @@ static ToolbarGTKMetrics sToolbarMetrics - #endif - - static GtkBorder -+operator-(const GtkBorder& first, const GtkBorder& second) -+{ -+ GtkBorder result; -+ result.left = first.left - second.left; -+ result.right = first.right - second.right; -+ result.top = first.top - second.top; -+ result.bottom = first.bottom - second.bottom; -+ return result; -+} -+ -+static GtkBorder -+operator+(const GtkBorder& first, const GtkBorder& second) -+{ -+ GtkBorder result; -+ result.left = first.left + second.left; -+ result.right = first.right + second.right; -+ result.top = first.top + second.top; -+ result.bottom = first.bottom + second.bottom; -+ return result; -+} -+ -+static GtkBorder - operator+=(GtkBorder& first, const GtkBorder& second) - { - first.left += second.left; -@@ -84,7 +106,7 @@ moz_gtk_add_style_border(GtkStyleContext - { - GtkBorder border; - -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); - - *left += border.left; - *right += border.right; -@@ -98,7 +120,7 @@ moz_gtk_add_style_padding(GtkStyleContex - { - GtkBorder padding; - -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - *left += padding.left; - *right += padding.right; -@@ -193,8 +215,8 @@ moz_gtk_refresh() - - sScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; - sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; -- sScrollbarMetricsActive[GTK_ORIENTATION_HORIZONTAL].initialized = false; -- sScrollbarMetricsActive[GTK_ORIENTATION_VERTICAL].initialized = false; -+ sActiveScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; -+ sActiveScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; - sCheckboxMetrics.initialized = false; - sRadioMetrics.initialized = false; - sToolbarMetrics.initialized = false; -@@ -229,8 +251,8 @@ moz_gtk_get_focus_outline_size(GtkStyleC - { - GtkBorder border; - GtkBorder padding; -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - *focus_h_width = border.left + padding.left; - *focus_v_width = border.top + padding.top; - return MOZ_GTK_SUCCESS; -@@ -688,8 +710,8 @@ calculate_button_inner_rect(GtkWidget* b - style = gtk_widget_get_style_context(button); - - /* This mirrors gtkbutton's child positioning */ -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - inner_rect->x = rect->x + border.left + padding.left; - inner_rect->y = rect->y + padding.top + border.top; -@@ -1008,19 +1030,21 @@ moz_gtk_scrollbar_thumb_paint(WidgetNode - GtkTextDirection direction) - { - GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); -+ GtkStyleContext* style = GetStyleContext(widget, direction, state_flags); -+ -+ GtkOrientation orientation = (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ? -+ GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; - - GdkRectangle rect = *aRect; -- GtkStyleContext* style = GetStyleContext(widget, direction, state_flags); -- InsetByMargin(&rect, style); - -- gtk_render_slider(style, cr, -- rect.x, -- rect.y, -- rect.width, -- rect.height, -- (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ? -- GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); -+ const ScrollbarGTKMetrics* metrics = -+ (state->depressed || state->active || state->inHover) ? -+ GetActiveScrollbarMetrics(orientation) : -+ GetScrollbarMetrics(orientation); -+ Inset(&rect, metrics->margin.thumb); - -+ gtk_render_slider(style, cr, rect.x, rect.y, rect.width, rect.height, -+ orientation); - - return MOZ_GTK_SUCCESS; - } -@@ -1217,7 +1241,7 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRect - GtkStyleContext* style) - { - gint x = rect->x, y = rect->y, width = rect->width, height = rect->height; -- int draw_focus_outline_only = state->depressed; // NS_THEME_FOCUS_OUTLINE -+ int draw_focus_outline_only = state->depressed; // StyleAppearance::FocusOutline - - if (draw_focus_outline_only) { - // Inflate the given 'rect' with the focus outline size. -@@ -1621,7 +1645,7 @@ moz_gtk_toolbar_separator_paint(cairo_t - rect->height * (end_fraction - start_fraction)); - } else { - GtkBorder padding; -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - paint_width = padding.left; - if (paint_width > rect->width) -@@ -1790,7 +1814,7 @@ moz_gtk_get_tab_thickness(GtkStyleContex - return 0; /* tabs do not overdraw the tabpanel border with "no gap" style */ - - GtkBorder border; -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); - if (border.top < 2) - return 2; /* some themes don't set ythickness correctly */ - -@@ -2127,7 +2151,7 @@ moz_gtk_menu_separator_paint(cairo_t *cr - GtkBorder padding; - - style = GetStyleContext(MOZ_GTK_MENUSEPARATOR, direction); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - x = rect->x; - y = rect->y; -@@ -2433,7 +2457,7 @@ moz_gtk_get_widget_border(WidgetNodeType - NULL); - - if (!wide_separators) { -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), - &border); - separator_width = border.left; - } -@@ -2606,13 +2630,13 @@ moz_gtk_get_tab_border(gint* left, gint* - } else { - GtkBorder margin; - -- gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin); -+ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), &margin); - *left += margin.left; - *right += margin.right; - - if (flags & MOZ_GTK_TAB_FIRST) { - style = GetStyleContext(MOZ_GTK_NOTEBOOK_HEADER, direction); -- gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin); -+ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), &margin); - *left += margin.left; - *right += margin.right; - } -@@ -2687,7 +2711,7 @@ moz_gtk_get_toolbar_separator_width(gint - "separator-width", &separator_width, - NULL); - /* Just in case... */ -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); - *size = MAX(*size, (wide_separators ? separator_width : border.left)); - return MOZ_GTK_SUCCESS; - } -@@ -2718,7 +2742,7 @@ moz_gtk_get_menu_separator_height(gint * - gint separator_height; - GtkBorder padding; - GtkStyleContext* style = GetStyleContext(MOZ_GTK_MENUSEPARATOR); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - gtk_style_context_save(style); - gtk_style_context_add_class(style, GTK_STYLE_CLASS_SEPARATOR); -@@ -2750,8 +2774,8 @@ moz_gtk_get_entry_min_height(gint* heigh - - GtkBorder border; - GtkBorder padding; -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - *height += (border.top + border.bottom + padding.top + padding.bottom); - } -@@ -2901,23 +2925,17 @@ GetToggleMetrics(bool isRadio) - return metrics; - } - --const ScrollbarGTKMetrics* --GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive) -+static void -+InitScrollbarMetrics(ScrollbarGTKMetrics* aMetrics, -+ GtkOrientation aOrientation, -+ GtkStateFlags aStateFlags) - { -- auto metrics = aActive ? &sScrollbarMetricsActive[aOrientation] : -- &sScrollbarMetrics[aOrientation]; -- if (metrics->initialized) -- return metrics; -- -- metrics->initialized = true; -- - WidgetNodeType scrollbar = aOrientation == GTK_ORIENTATION_HORIZONTAL ? - MOZ_GTK_SCROLLBAR_HORIZONTAL : MOZ_GTK_SCROLLBAR_VERTICAL; - - gboolean backward, forward, secondary_backward, secondary_forward; - GtkStyleContext* style = GetStyleContext(scrollbar, GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -+ aStateFlags); - gtk_style_context_get_style(style, - "has-backward-stepper", &backward, - "has-forward-stepper", &forward, -@@ -2938,15 +2956,15 @@ GetScrollbarMetrics(GtkOrientation aOrie - "min-slider-length", &min_slider_size, - nullptr); - -- metrics->size.thumb = -+ aMetrics->size.thumb = - SizeFromLengthAndBreadth(aOrientation, min_slider_size, slider_width); -- metrics->size.button = -+ aMetrics->size.button = - SizeFromLengthAndBreadth(aOrientation, stepper_size, slider_width); - // overall scrollbar - gint breadth = slider_width + 2 * trough_border; - // Require room for the slider in the track if we don't have buttons. - gint length = hasButtons ? 0 : min_slider_size + 2 * trough_border; -- metrics->size.scrollbar = -+ aMetrics->size.scrollbar = - SizeFromLengthAndBreadth(aOrientation, length, breadth); - - // Borders on the major axis are set on the outermost scrollbar -@@ -2956,23 +2974,24 @@ GetScrollbarMetrics(GtkOrientation aOrie - // receives mouse events, as in GTK. - // Other borders have been zero-initialized. - if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { -- metrics->border.scrollbar.left = -- metrics->border.scrollbar.right = -- metrics->border.track.top = -- metrics->border.track.bottom = trough_border; -+ aMetrics->border.scrollbar.left = -+ aMetrics->border.scrollbar.right = -+ aMetrics->border.track.top = -+ aMetrics->border.track.bottom = trough_border; - } else { -- metrics->border.scrollbar.top = -- metrics->border.scrollbar.bottom = -- metrics->border.track.left = -- metrics->border.track.right = trough_border; -+ aMetrics->border.scrollbar.top = -+ aMetrics->border.scrollbar.bottom = -+ aMetrics->border.track.left = -+ aMetrics->border.track.right = trough_border; - } - -- return metrics; -+ // We're done here for Gtk+ < 3.20... -+ return; - } - - // GTK version > 3.20 - // scrollbar -- metrics->border.scrollbar = GetMarginBorderPadding(style); -+ aMetrics->border.scrollbar = GetMarginBorderPadding(style); - - WidgetNodeType contents, track, thumb; - if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { -@@ -3003,72 +3022,102 @@ GetScrollbarMetrics(GtkOrientation aOrie - */ - - // thumb -- style = CreateStyleContextWithStates(thumb, GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -- metrics->size.thumb = GetMinMarginBox(style); -+ style = CreateStyleContextWithStates(thumb, GTK_TEXT_DIR_NONE, aStateFlags); -+ aMetrics->size.thumb = GetMinMarginBox(style); -+ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), -+ &aMetrics->margin.thumb); - g_object_unref(style); - - // track -- style = CreateStyleContextWithStates(track, GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -- metrics->border.track = GetMarginBorderPadding(style); -- MozGtkSize trackMinSize = GetMinContentBox(style) + metrics->border.track; -- MozGtkSize trackSizeForThumb = metrics->size.thumb + metrics->border.track; -+ style = CreateStyleContextWithStates(track, GTK_TEXT_DIR_NONE, aStateFlags); -+ aMetrics->border.track = GetMarginBorderPadding(style); -+ MozGtkSize trackMinSize = GetMinContentBox(style) + aMetrics->border.track; -+ MozGtkSize trackSizeForThumb = aMetrics->size.thumb + aMetrics->border.track; - g_object_unref(style); - - // button - if (hasButtons) { - style = CreateStyleContextWithStates(MOZ_GTK_SCROLLBAR_BUTTON, -- GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -- metrics->size.button = GetMinMarginBox(style); -+ GTK_TEXT_DIR_NONE, aStateFlags); -+ aMetrics->size.button = GetMinMarginBox(style); - g_object_unref(style); - } else { -- metrics->size.button = {0, 0}; -+ aMetrics->size.button = {0, 0}; - } - if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { -- metrics->size.button.Rotate(); -+ aMetrics->size.button.Rotate(); - // If the track is wider than necessary for the thumb, including when - // the buttons will cause Gecko to expand the track to fill - // available breadth, then add to the track border to prevent Gecko - // from expanding the thumb to fill available breadth. - gint extra = - std::max(trackMinSize.height, -- metrics->size.button.height) - trackSizeForThumb.height; -+ aMetrics->size.button.height) - trackSizeForThumb.height; - if (extra > 0) { - // If extra is odd, then the thumb is 0.5 pixels above - // center as in gtk_range_compute_slider_position(). -- metrics->border.track.top += extra / 2; -- metrics->border.track.bottom += extra - extra / 2; -+ aMetrics->border.track.top += extra / 2; -+ aMetrics->border.track.bottom += extra - extra / 2; - // Update size for change in border. - trackSizeForThumb.height += extra; - } - } else { - gint extra = - std::max(trackMinSize.width, -- metrics->size.button.width) - trackSizeForThumb.width; -+ aMetrics->size.button.width) - trackSizeForThumb.width; - if (extra > 0) { - // If extra is odd, then the thumb is 0.5 pixels to the left - // of center as in gtk_range_compute_slider_position(). -- metrics->border.track.left += extra / 2; -- metrics->border.track.right += extra - extra / 2; -+ aMetrics->border.track.left += extra / 2; -+ aMetrics->border.track.right += extra - extra / 2; - trackSizeForThumb.width += extra; - } - } - - style = CreateStyleContextWithStates(contents, GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -+ aStateFlags); - GtkBorder contentsBorder = GetMarginBorderPadding(style); - g_object_unref(style); - -- metrics->size.scrollbar = -- trackSizeForThumb + contentsBorder + metrics->border.scrollbar; -+ aMetrics->size.scrollbar = -+ trackSizeForThumb + contentsBorder + aMetrics->border.scrollbar; -+} -+ -+const ScrollbarGTKMetrics* -+GetScrollbarMetrics(GtkOrientation aOrientation) -+{ -+ auto metrics = &sScrollbarMetrics[aOrientation]; -+ if (!metrics->initialized) { -+ InitScrollbarMetrics(metrics, aOrientation, GTK_STATE_FLAG_NORMAL); -+ -+ // We calculate thumb margin here because it's composited from -+ // thumb class margin + difference margin between active and inactive -+ // scrollbars. It's a workaround which alows us to emulate -+ // overlay scrollbars for some Gtk+ themes (Ubuntu/Ambiance), -+ // when an inactive scrollbar thumb is smaller than the active one. -+ const ScrollbarGTKMetrics *metricsActive = -+ GetActiveScrollbarMetrics(aOrientation); -+ -+ if (metrics->size.thumb < metricsActive->size.thumb) { -+ metrics->margin.thumb += -+ (metrics->border.scrollbar + metrics->border.track) - -+ (metricsActive->border.scrollbar + metricsActive->border.track); -+ } - -- return metrics; -+ metrics->initialized = true; -+ } -+ return metrics; -+} -+ -+const ScrollbarGTKMetrics* -+GetActiveScrollbarMetrics(GtkOrientation aOrientation) -+{ -+ auto metrics = &sActiveScrollbarMetrics[aOrientation]; -+ if (!metrics->initialized) { -+ InitScrollbarMetrics(metrics, aOrientation, GTK_STATE_FLAG_PRELIGHT); -+ metrics->initialized = true; -+ } -+ return metrics; - } - - /* -@@ -3078,6 +3127,16 @@ GetScrollbarMetrics(GtkOrientation aOrie - bool - GetCSDDecorationSize(GtkWindow *aGtkWindow, GtkBorder* aDecorationSize) - { -+ // Available on GTK 3.20+. -+ static auto sGtkRenderBackgroundGetClip = -+ (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*)) -+ dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip"); -+ -+ if (!sGtkRenderBackgroundGetClip) { -+ *aDecorationSize = {0,0,0,0}; -+ return false; -+ } -+ - GtkStyleContext* context = gtk_widget_get_style_context(GTK_WIDGET(aGtkWindow)); - bool solidDecorations = gtk_style_context_has_class(context, "solid-csd"); - context = GetStyleContext(solidDecorations ? -@@ -3091,54 +3150,32 @@ GetCSDDecorationSize(GtkWindow *aGtkWind - gtk_style_context_get_padding(context, state, &padding); - *aDecorationSize += padding; - -- // Available on GTK 3.20+. -- static auto sGtkRenderBackgroundGetClip = -- (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*)) -- dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip"); - - GtkBorder margin; - gtk_style_context_get_margin(context, state, &margin); - -- GtkBorder extents = {0, 0, 0, 0}; -- if (sGtkRenderBackgroundGetClip) { -- /* Get shadow extents but combine with style margin; use the bigger value. -- */ -- GdkRectangle clip; -- sGtkRenderBackgroundGetClip(context, 0, 0, 0, 0, &clip); -- -- extents.top = -clip.y; -- extents.right = clip.width + clip.x; -- extents.bottom = clip.height + clip.y; -- extents.left = -clip.x; -- -- // Margin is used for resize grip size - it's not present on -- // popup windows. -- if (gtk_window_get_window_type(aGtkWindow) != GTK_WINDOW_POPUP) { -- extents.top = MAX(extents.top, margin.top); -- extents.right = MAX(extents.right, margin.right); -- extents.bottom = MAX(extents.bottom, margin.bottom); -- extents.left = MAX(extents.left, margin.left); -- } -- } else { -- /* If we can't get shadow extents use decoration-resize-handle instead -- * as a workaround. This is inspired by update_border_windows() -- * from gtkwindow.c although this is not 100% accurate as we emulate -- * the extents here. -- */ -- gint handle; -- gtk_widget_style_get(GetWidget(MOZ_GTK_WINDOW), -- "decoration-resize-handle", &handle, -- NULL); -- -- extents.top = handle + margin.top; -- extents.right = handle + margin.right; -- extents.bottom = handle + margin.bottom; -- extents.left = handle + margin.left; -+ /* Get shadow extents but combine with style margin; use the bigger value. -+ */ -+ GdkRectangle clip; -+ sGtkRenderBackgroundGetClip(context, 0, 0, 0, 0, &clip); -+ -+ GtkBorder extents; -+ extents.top = -clip.y; -+ extents.right = clip.width + clip.x; -+ extents.bottom = clip.height + clip.y; -+ extents.left = -clip.x; -+ -+ // Margin is used for resize grip size - it's not present on -+ // popup windows. -+ if (gtk_window_get_window_type(aGtkWindow) != GTK_WINDOW_POPUP) { -+ extents.top = MAX(extents.top, margin.top); -+ extents.right = MAX(extents.right, margin.right); -+ extents.bottom = MAX(extents.bottom, margin.bottom); -+ extents.left = MAX(extents.left, margin.left); - } - - *aDecorationSize += extents; -- -- return (sGtkRenderBackgroundGetClip != nullptr); -+ return true; - } - - /* cairo_t *cr argument has to be a system-cairo. */ diff -up thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp.wayland thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp --- thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp 2018-11-20 12:04:43.731787368 +0100 ++++ thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp 2018-11-21 13:42:00.757025666 +0100 @@ -40,7 +40,9 @@ GtkCompositorWidget::GtkCompositorWidget // Grab the window's visual and depth @@ -529,2042 +12,563 @@ diff -up thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp.wayland thunderbi Visual* visual = windowAttrs.visual; int depth = windowAttrs.depth; -@@ -50,8 +52,8 @@ GtkCompositorWidget::GtkCompositorWidget +@@ -50,8 +52,7 @@ GtkCompositorWidget::GtkCompositorWidget mXDisplay, mXWindow, visual, - depth - ); -+ depth, -+ aInitData.Shaped()); ++ depth); } mClientSize = aInitData.InitialClientSize(); } -diff -up thunderbird-60.3.0/widget/gtk/gtkdrawing.h.wayland thunderbird-60.3.0/widget/gtk/gtkdrawing.h ---- thunderbird-60.3.0/widget/gtk/gtkdrawing.h.wayland 2018-10-30 12:45:37.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/gtkdrawing.h 2018-11-20 12:04:43.731787368 +0100 -@@ -83,6 +83,9 @@ typedef struct { - GtkBorder scrollbar; - GtkBorder track; - } border; -+ struct { -+ GtkBorder thumb; -+ } margin; - } ScrollbarGTKMetrics; - - typedef struct { -@@ -502,11 +505,17 @@ moz_gtk_get_scalethumb_metrics(GtkOrient - /** - * Get the metrics in GTK pixels for a scrollbar. - * aOrientation: [IN] the scrollbar orientation -- * aActive: [IN] Metricts for scrollbar with mouse pointer over it. -- * - */ - const ScrollbarGTKMetrics* --GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive = false); -+GetScrollbarMetrics(GtkOrientation aOrientation); -+ -+/** -+ * Get the metrics in GTK pixels for a scrollbar which is active -+ * (selected by mouse pointer). -+ * aOrientation: [IN] the scrollbar orientation -+ */ -+const ScrollbarGTKMetrics* -+GetActiveScrollbarMetrics(GtkOrientation aOrientation); - - /** - * Get the desired size of a dropdown arrow button -diff -up thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp.wayland thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp ---- thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp 2018-11-20 12:04:43.732787365 +0100 -@@ -14,6 +14,7 @@ - #include "mozilla/Likely.h" - #include "mozilla/MiscEvents.h" - #include "mozilla/Preferences.h" -+#include "mozilla/Telemetry.h" - #include "mozilla/TextEventDispatcher.h" - #include "mozilla/TextEvents.h" - #include "WritingModes.h" -@@ -59,6 +60,73 @@ GetEventType(GdkEventKey* aKeyEvent) - } - } +diff -up thunderbird-60.3.0/widget/gtk/moz.build.wayland thunderbird-60.3.0/widget/gtk/moz.build +--- thunderbird-60.3.0/widget/gtk/moz.build.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/moz.build 2018-11-21 13:42:00.757025666 +0100 +@@ -123,6 +123,7 @@ include('/ipc/chromium/chromium-config.m + FINAL_LIBRARY = 'xul' -+class GetEventStateName : public nsAutoCString -+{ -+public: -+ explicit GetEventStateName(guint aState, -+ IMContextWrapper::IMContextID aIMContextID = -+ IMContextWrapper::IMContextID::eUnknown) -+ { -+ if (aState & GDK_SHIFT_MASK) { -+ AppendModifier("shift"); -+ } -+ if (aState & GDK_CONTROL_MASK) { -+ AppendModifier("control"); -+ } -+ if (aState & GDK_MOD1_MASK) { -+ AppendModifier("mod1"); -+ } -+ if (aState & GDK_MOD2_MASK) { -+ AppendModifier("mod2"); -+ } -+ if (aState & GDK_MOD3_MASK) { -+ AppendModifier("mod3"); -+ } -+ if (aState & GDK_MOD4_MASK) { -+ AppendModifier("mod4"); -+ } -+ if (aState & GDK_MOD4_MASK) { -+ AppendModifier("mod5"); -+ } -+ if (aState & GDK_MOD4_MASK) { -+ AppendModifier("mod5"); -+ } -+ switch (aIMContextID) { -+ case IMContextWrapper::IMContextID::eIBus: -+ static const guint IBUS_HANDLED_MASK = 1 << 24; -+ static const guint IBUS_IGNORED_MASK = 1 << 25; -+ if (aState & IBUS_HANDLED_MASK) { -+ AppendModifier("IBUS_HANDLED_MASK"); -+ } -+ if (aState & IBUS_IGNORED_MASK) { -+ AppendModifier("IBUS_IGNORED_MASK"); -+ } -+ break; -+ case IMContextWrapper::IMContextID::eFcitx: -+ static const guint FcitxKeyState_HandledMask = 1 << 24; -+ static const guint FcitxKeyState_IgnoredMask = 1 << 25; -+ if (aState & FcitxKeyState_HandledMask) { -+ AppendModifier("FcitxKeyState_HandledMask"); -+ } -+ if (aState & FcitxKeyState_IgnoredMask) { -+ AppendModifier("FcitxKeyState_IgnoredMask"); -+ } -+ break; -+ default: -+ break; -+ } -+ } -+ -+private: -+ void AppendModifier(const char* aModifierName) -+ { -+ if (!IsEmpty()) { -+ AppendLiteral(" + "); -+ } -+ Append(aModifierName); -+ } -+}; + LOCAL_INCLUDES += [ ++ '/layout/base', + '/layout/generic', + '/layout/xul', + '/other-licenses/atk-1.0', +diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.3.0/widget/gtk/mozcontainer.cpp +--- thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozcontainer.cpp 2018-11-21 13:42:00.757025666 +0100 +@@ -10,6 +10,7 @@ + #ifdef MOZ_WAYLAND + #include + #include ++#include + #endif + #include + #include +@@ -207,6 +208,12 @@ moz_container_init (MozContainer *contai + + #if defined(MOZ_WAYLAND) + { ++ container->subcompositor = nullptr; ++ container->surface = nullptr; ++ container->subsurface = nullptr; ++ container->eglwindow = nullptr; ++ container->parent_surface_committed = false; + - class GetWritingModeName : public nsAutoCString - { - public: -@@ -281,12 +349,17 @@ IMContextWrapper::IMContextWrapper(nsWin - , mCompositionStart(UINT32_MAX) - , mProcessingKeyEvent(nullptr) - , mCompositionState(eCompositionState_NotComposing) -+ , mIMContextID(IMContextID::eUnknown) - , mIsIMFocused(false) -+ , mFallbackToKeyEvent(false) -+ , mKeyboardEventWasDispatched(false) - , mIsDeletingSurrounding(false) - , mLayoutChanged(false) - , mSetCursorPositionOnKeyEvent(true) - , mPendingResettingIMContext(false) - , mRetrieveSurroundingSignalReceived(false) -+ , mMaybeInDeadKeySequence(false) -+ , mIsIMInAsyncKeyHandlingMode(false) - { - static bool sFirstInstance = true; - if (sFirstInstance) { -@@ -299,15 +372,101 @@ IMContextWrapper::IMContextWrapper(nsWin - Init(); + GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container)); + if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) { + // Available as of GTK 3.8+ +@@ -225,12 +232,21 @@ moz_container_init (MozContainer *contai } -+static bool -+IsIBusInSyncMode() + #if defined(MOZ_WAYLAND) ++static void ++moz_container_commited_handler(GdkFrameClock *clock, MozContainer *container) +{ -+ // See ibus_im_context_class_init() in client/gtk2/ibusimcontext.c -+ // https://github.com/ibus/ibus/blob/86963f2f94d1e4fc213b01c2bc2ba9dcf4b22219/client/gtk2/ibusimcontext.c#L610 -+ const char* env = PR_GetEnv("IBUS_ENABLE_SYNC_MODE"); -+ -+ // See _get_boolean_env() in client/gtk2/ibusimcontext.c -+ // https://github.com/ibus/ibus/blob/86963f2f94d1e4fc213b01c2bc2ba9dcf4b22219/client/gtk2/ibusimcontext.c#L520-L537 -+ if (!env) { -+ return false; -+ } -+ nsDependentCString envStr(env); -+ if (envStr.IsEmpty() || -+ envStr.EqualsLiteral("0") || -+ envStr.EqualsLiteral("false") || -+ envStr.EqualsLiteral("False") || -+ envStr.EqualsLiteral("FALSE")) { -+ return false; -+ } -+ return true; ++ container->parent_surface_committed = true; ++ g_signal_handler_disconnect(clock, ++ container->parent_surface_committed_handler); ++ container->parent_surface_committed_handler = 0; +} + -+static bool -+GetFcitxBoolEnv(const char* aEnv) -+{ -+ // See fcitx_utils_get_boolean_env in src/lib/fcitx-utils/utils.c -+ // https://github.com/fcitx/fcitx/blob/0c87840dc7d9460c2cb5feaeefec299d0d3d62ec/src/lib/fcitx-utils/utils.c#L721-L736 -+ const char* env = PR_GetEnv(aEnv); -+ if (!env) { -+ return false; -+ } -+ nsDependentCString envStr(env); -+ if (envStr.IsEmpty() || -+ envStr.EqualsLiteral("0") || -+ envStr.EqualsLiteral("false")) { + /* We want to draw to GdkWindow owned by mContainer from Compositor thread but + * Gtk+ can be used in main thread only. So we create wayland wl_surface + * and attach it as an overlay to GdkWindow. + * + * see gtk_clutter_embed_ensure_subsurface() at gtk-clutter-embed.c +-* for reference. ++ * for reference. + */ + static gboolean + moz_container_map_surface(MozContainer *container) +@@ -242,6 +258,9 @@ moz_container_map_surface(MozContainer * + static auto sGdkWaylandWindowGetWlSurface = + (wl_surface *(*)(GdkWindow *)) + dlsym(RTLD_DEFAULT, "gdk_wayland_window_get_wl_surface"); ++ static auto sGdkWindowGetFrameClock = ++ (GdkFrameClock *(*)(GdkWindow *)) ++ dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock"); + + GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container)); + if (GDK_IS_X11_DISPLAY(display)) +@@ -250,6 +269,18 @@ moz_container_map_surface(MozContainer * + if (container->subsurface && container->surface) + return true; + ++ if (!container->parent_surface_committed) { ++ if (!container->parent_surface_committed_handler) { ++ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); ++ GdkFrameClock *clock = sGdkWindowGetFrameClock(window); ++ container->parent_surface_committed_handler = ++ g_signal_connect_after(clock, "after-paint", ++ G_CALLBACK(moz_container_commited_handler), ++ container); ++ } + return false; + } -+ return true; -+} -+ -+static bool -+IsFcitxInSyncMode() -+{ -+ // See fcitx_im_context_class_init() in src/frontend/gtk2/fcitximcontext.c -+ // https://github.com/fcitx/fcitx/blob/78b98d9230dc9630e99d52e3172bdf440ffd08c4/src/frontend/gtk2/fcitximcontext.c#L395-L398 -+ return GetFcitxBoolEnv("IBUS_ENABLE_SYNC_MODE") || -+ GetFcitxBoolEnv("FCITX_ENABLE_SYNC_MODE"); -+} -+ -+nsDependentCSubstring -+IMContextWrapper::GetIMName() const -+{ -+ const char* contextIDChar = -+ gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(mContext)); -+ if (!contextIDChar) { -+ return nsDependentCSubstring(); -+ } -+ -+ nsDependentCSubstring im(contextIDChar, strlen(contextIDChar)); -+ -+ // If the context is XIM, actual engine must be specified with -+ // |XMODIFIERS=@im=foo|. -+ const char* xmodifiersChar = PR_GetEnv("XMODIFIERS"); -+ if (!im.EqualsLiteral("xim") || !xmodifiersChar) { -+ return im; -+ } -+ -+ nsDependentCString xmodifiers(xmodifiersChar); -+ int32_t atIMValueStart = xmodifiers.Find("@im=") + 4; -+ if (atIMValueStart < 4 || -+ xmodifiers.Length() <= static_cast(atIMValueStart)) { -+ return im; -+ } + -+ int32_t atIMValueEnd = -+ xmodifiers.Find("@", false, atIMValueStart); -+ if (atIMValueEnd > atIMValueStart) { -+ return nsDependentCSubstring(xmodifiersChar + atIMValueStart, -+ atIMValueEnd - atIMValueStart); -+ } -+ -+ if (atIMValueEnd == kNotFound) { -+ return nsDependentCSubstring(xmodifiersChar + atIMValueStart, -+ strlen(xmodifiersChar) - atIMValueStart); -+ } + if (!container->surface) { + struct wl_compositor *compositor; + compositor = sGdkWaylandDisplayGetWlCompositor(display); +@@ -289,8 +320,22 @@ moz_container_map_surface(MozContainer * + static void + moz_container_unmap_surface(MozContainer *container) + { ++ //g_clear_pointer(&container->eglwindow, wl_egl_window_destroy); + g_clear_pointer(&container->subsurface, wl_subsurface_destroy); + g_clear_pointer(&container->surface, wl_surface_destroy); + -+ return im; -+} ++ if (container->parent_surface_committed_handler) { ++ static auto sGdkWindowGetFrameClock = ++ (GdkFrameClock *(*)(GdkWindow *)) ++ dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock"); ++ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); ++ GdkFrameClock *clock = sGdkWindowGetFrameClock(window); + - void - IMContextWrapper::Init() - { -- MOZ_LOG(gGtkIMLog, LogLevel::Info, -- ("0x%p Init(), mOwnerWindow=0x%p", -- this, mOwnerWindow)); -- - MozContainer* container = mOwnerWindow->GetMozContainer(); -- NS_PRECONDITION(container, "container is null"); -+ MOZ_ASSERT(container, "container is null"); - GdkWindow* gdkWindow = gtk_widget_get_window(GTK_WIDGET(container)); - - // Overwrite selection colors of the window before associating the window -@@ -333,6 +492,47 @@ IMContextWrapper::Init() - G_CALLBACK(IMContextWrapper::OnStartCompositionCallback), this); - g_signal_connect(mContext, "preedit_end", - G_CALLBACK(IMContextWrapper::OnEndCompositionCallback), this); -+ nsDependentCSubstring im = GetIMName(); -+ if (im.EqualsLiteral("ibus")) { -+ mIMContextID = IMContextID::eIBus; -+ mIsIMInAsyncKeyHandlingMode = !IsIBusInSyncMode(); -+ // Although ibus has key snooper mode, it's forcibly disabled on Firefox -+ // in default settings by its whitelist since we always send key events -+ // to IME before handling shortcut keys. The whitelist can be -+ // customized with env, IBUS_NO_SNOOPER_APPS, but we don't need to -+ // support such rare cases for reducing maintenance cost. -+ mIsKeySnooped = false; -+ } else if (im.EqualsLiteral("fcitx")) { -+ mIMContextID = IMContextID::eFcitx; -+ mIsIMInAsyncKeyHandlingMode = !IsFcitxInSyncMode(); -+ // Although Fcitx has key snooper mode similar to ibus, it's also -+ // disabled on Firefox in default settings by its whitelist. The -+ // whitelist can be customized with env, IBUS_NO_SNOOPER_APPS or -+ // FCITX_NO_SNOOPER_APPS, but we don't need to support such rare cases -+ // for reducing maintenance cost. -+ mIsKeySnooped = false; -+ } else if (im.EqualsLiteral("uim")) { -+ mIMContextID = IMContextID::eUim; -+ mIsIMInAsyncKeyHandlingMode = false; -+ // We cannot know if uim uses key snooper since it's build option of -+ // uim. Therefore, we need to retrieve the consideration from the -+ // pref for making users and distributions allowed to choose their -+ // preferred value. -+ mIsKeySnooped = -+ Preferences::GetBool("intl.ime.hack.uim.using_key_snooper", true); -+ } else if (im.EqualsLiteral("scim")) { -+ mIMContextID = IMContextID::eScim; -+ mIsIMInAsyncKeyHandlingMode = false; -+ mIsKeySnooped = false; -+ } else if (im.EqualsLiteral("iiim")) { -+ mIMContextID = IMContextID::eIIIMF; -+ mIsIMInAsyncKeyHandlingMode = false; -+ mIsKeySnooped = false; -+ } else { -+ mIMContextID = IMContextID::eUnknown; -+ mIsIMInAsyncKeyHandlingMode = false; -+ mIsKeySnooped = false; ++ g_signal_handler_disconnect(clock, ++ container->parent_surface_committed_handler); ++ container->parent_surface_committed_handler = 0; + } - - // Simple context - if (sUseSimpleContext) { -@@ -361,6 +561,18 @@ IMContextWrapper::Init() - // Dummy context - mDummyContext = gtk_im_multicontext_new(); - gtk_im_context_set_client_window(mDummyContext, gdkWindow); -+ -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p Init(), mOwnerWindow=%p, mContext=%p (im=\"%s\"), " -+ "mIsIMInAsyncKeyHandlingMode=%s, mIsKeySnooped=%s, " -+ "mSimpleContext=%p, mDummyContext=%p, " -+ "gtk_im_multicontext_get_context_id()=\"%s\", " -+ "PR_GetEnv(\"XMODIFIERS\")=\"%s\"", -+ this, mOwnerWindow, mContext, nsAutoCString(im).get(), -+ ToChar(mIsIMInAsyncKeyHandlingMode), ToChar(mIsKeySnooped), -+ mSimpleContext, mDummyContext, -+ gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(mContext)), -+ PR_GetEnv("XMODIFIERS"))); ++ container->parent_surface_committed = false; } - /* static */ -@@ -469,7 +681,7 @@ IMContextWrapper::OnDestroyWindow(nsWind - "mOwnerWindow=0x%p, mLastFocusedModule=0x%p", - this, aWindow, mLastFocusedWindow, mOwnerWindow, sLastFocusedContext)); - -- NS_PRECONDITION(aWindow, "aWindow must not be null"); -+ MOZ_ASSERT(aWindow, "aWindow must not be null"); - - if (mLastFocusedWindow == aWindow) { - EndIMEComposition(aWindow); -@@ -524,46 +736,46 @@ IMContextWrapper::OnDestroyWindow(nsWind - mOwnerWindow = nullptr; - mLastFocusedWindow = nullptr; - mInputContext.mIMEState.mEnabled = IMEState::DISABLED; -+ mPostingKeyEvents.Clear(); - - MOZ_LOG(gGtkIMLog, LogLevel::Debug, - ("0x%p OnDestroyWindow(), succeeded, Completely destroyed", - this)); - } + #endif +@@ -555,8 +605,40 @@ moz_container_get_wl_surface(MozContaine + return nullptr; --// Work around gtk bug http://bugzilla.gnome.org/show_bug.cgi?id=483223: --// (and the similar issue of GTK+ IIIM) --// The GTK+ XIM and IIIM modules register handlers for the "closed" signal --// on the display, but: --// * The signal handlers are not disconnected when the module is unloaded. --// --// The GTK+ XIM module has another problem: --// * When the signal handler is run (with the module loaded) it tries --// XFree (and fails) on a pointer that did not come from Xmalloc. --// --// To prevent these modules from being unloaded, use static variables to --// hold ref of GtkIMContext class. --// For GTK+ XIM module, to prevent the signal handler from being run, --// find the signal handlers and remove them. --// --// GtkIMContextXIMs share XOpenIM connections and display closed signal --// handlers (where possible). -- - void - IMContextWrapper::PrepareToDestroyContext(GtkIMContext* aContext) - { -- GtkIMContext *slave = nullptr; //TODO GTK3 -- if (!slave) { -- return; -- } -- -- GType slaveType = G_TYPE_FROM_INSTANCE(slave); -- const gchar *im_type_name = g_type_name(slaveType); -- if (strcmp(im_type_name, "GtkIMContextIIIM") == 0) { -- // Add a reference to prevent the IIIM module from being unloaded -- static gpointer gtk_iiim_context_class = -- g_type_class_ref(slaveType); -- // Mute unused variable warning: -- (void)gtk_iiim_context_class; -+ if (mIMContextID == IMContextID::eIIIMF) { -+ // IIIM module registers handlers for the "closed" signal on the -+ // display, but the signal handler is not disconnected when the module -+ // is unloaded. To prevent the module from being unloaded, use static -+ // variable to hold reference of slave context class declared by IIIM. -+ // Note that this does not grab any instance, it grabs the "class". -+ static gpointer sGtkIIIMContextClass = nullptr; -+ if (!sGtkIIIMContextClass) { -+ // We retrieved slave context class with g_type_name() and actual -+ // slave context instance when our widget was GTK2. That must be -+ // _GtkIMContext::priv::slave in GTK3. However, _GtkIMContext::priv -+ // is an opacity struct named _GtkIMMulticontextPrivate, i.e., it's -+ // not exposed by GTK3. Therefore, we cannot access the instance -+ // safely. So, we need to retrieve the slave context class with -+ // g_type_from_name("GtkIMContextIIIM") directly (anyway, we needed -+ // to compare the class name with "GtkIMContextIIIM"). -+ GType IIMContextType = g_type_from_name("GtkIMContextIIIM"); -+ if (IIMContextType) { -+ sGtkIIIMContextClass = g_type_class_ref(IIMContextType); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p PrepareToDestroyContext(), added to reference to " -+ "GtkIMContextIIIM class to prevent it from being unloaded", -+ this)); -+ } else { -+ MOZ_LOG(gGtkIMLog, LogLevel::Error, -+ ("0x%p PrepareToDestroyContext(), FAILED to prevent the " -+ "IIIM module from being uploaded", -+ this)); + moz_container_map_surface(container); ++ // Set the scale factor for the buffer right after we create it. ++ if (container->surface) { ++ static auto sGdkWindowGetScaleFactorPtr = (gint (*)(GdkWindow*)) ++ dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor"); ++ if (sGdkWindowGetScaleFactorPtr && window) { ++ gint scaleFactor = (*sGdkWindowGetScaleFactorPtr)(window); ++ wl_surface_set_buffer_scale(container->surface, scaleFactor); + } + } } - } - -@@ -603,9 +815,9 @@ IMContextWrapper::OnBlurWindow(nsWindow* - bool - IMContextWrapper::OnKeyEvent(nsWindow* aCaller, - GdkEventKey* aEvent, -- bool aKeyDownEventWasSent /* = false */) -+ bool aKeyboardEventWasDispatched /* = false */) - { -- NS_PRECONDITION(aEvent, "aEvent must be non-null"); -+ MOZ_ASSERT(aEvent, "aEvent must be non-null"); - - if (!mInputContext.mIMEState.MaybeEditable() || - MOZ_UNLIKELY(IsDestroyed())) { -@@ -613,13 +825,24 @@ IMContextWrapper::OnKeyEvent(nsWindow* a - } - - MOZ_LOG(gGtkIMLog, LogLevel::Info, -- ("0x%p OnKeyEvent(aCaller=0x%p, aKeyDownEventWasSent=%s), " -- "mCompositionState=%s, current context=0x%p, active context=0x%p, " -- "aEvent(0x%p): { type=%s, keyval=%s, unicode=0x%X }", -- this, aCaller, ToChar(aKeyDownEventWasSent), -+ ("0x%p OnKeyEvent(aCaller=0x%p, " -+ "aEvent(0x%p): { type=%s, keyval=%s, unicode=0x%X, state=%s, " -+ "time=%u, hardware_keycode=%u, group=%u }, " -+ "aKeyboardEventWasDispatched=%s)", -+ this, aCaller, aEvent, GetEventType(aEvent), -+ gdk_keyval_name(aEvent->keyval), -+ gdk_keyval_to_unicode(aEvent->keyval), -+ GetEventStateName(aEvent->state, mIMContextID).get(), -+ aEvent->time, aEvent->hardware_keycode, aEvent->group, -+ ToChar(aKeyboardEventWasDispatched))); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnKeyEvent(), mMaybeInDeadKeySequence=%s, " -+ "mCompositionState=%s, current context=%p, active context=%p, " -+ "mIMContextID=%s, mIsIMInAsyncKeyHandlingMode=%s", -+ this, ToChar(mMaybeInDeadKeySequence), - GetCompositionStateName(), GetCurrentContext(), GetActiveContext(), -- aEvent, GetEventType(aEvent), gdk_keyval_name(aEvent->keyval), -- gdk_keyval_to_unicode(aEvent->keyval))); -+ GetIMContextIDName(mIMContextID), -+ ToChar(mIsIMInAsyncKeyHandlingMode))); - - if (aCaller != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Error, -@@ -644,49 +867,158 @@ IMContextWrapper::OnKeyEvent(nsWindow* a - mSetCursorPositionOnKeyEvent = false; - } -- mKeyDownEventWasSent = aKeyDownEventWasSent; -- mFilterKeyEvent = true; -+ // Let's support dead key event even if active keyboard layout also -+ // supports complicated composition like CJK IME. -+ bool isDeadKey = -+ KeymapWrapper::ComputeDOMKeyNameIndex(aEvent) == KEY_NAME_INDEX_Dead; -+ mMaybeInDeadKeySequence |= isDeadKey; -+ -+ // If current context is mSimpleContext, both ibus and fcitx handles key -+ // events synchronously. So, only when current context is mContext which -+ // is GtkIMMulticontext, the key event may be handled by IME asynchronously. -+ bool maybeHandledAsynchronously = -+ mIsIMInAsyncKeyHandlingMode && currentContext == mContext; -+ -+ // If IM is ibus or fcitx and it handles key events asynchronously, -+ // they mark aEvent->state as "handled by me" when they post key event -+ // to another process. Unfortunately, we need to check this hacky -+ // flag because it's difficult to store all pending key events by -+ // an array or a hashtable. -+ if (maybeHandledAsynchronously) { -+ switch (mIMContextID) { -+ case IMContextID::eIBus: -+ // ibus won't send back key press events in a dead key sequcne. -+ if (mMaybeInDeadKeySequence && aEvent->type == GDK_KEY_PRESS) { -+ maybeHandledAsynchronously = false; -+ break; -+ } -+ // ibus handles key events synchronously if focused editor is -+ // or |ime-mode: disabled;|. -+ if (mInputContext.mIMEState.mEnabled == IMEState::PASSWORD) { -+ maybeHandledAsynchronously = false; -+ break; -+ } -+ // See src/ibustypes.h -+ static const guint IBUS_IGNORED_MASK = 1 << 25; -+ // If IBUS_IGNORED_MASK was set to aEvent->state, the event -+ // has already been handled by another process and it wasn't -+ // used by IME. -+ if (aEvent->state & IBUS_IGNORED_MASK) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnKeyEvent(), aEvent->state has " -+ "IBUS_IGNORED_MASK, so, it won't be handled " -+ "asynchronously anymore. Removing posted events from " -+ "the queue", -+ this)); -+ maybeHandledAsynchronously = false; -+ mPostingKeyEvents.RemoveEvent(aEvent); -+ break; -+ } -+ break; -+ case IMContextID::eFcitx: -+ // fcitx won't send back key press events in a dead key sequcne. -+ if (mMaybeInDeadKeySequence && aEvent->type == GDK_KEY_PRESS) { -+ maybeHandledAsynchronously = false; -+ break; -+ } -+ -+ // fcitx handles key events asynchronously even if focused -+ // editor cannot use IME actually. -+ -+ // See src/lib/fcitx-utils/keysym.h -+ static const guint FcitxKeyState_IgnoredMask = 1 << 25; -+ // If FcitxKeyState_IgnoredMask was set to aEvent->state, -+ // the event has already been handled by another process and -+ // it wasn't used by IME. -+ if (aEvent->state & FcitxKeyState_IgnoredMask) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnKeyEvent(), aEvent->state has " -+ "FcitxKeyState_IgnoredMask, so, it won't be handled " -+ "asynchronously anymore. Removing posted events from " -+ "the queue", -+ this)); -+ maybeHandledAsynchronously = false; -+ mPostingKeyEvents.RemoveEvent(aEvent); -+ break; -+ } -+ break; -+ default: -+ MOZ_ASSERT_UNREACHABLE("IME may handle key event " -+ "asyncrhonously, but not yet confirmed if it comes agian " -+ "actually"); -+ } -+ } + return container->surface; + } + -+ mKeyboardEventWasDispatched = aKeyboardEventWasDispatched; -+ mFallbackToKeyEvent = false; - mProcessingKeyEvent = aEvent; - gboolean isFiltered = - gtk_im_context_filter_keypress(currentContext, aEvent); -- mProcessingKeyEvent = nullptr; - -- // We filter the key event if the event was not committed (because -- // it's probably part of a composition) or if the key event was -- // committed _and_ changed. This way we still let key press -- // events go through as simple key press events instead of -- // composed characters. -- bool filterThisEvent = isFiltered && mFilterKeyEvent; -- -- if (IsComposingOnCurrentContext() && !isFiltered) { -- if (aEvent->type == GDK_KEY_PRESS) { -- if (!mDispatchedCompositionString.IsEmpty()) { -- // If there is composition string, we shouldn't dispatch -- // any keydown events during composition. -- filterThisEvent = true; -- } else { -- // A Hangul input engine for SCIM doesn't emit preedit_end -- // signal even when composition string becomes empty. On the -- // other hand, we should allow to make composition with empty -- // string for other languages because there *might* be such -- // IM. For compromising this issue, we should dispatch -- // compositionend event, however, we don't need to reset IM -- // actually. -- DispatchCompositionCommitEvent(currentContext, &EmptyString()); -- filterThisEvent = false; -- } -- } else { -- // Key release event may not be consumed by IM, however, we -- // shouldn't dispatch any keyup event during composition. -- filterThisEvent = true; -+ // The caller of this shouldn't handle aEvent anymore if we've dispatched -+ // composition events or modified content with other events. -+ bool filterThisEvent = isFiltered && !mFallbackToKeyEvent; -+ -+ if (IsComposingOnCurrentContext() && !isFiltered && -+ aEvent->type == GDK_KEY_PRESS && -+ mDispatchedCompositionString.IsEmpty()) { -+ // A Hangul input engine for SCIM doesn't emit preedit_end -+ // signal even when composition string becomes empty. On the -+ // other hand, we should allow to make composition with empty -+ // string for other languages because there *might* be such -+ // IM. For compromising this issue, we should dispatch -+ // compositionend event, however, we don't need to reset IM -+ // actually. -+ // NOTE: Don't dispatch key events as "processed by IME" since -+ // we need to dispatch keyboard events as IME wasn't handled it. -+ mProcessingKeyEvent = nullptr; -+ DispatchCompositionCommitEvent(currentContext, &EmptyString()); -+ mProcessingKeyEvent = aEvent; -+ // In this case, even though we handle the keyboard event here, -+ // but we should dispatch keydown event as -+ filterThisEvent = false; -+ } -+ -+ if (filterThisEvent && !mKeyboardEventWasDispatched) { -+ // If IME handled the key event but we've not dispatched eKeyDown nor -+ // eKeyUp event yet, we need to dispatch here unless the key event is -+ // now being handled by other IME process. -+ if (!maybeHandledAsynchronously) { -+ MaybeDispatchKeyEventAsProcessedByIME(eVoidEvent); -+ // Be aware, the widget might have been gone here. -+ } -+ // If we need to wait reply from IM, IM may send some signals to us -+ // without sending the key event again. In such case, we need to -+ // dispatch keyboard events with a copy of aEvent. Therefore, we -+ // need to use information of this key event to dispatch an KeyDown -+ // or eKeyUp event later. -+ else { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnKeyEvent(), putting aEvent into the queue...", -+ this)); -+ mPostingKeyEvents.PutEvent(aEvent); - } - } - -+ mProcessingKeyEvent = nullptr; ++struct wl_egl_window * ++moz_container_get_wl_egl_window(MozContainer *container) ++{ /* ++ if (!container->eglwindow) { ++ struct wl_surface *wlsurf = moz_container_get_wl_surface(container); ++ if (!wlsurf) ++ return nullptr; + -+ if (aEvent->type == GDK_KEY_PRESS && !filterThisEvent) { -+ // If the key event hasn't been handled by active IME nor keyboard -+ // layout, we can assume that the dead key sequence has been or was -+ // ended. Note that we should not reset it when the key event is -+ // GDK_KEY_RELEASE since it may not be filtered by active keyboard -+ // layout even in composition. -+ mMaybeInDeadKeySequence = false; ++ GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container)); ++ container->eglwindow ++ = wl_egl_window_create(wlsurf, ++ gdk_window_get_width(window), ++ gdk_window_get_height(window)); + } ++ return container->eglwindow;*/ return nullptr; ++} + - MOZ_LOG(gGtkIMLog, LogLevel::Debug, - ("0x%p OnKeyEvent(), succeeded, filterThisEvent=%s " -- "(isFiltered=%s, mFilterKeyEvent=%s), mCompositionState=%s", -+ "(isFiltered=%s, mFallbackToKeyEvent=%s, " -+ "maybeHandledAsynchronously=%s), mCompositionState=%s, " -+ "mMaybeInDeadKeySequence=%s", - this, ToChar(filterThisEvent), ToChar(isFiltered), -- ToChar(mFilterKeyEvent), GetCompositionStateName())); -+ ToChar(mFallbackToKeyEvent), ToChar(maybeHandledAsynchronously), -+ GetCompositionStateName(), ToChar(mMaybeInDeadKeySequence))); - - return filterThisEvent; - } -@@ -1005,6 +1337,10 @@ IMContextWrapper::Focus() ++gboolean ++moz_container_has_wl_egl_window(MozContainer *container) ++{ ++ return container->eglwindow ? true : false; ++} + #endif +diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.h.wayland thunderbird-60.3.0/widget/gtk/mozcontainer.h +--- thunderbird-60.3.0/widget/gtk/mozcontainer.h.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozcontainer.h 2018-11-21 13:42:00.757025666 +0100 +@@ -72,6 +72,9 @@ struct _MozContainer + struct wl_subcompositor *subcompositor; + struct wl_surface *surface; + struct wl_subsurface *subsurface; ++ struct wl_egl_window *eglwindow; ++ gboolean parent_surface_committed; ++ gulong parent_surface_committed_handler; + #endif + }; - sLastFocusedContext = this; +@@ -95,6 +98,8 @@ void moz_container_move ( -+ // Forget all posted key events when focus is moved since they shouldn't -+ // be fired in different editor. -+ mPostingKeyEvents.Clear(); -+ - gtk_im_context_focus_in(currentContext); - mIsIMFocused = true; - mSetCursorPositionOnKeyEvent = true; -@@ -1400,6 +1736,7 @@ IMContextWrapper::OnCommitCompositionNat + #ifdef MOZ_WAYLAND + struct wl_surface* moz_container_get_wl_surface(MozContainer *container); ++struct wl_egl_window* moz_container_get_wl_egl_window(MozContainer *container); ++gboolean moz_container_has_wl_egl_window(MozContainer *container); + #endif + + #endif /* __MOZ_CONTAINER_H__ */ +diff -up thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c +--- thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c 2018-11-21 13:42:00.757025666 +0100 +@@ -135,6 +135,8 @@ STUB(gdk_x11_get_xatom_by_name) + STUB(gdk_x11_get_xatom_by_name_for_display) + STUB(gdk_x11_lookup_xdisplay) + STUB(gdk_x11_screen_get_xscreen) ++STUB(gdk_x11_screen_get_screen_number) ++STUB(gdk_x11_screen_lookup_visual) + STUB(gdk_x11_screen_supports_net_wm_hint) + STUB(gdk_x11_visual_get_xvisual) + STUB(gdk_x11_window_foreign_new_for_display) +@@ -266,6 +268,7 @@ STUB(gtk_im_context_set_client_window) + STUB(gtk_im_context_set_cursor_location) + STUB(gtk_im_context_set_surrounding) + STUB(gtk_im_context_simple_new) ++STUB(gtk_im_multicontext_get_context_id) + STUB(gtk_im_multicontext_get_type) + STUB(gtk_im_multicontext_new) + STUB(gtk_info_bar_get_type) +diff -up thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c.wayland thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c +--- thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c 2018-11-21 13:42:00.758025661 +0100 +@@ -271,3 +271,21 @@ wl_log_set_handler_client(wl_log_func_t { - const gchar emptyStr = 0; - const gchar *commitString = aUTF8Char ? aUTF8Char : &emptyStr; -+ NS_ConvertUTF8toUTF16 utf16CommitString(commitString); - - MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("0x%p OnCommitCompositionNative(aContext=0x%p), " -@@ -1422,7 +1759,7 @@ IMContextWrapper::OnCommitCompositionNat - // signal, we would dispatch compositionstart, text, compositionend - // events with empty string. Of course, they are unnecessary events - // for Web applications and our editor. -- if (!IsComposingOn(aContext) && !commitString[0]) { -+ if (!IsComposingOn(aContext) && utf16CommitString.IsEmpty()) { - MOZ_LOG(gGtkIMLog, LogLevel::Warning, - ("0x%p OnCommitCompositionNative(), Warning, does nothing " - "because has not started composition and commit string is empty", -@@ -1431,11 +1768,14 @@ IMContextWrapper::OnCommitCompositionNat - } + } - // If IME doesn't change their keyevent that generated this commit, -- // don't send it through XIM - just send it as a normal key press -- // event. -+ // we should treat that IME didn't handle the key event because -+ // web applications want to receive "keydown" and "keypress" event -+ // in such case. - // NOTE: While a key event is being handled, this might be caused on - // current context. Otherwise, this may be caused on active context. -- if (!IsComposingOn(aContext) && mProcessingKeyEvent && -+ if (!IsComposingOn(aContext) && -+ mProcessingKeyEvent && -+ mProcessingKeyEvent->type == GDK_KEY_PRESS && - aContext == GetCurrentContext()) { - char keyval_utf8[8]; /* should have at least 6 bytes of space */ - gint keyval_utf8_len; -@@ -1445,12 +1785,80 @@ IMContextWrapper::OnCommitCompositionNat - keyval_utf8_len = g_unichar_to_utf8(keyval_unicode, keyval_utf8); - keyval_utf8[keyval_utf8_len] = '\0'; - -+ // If committing string is exactly same as a character which is -+ // produced by the key, eKeyDown and eKeyPress event should be -+ // dispatched by the caller of OnKeyEvent() normally. Note that -+ // mMaybeInDeadKeySequence will be set to false by OnKeyEvent() -+ // since we set mFallbackToKeyEvent to true here. - if (!strcmp(commitString, keyval_utf8)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("0x%p OnCommitCompositionNative(), " - "we'll send normal key event", - this)); -- mFilterKeyEvent = false; -+ mFallbackToKeyEvent = true; -+ return; -+ } ++MOZ_EXPORT struct wl_egl_window * ++wl_egl_window_create(struct wl_surface *surface, ++ int width, int height) ++{ ++ return NULL; ++} + -+ // If we're in a dead key sequence, commit string is a character in -+ // the BMP and mProcessingKeyEvent produces some characters but it's -+ // not same as committing string, we should dispatch an eKeyPress -+ // event from here. -+ WidgetKeyboardEvent keyDownEvent(true, eKeyDown, -+ mLastFocusedWindow); -+ KeymapWrapper::InitKeyEvent(keyDownEvent, mProcessingKeyEvent, false); -+ if (mMaybeInDeadKeySequence && -+ utf16CommitString.Length() == 1 && -+ keyDownEvent.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) { -+ mKeyboardEventWasDispatched = true; -+ // Anyway, we're not in dead key sequence anymore. -+ mMaybeInDeadKeySequence = false; -+ -+ RefPtr dispatcher = GetTextEventDispatcher(); -+ nsresult rv = dispatcher->BeginNativeInputTransaction(); -+ if (NS_WARN_IF(NS_FAILED(rv))) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Error, -+ ("0x%p OnCommitCompositionNative(), FAILED, " -+ "due to BeginNativeInputTransaction() failure", -+ this)); -+ return; -+ } ++MOZ_EXPORT void ++wl_egl_window_destroy(struct wl_egl_window *egl_window) ++{ ++} + -+ // First, dispatch eKeyDown event. -+ keyDownEvent.mKeyValue = utf16CommitString; -+ nsEventStatus status = nsEventStatus_eIgnore; -+ bool dispatched = -+ dispatcher->DispatchKeyboardEvent(eKeyDown, keyDownEvent, -+ status, mProcessingKeyEvent); -+ if (!dispatched || status == nsEventStatus_eConsumeNoDefault) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnCommitCompositionNative(), " -+ "doesn't dispatch eKeyPress event because the preceding " -+ "eKeyDown event was not dispatched or was consumed", -+ this)); -+ return; -+ } -+ if (mLastFocusedWindow != keyDownEvent.mWidget || -+ mLastFocusedWindow->Destroyed()) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p OnCommitCompositionNative(), Warning, " -+ "stop dispatching eKeyPress event because the preceding " -+ "eKeyDown event caused changing focused widget or " -+ "destroyed", -+ this)); -+ return; -+ } -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnCommitCompositionNative(), " -+ "dispatched eKeyDown event for the committed character", -+ this)); -+ -+ // Next, dispatch eKeyPress event. -+ dispatcher->MaybeDispatchKeypressEvents(keyDownEvent, status, -+ mProcessingKeyEvent); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnCommitCompositionNative(), " -+ "dispatched eKeyPress event for the committed character", -+ this)); - return; - } - } -@@ -1470,7 +1878,7 @@ IMContextWrapper::GetCompositionString(G - gtk_im_context_get_preedit_string(aContext, &preedit_string, - &feedback_list, &cursor_pos); - if (preedit_string && *preedit_string) { -- CopyUTF8toUTF16(preedit_string, aCompositionString); -+ CopyUTF8toUTF16(MakeStringSpan(preedit_string), aCompositionString); - } else { - aCompositionString.Truncate(); ++MOZ_EXPORT void ++wl_egl_window_resize(struct wl_egl_window *egl_window, ++ int width, int height, ++ int dx, int dy) ++{ ++} +diff -up thunderbird-60.3.0/widget/gtk/nsClipboard.cpp.wayland thunderbird-60.3.0/widget/gtk/nsClipboard.cpp +--- thunderbird-60.3.0/widget/gtk/nsClipboard.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsClipboard.cpp 2018-11-21 13:42:00.758025661 +0100 +@@ -671,11 +671,9 @@ void ConvertHTMLtoUCS2(const char* data, + *unicodeData = + reinterpret_cast + (moz_xmalloc((outUnicodeLen + sizeof('\0')) * sizeof(char16_t))); +- if (*unicodeData) { +- memcpy(*unicodeData, data + sizeof(char16_t), +- outUnicodeLen * sizeof(char16_t)); +- (*unicodeData)[outUnicodeLen] = '\0'; +- } ++ memcpy(*unicodeData, data + sizeof(char16_t), ++ outUnicodeLen * sizeof(char16_t)); ++ (*unicodeData)[outUnicodeLen] = '\0'; + } else if (charset.EqualsLiteral("UNKNOWN")) { + outUnicodeLen = 0; + return; +@@ -701,27 +699,25 @@ void ConvertHTMLtoUCS2(const char* data, + if (needed.value()) { + *unicodeData = reinterpret_cast( + moz_xmalloc((needed.value() + 1) * sizeof(char16_t))); +- if (*unicodeData) { +- uint32_t result; +- size_t read; +- size_t written; +- bool hadErrors; +- Tie(result, read, written, hadErrors) = +- decoder->DecodeToUTF16(AsBytes(MakeSpan(data, dataLength)), +- MakeSpan(*unicodeData, needed.value()), +- true); +- MOZ_ASSERT(result == kInputEmpty); +- MOZ_ASSERT(read == size_t(dataLength)); +- MOZ_ASSERT(written <= needed.value()); +- Unused << hadErrors; ++ uint32_t result; ++ size_t read; ++ size_t written; ++ bool hadErrors; ++ Tie(result, read, written, hadErrors) = ++ decoder->DecodeToUTF16(AsBytes(MakeSpan(data, dataLength)), ++ MakeSpan(*unicodeData, needed.value()), ++ true); ++ MOZ_ASSERT(result == kInputEmpty); ++ MOZ_ASSERT(read == size_t(dataLength)); ++ MOZ_ASSERT(written <= needed.value()); ++ Unused << hadErrors; + #ifdef DEBUG_CLIPBOARD +- if (read != dataLength) +- printf("didn't consume all the bytes\n"); ++ if (read != dataLength) ++ printf("didn't consume all the bytes\n"); + #endif +- outUnicodeLen = written; +- // null terminate. +- (*unicodeData)[outUnicodeLen] = '\0'; +- } ++ outUnicodeLen = written; ++ // null terminate. ++ (*unicodeData)[outUnicodeLen] = '\0'; + } // if valid length } -@@ -1485,6 +1893,173 @@ IMContextWrapper::GetCompositionString(G } +diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp +--- thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp 2018-11-21 13:42:00.758025661 +0100 +@@ -23,6 +23,7 @@ + #include "mozilla/Services.h" + #include "mozilla/RefPtr.h" + #include "mozilla/TimeStamp.h" ++#include "nsDragService.h" - bool -+IMContextWrapper::MaybeDispatchKeyEventAsProcessedByIME( -+ EventMessage aFollowingEvent) + #include "imgIContainer.h" + +@@ -46,6 +47,44 @@ nsRetrievalContextWayland::sTextMimeType + "COMPOUND_TEXT" + }; + ++static inline GdkDragAction ++wl_to_gdk_actions(uint32_t dnd_actions) +{ -+ if (!mLastFocusedWindow) { -+ return false; -+ } ++ GdkDragAction actions = GdkDragAction(0); + -+ if (!mIsKeySnooped && -+ ((!mProcessingKeyEvent && mPostingKeyEvents.IsEmpty()) || -+ (mProcessingKeyEvent && mKeyboardEventWasDispatched))) { -+ return true; -+ } ++ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) ++ actions = GdkDragAction(actions|GDK_ACTION_COPY); ++ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) ++ actions = GdkDragAction(actions|GDK_ACTION_MOVE); + -+ // A "keydown" or "keyup" event handler may change focus with the -+ // following event. In such case, we need to cancel this composition. -+ // So, we need to store IM context now because mComposingContext may be -+ // overwritten with different context if calling this method recursively. -+ // Note that we don't need to grab the context here because |context| -+ // will be used only for checking if it's same as mComposingContext. -+ GtkIMContext* oldCurrentContext = GetCurrentContext(); -+ GtkIMContext* oldComposingContext = mComposingContext; ++ return actions; ++} + -+ RefPtr lastFocusedWindow(mLastFocusedWindow); ++static inline uint32_t ++gdk_to_wl_actions(GdkDragAction action) ++{ ++ uint32_t dnd_actions = 0; + -+ if (mProcessingKeyEvent || !mPostingKeyEvents.IsEmpty()) { -+ if (mProcessingKeyEvent) { -+ mKeyboardEventWasDispatched = true; -+ } -+ // If we're not handling a key event synchronously, the signal may be -+ // sent by IME without sending key event to us. In such case, we -+ // should dispatch keyboard event for the last key event which was -+ // posted to other IME process. -+ GdkEventKey* sourceEvent = -+ mProcessingKeyEvent ? mProcessingKeyEvent : -+ mPostingKeyEvents.GetFirstEvent(); -+ -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(" -+ "aFollowingEvent=%s), dispatch %s %s " -+ "event: { type=%s, keyval=%s, unicode=0x%X, state=%s, " -+ "time=%u, hardware_keycode=%u, group=%u }", -+ this, ToChar(aFollowingEvent), -+ ToChar(sourceEvent->type == GDK_KEY_PRESS ? eKeyDown : eKeyUp), -+ mProcessingKeyEvent ? "processing" : "posted", -+ GetEventType(sourceEvent), gdk_keyval_name(sourceEvent->keyval), -+ gdk_keyval_to_unicode(sourceEvent->keyval), -+ GetEventStateName(sourceEvent->state, mIMContextID).get(), -+ sourceEvent->time, sourceEvent->hardware_keycode, -+ sourceEvent->group)); -+ -+ // Let's dispatch eKeyDown event or eKeyUp event now. Note that only -+ // when we're not in a dead key composition, we should mark the -+ // eKeyDown and eKeyUp event as "processed by IME" since we should -+ // expose raw keyCode and key value to web apps the key event is a -+ // part of a dead key sequence. -+ // FYI: We should ignore if default of preceding keydown or keyup -+ // event is prevented since even on the other browsers, web -+ // applications cannot cancel the following composition event. -+ // Spec bug: https://github.com/w3c/uievents/issues/180 -+ bool isCancelled; -+ lastFocusedWindow->DispatchKeyDownOrKeyUpEvent(sourceEvent, -+ !mMaybeInDeadKeySequence, -+ &isCancelled); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), keydown or keyup " -+ "event is dispatched", -+ this)); -+ -+ if (!mProcessingKeyEvent) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), removing first " -+ "event from the queue", -+ this)); -+ mPostingKeyEvents.RemoveEvent(sourceEvent); -+ } -+ } else { -+ MOZ_ASSERT(mIsKeySnooped); -+ // Currently, we support key snooper mode of uim only. -+ MOZ_ASSERT(mIMContextID == IMContextID::eUim); -+ // uim sends "preedit_start" signal and "preedit_changed" separately -+ // at starting composition, "commit" and "preedit_end" separately at -+ // committing composition. -+ -+ // Currently, we should dispatch only fake eKeyDown event because -+ // we cannot decide which is the last signal of each key operation -+ // and Chromium also dispatches only "keydown" event in this case. -+ bool dispatchFakeKeyDown = false; -+ switch (aFollowingEvent) { -+ case eCompositionStart: -+ case eCompositionCommit: -+ case eCompositionCommitAsIs: -+ dispatchFakeKeyDown = true; -+ break; -+ // XXX Unfortunately, I don't have a good idea to prevent to -+ // dispatch redundant eKeyDown event for eCompositionStart -+ // immediately after "delete_surrounding" signal. However, -+ // not dispatching eKeyDown event is worse than dispatching -+ // redundant eKeyDown events. -+ case eContentCommandDelete: -+ dispatchFakeKeyDown = true; -+ break; -+ // We need to prevent to dispatch redundant eKeyDown event for -+ // eCompositionChange immediately after eCompositionStart. So, -+ // We should not dispatch eKeyDown event if dispatched composition -+ // string is still empty string. -+ case eCompositionChange: -+ dispatchFakeKeyDown = !mDispatchedCompositionString.IsEmpty(); -+ break; -+ default: -+ MOZ_ASSERT_UNREACHABLE("Do you forget to handle the case?"); -+ break; -+ } ++ if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_PRIVATE)) ++ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; ++ if (action & GDK_ACTION_MOVE) ++ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; + -+ if (dispatchFakeKeyDown) { -+ WidgetKeyboardEvent fakeKeyDownEvent(true, eKeyDown, -+ lastFocusedWindow); -+ fakeKeyDownEvent.mKeyCode = NS_VK_PROCESSKEY; -+ fakeKeyDownEvent.mKeyNameIndex = KEY_NAME_INDEX_Process; -+ // It's impossible to get physical key information in this case but -+ // this should be okay since web apps shouldn't do anything with -+ // physical key information during composition. -+ fakeKeyDownEvent.mCodeNameIndex = CODE_NAME_INDEX_UNKNOWN; -+ -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(" -+ "aFollowingEvent=%s), dispatch fake eKeyDown event", -+ this, ToChar(aFollowingEvent))); -+ -+ bool isCancelled; -+ lastFocusedWindow->DispatchKeyDownOrKeyUpEvent(fakeKeyDownEvent, -+ &isCancelled); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), " -+ "fake keydown event is dispatched", -+ this)); -+ } -+ } ++ return dnd_actions; ++} + -+ if (lastFocusedWindow->IsDestroyed() || -+ lastFocusedWindow != mLastFocusedWindow) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), Warning, the " -+ "focused widget was destroyed/changed by a key event", -+ this)); -+ return false; -+ } ++static GtkWidget* ++get_gtk_widget_for_wl_surface(struct wl_surface *surface) ++{ ++ GdkWindow *gdkParentWindow = ++ static_cast(wl_surface_get_user_data(surface)); + -+ // If the dispatched keydown event caused moving focus and that also -+ // caused changing active context, we need to cancel composition here. -+ if (GetCurrentContext() != oldCurrentContext) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), Warning, the key " -+ "event causes changing active IM context", -+ this)); -+ if (mComposingContext == oldComposingContext) { -+ // Only when the context is still composing, we should call -+ // ResetIME() here. Otherwise, it should've already been -+ // cleaned up. -+ ResetIME(); -+ } -+ return false; -+ } ++ gpointer user_data = nullptr; ++ gdk_window_get_user_data(gdkParentWindow, &user_data); + -+ return true; ++ return GTK_WIDGET(user_data); +} + -+bool - IMContextWrapper::DispatchCompositionStart(GtkIMContext* aContext) + void + DataOffer::AddMIMEType(const char *aMimeType) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, -@@ -1528,50 +2103,16 @@ IMContextWrapper::DispatchCompositionSta - mCompositionStart = mSelection.mOffset; - mDispatchedCompositionString.Truncate(); - -- if (mProcessingKeyEvent && !mKeyDownEventWasSent && -- mProcessingKeyEvent->type == GDK_KEY_PRESS) { -- // A keydown event handler may change focus with the following keydown -- // event. In such case, we need to cancel this composition. So, we -- // need to store IM context now because mComposingContext may be -- // overwritten with different context if calling this method -- // recursively. -- // Note that we don't need to grab the context here because |context| -- // will be used only for checking if it's same as mComposingContext. -- GtkIMContext* context = mComposingContext; -- -- // If this composition is started by a native keydown event, we need to -- // dispatch our keydown event here (before composition start). -- bool isCancelled; -- mLastFocusedWindow->DispatchKeyDownEvent(mProcessingKeyEvent, -- &isCancelled); -- MOZ_LOG(gGtkIMLog, LogLevel::Debug, -- ("0x%p DispatchCompositionStart(), preceding keydown event is " -- "dispatched", -+ // If this composition is started by a key press, we need to dispatch -+ // eKeyDown or eKeyUp event before dispatching eCompositionStart event. -+ // Note that dispatching a keyboard event which is marked as "processed -+ // by IME" is okay since Chromium also dispatches keyboard event as so. -+ if (!MaybeDispatchKeyEventAsProcessedByIME(eCompositionStart)) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p DispatchCompositionStart(), Warning, " -+ "MaybeDispatchKeyEventAsProcessedByIME() returned false", - this)); -- if (lastFocusedWindow->IsDestroyed() || -- lastFocusedWindow != mLastFocusedWindow) { -- MOZ_LOG(gGtkIMLog, LogLevel::Warning, -- ("0x%p DispatchCompositionStart(), Warning, the focused " -- "widget was destroyed/changed by keydown event", -- this)); -- return false; -- } -- -- // If the dispatched keydown event caused moving focus and that also -- // caused changing active context, we need to cancel composition here. -- if (GetCurrentContext() != context) { -- MOZ_LOG(gGtkIMLog, LogLevel::Warning, -- ("0x%p DispatchCompositionStart(), Warning, the preceding " -- "keydown event causes changing active IM context", -- this)); -- if (mComposingContext == context) { -- // Only when the context is still composing, we should call -- // ResetIME() here. Otherwise, it should've already been -- // cleaned up. -- ResetIME(); -- } -- return false; -- } -+ return false; - } - - RefPtr dispatcher = GetTextEventDispatcher(); -@@ -1584,6 +2125,25 @@ IMContextWrapper::DispatchCompositionSta - return false; - } - -+ static bool sHasSetTelemetry = false; -+ if (!sHasSetTelemetry) { -+ sHasSetTelemetry = true; -+ NS_ConvertUTF8toUTF16 im(GetIMName()); -+ // 72 is kMaximumKeyStringLength in TelemetryScalar.cpp -+ if (im.Length() > 72) { -+ if (NS_IS_LOW_SURROGATE(im[72 - 1]) && -+ NS_IS_HIGH_SURROGATE(im[72 - 2])) { -+ im.Truncate(72 - 2); -+ } else { -+ im.Truncate(72 - 1); -+ } -+ // U+2026 is "..." -+ im.Append(char16_t(0x2026)); -+ } -+ Telemetry::ScalarSet(Telemetry::ScalarID::WIDGET_IME_NAME_ON_LINUX, -+ im, true); -+ } -+ - MOZ_LOG(gGtkIMLog, LogLevel::Debug, - ("0x%p DispatchCompositionStart(), dispatching " - "compositionstart... (mCompositionStart=%u)", -@@ -1629,6 +2189,15 @@ IMContextWrapper::DispatchCompositionCha - return false; - } - } -+ // If this composition string change caused by a key press, we need to -+ // dispatch eKeyDown or eKeyUp before dispatching eCompositionChange event. -+ else if (!MaybeDispatchKeyEventAsProcessedByIME(eCompositionChange)) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p DispatchCompositionChangeEvent(), Warning, " -+ "MaybeDispatchKeyEventAsProcessedByIME() returned false", -+ this)); -+ return false; -+ } +@@ -114,7 +153,7 @@ DataOffer::GetData(wl_display* aDisplay, - RefPtr dispatcher = GetTextEventDispatcher(); - nsresult rv = dispatcher->BeginNativeInputTransaction(); -@@ -1718,6 +2287,14 @@ IMContextWrapper::DispatchCompositionCom - return false; - } + GIOChannel *channel = g_io_channel_unix_new(pipe_fd[0]); + GError* error = nullptr; +- char* clipboardData; ++ char* clipboardData = nullptr; -+ // TODO: We need special care to handle request to commit composition -+ // by content while we're committing composition because we have -+ // commit string information now but IME may not have composition -+ // anymore. Therefore, we may not be able to handle commit as -+ // expected. However, this is rare case because this situation -+ // never occurs with remote content. So, it's okay to fix this -+ // issue later. (Perhaps, TextEventDisptcher should do it for -+ // all platforms. E.g., creating WillCommitComposition()?) - if (!IsComposing()) { - if (!aCommitString || aCommitString->IsEmpty()) { - MOZ_LOG(gGtkIMLog, LogLevel::Error, -@@ -1734,6 +2311,17 @@ IMContextWrapper::DispatchCompositionCom - return false; - } - } -+ // If this commit caused by a key press, we need to dispatch eKeyDown or -+ // eKeyUp before dispatching composition events. -+ else if (!MaybeDispatchKeyEventAsProcessedByIME( -+ aCommitString ? eCompositionCommit : eCompositionCommitAsIs)) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p DispatchCompositionCommitEvent(), Warning, " -+ "MaybeDispatchKeyEventAsProcessedByIME() returned false", -+ this)); -+ mCompositionState = eCompositionState_NotComposing; -+ return false; -+ } + g_io_channel_set_encoding(channel, nullptr, &error); + if (!error) { +@@ -155,6 +194,61 @@ WaylandDataOffer::RequestDataTransfer(co + return false; + } - RefPtr dispatcher = GetTextEventDispatcher(); - nsresult rv = dispatcher->BeginNativeInputTransaction(); -@@ -1755,6 +2343,11 @@ IMContextWrapper::DispatchCompositionCom - mSelection.mWritingMode); - - mCompositionState = eCompositionState_NotComposing; -+ // Reset dead key sequence too because GTK doesn't support dead key chain -+ // (i.e., a key press doesn't cause both producing some characters and -+ // restarting new dead key sequence at one time). So, committing -+ // composition means end of a dead key sequence. -+ mMaybeInDeadKeySequence = false; - mCompositionStart = UINT32_MAX; - mCompositionTargetRange.Clear(); - mDispatchedCompositionString.Truncate(); -@@ -2427,6 +3020,16 @@ IMContextWrapper::DeleteText(GtkIMContex - this)); - return NS_ERROR_FAILURE; - } ++void ++WaylandDataOffer::DragOfferAccept(const char* aMimeType, uint32_t aTime) ++{ ++ wl_data_offer_accept(mWaylandDataOffer, aTime, aMimeType); ++} + -+ // If this deleting text caused by a key press, we need to dispatch -+ // eKeyDown or eKeyUp before dispatching eContentCommandDelete event. -+ if (!MaybeDispatchKeyEventAsProcessedByIME(eContentCommandDelete)) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p DeleteText(), Warning, " -+ "MaybeDispatchKeyEventAsProcessedByIME() returned false", -+ this)); -+ return NS_ERROR_FAILURE; -+ } - - // Delete the selection - WidgetContentCommandEvent contentCommandEvent(true, eContentCommandDelete, -diff -up thunderbird-60.3.0/widget/gtk/IMContextWrapper.h.wayland thunderbird-60.3.0/widget/gtk/IMContextWrapper.h ---- thunderbird-60.3.0/widget/gtk/IMContextWrapper.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/IMContextWrapper.h 2018-11-20 12:04:43.733787362 +0100 -@@ -70,13 +70,26 @@ public: - // OnThemeChanged is called when desktop theme is changed. - static void OnThemeChanged(); - -- // OnKeyEvent is called when aWindow gets a native key press event or a -- // native key release event. If this returns TRUE, the key event was -- // filtered by IME. Otherwise, this returns FALSE. -- // NOTE: When the keypress event starts composition, this returns TRUE but -- // this dispatches keydown event before compositionstart event. -+ /** -+ * OnKeyEvent() is called when aWindow gets a native key press event or a -+ * native key release event. If this returns true, the key event was -+ * filtered by IME. Otherwise, this returns false. -+ * NOTE: When the native key press event starts composition, this returns -+ * true but dispatches an eKeyDown event or eKeyUp event before -+ * dispatching composition events or content command event. -+ * -+ * @param aWindow A window on which user operate the -+ * key. -+ * @param aEvent A native key press or release -+ * event. -+ * @param aKeyboardEventWasDispatched true if eKeyDown or eKeyUp event -+ * for aEvent has already been -+ * dispatched. In this case, -+ * this class doesn't dispatch -+ * keyboard event anymore. -+ */ - bool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent, -- bool aKeyDownEventWasSent = false); -+ bool aKeyboardEventWasDispatched = false); - - // IME related nsIWidget methods. - nsresult EndIMEComposition(nsWindow* aCaller); -@@ -89,6 +102,43 @@ public: - - TextEventDispatcher* GetTextEventDispatcher(); - -+ // TODO: Typically, new IM comes every several years. And now, our code -+ // becomes really IM behavior dependent. So, perhaps, we need prefs -+ // to control related flags for IM developers. -+ enum class IMContextID : uint8_t -+ { -+ eFcitx, -+ eIBus, -+ eIIIMF, -+ eScim, -+ eUim, -+ eUnknown, -+ }; -+ -+ static const char* GetIMContextIDName(IMContextID aIMContextID) -+ { -+ switch (aIMContextID) { -+ case IMContextID::eFcitx: -+ return "eFcitx"; -+ case IMContextID::eIBus: -+ return "eIBus"; -+ case IMContextID::eIIIMF: -+ return "eIIIMF"; -+ case IMContextID::eScim: -+ return "eScim"; -+ case IMContextID::eUim: -+ return "eUim"; -+ default: -+ return "eUnknown"; -+ } -+ } -+ -+ /** -+ * GetIMName() returns IM name associated with mContext. If the context is -+ * xim, this look for actual engine from XMODIFIERS environment variable. -+ */ -+ nsDependentCSubstring GetIMName() const; -+ - protected: - ~IMContextWrapper(); - -@@ -144,6 +194,100 @@ protected: - // event. - GdkEventKey* mProcessingKeyEvent; - -+ /** -+ * GdkEventKeyQueue stores *copy* of GdkEventKey instances. However, this -+ * must be safe to our usecase since it has |time| and the value should not -+ * be same as older event. -+ */ -+ class GdkEventKeyQueue final -+ { -+ public: -+ ~GdkEventKeyQueue() { Clear(); } -+ -+ void Clear() -+ { -+ if (!mEvents.IsEmpty()) { -+ RemoveEventsAt(0, mEvents.Length()); -+ } -+ } -+ -+ /** -+ * PutEvent() puts new event into the queue. -+ */ -+ void PutEvent(const GdkEventKey* aEvent) -+ { -+ GdkEventKey* newEvent = -+ reinterpret_cast( -+ gdk_event_copy(reinterpret_cast(aEvent))); -+ newEvent->state &= GDK_MODIFIER_MASK; -+ mEvents.AppendElement(newEvent); -+ } -+ -+ /** -+ * RemoveEvent() removes oldest same event and its preceding events -+ * from the queue. -+ */ -+ void RemoveEvent(const GdkEventKey* aEvent) -+ { -+ size_t index = IndexOf(aEvent); -+ if (NS_WARN_IF(index == mEvents.NoIndex)) { -+ return; -+ } -+ RemoveEventsAt(0, index + 1); -+ } -+ -+ /** -+ * FirstEvent() returns oldest event in the queue. -+ */ -+ GdkEventKey* GetFirstEvent() const -+ { -+ if (mEvents.IsEmpty()) { -+ return nullptr; -+ } -+ return mEvents[0]; -+ } -+ -+ bool IsEmpty() const { return mEvents.IsEmpty(); } ++/* We follow logic of gdk_wayland_drag_context_commit_status()/gdkdnd-wayland.c ++ * here. ++ */ ++void ++WaylandDataOffer::SetDragStatus(GdkDragAction aAction, uint32_t aTime) ++{ ++ uint32_t dnd_actions = gdk_to_wl_actions(aAction); ++ uint32_t all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | ++ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; + -+ private: -+ nsTArray mEvents; ++ wl_data_offer_set_actions(mWaylandDataOffer, all_actions, dnd_actions); + -+ void RemoveEventsAt(size_t aStart, size_t aCount) -+ { -+ for (size_t i = aStart; i < aStart + aCount; i++) { -+ gdk_event_free(reinterpret_cast(mEvents[i])); -+ } -+ mEvents.RemoveElementsAt(aStart, aCount); -+ } ++ /* Workaround Wayland D&D architecture here. To get the data_device_drop() ++ signal (which routes to nsDragService::GetData() call) we need to ++ accept at least one mime type before data_device_leave(). + -+ size_t IndexOf(const GdkEventKey* aEvent) const -+ { -+ static_assert(!(GDK_MODIFIER_MASK & (1 << 24)), -+ "We assumes 25th bit is used by some IM, but used by GDK"); -+ static_assert(!(GDK_MODIFIER_MASK & (1 << 25)), -+ "We assumes 26th bit is used by some IM, but used by GDK"); -+ for (size_t i = 0; i < mEvents.Length(); i++) { -+ GdkEventKey* event = mEvents[i]; -+ // It must be enough to compare only type, time, keyval and -+ // part of state. Note that we cannot compaire two events -+ // simply since IME may have changed unused bits of state. -+ if (event->time == aEvent->time) { -+ if (NS_WARN_IF(event->type != aEvent->type) || -+ NS_WARN_IF(event->keyval != aEvent->keyval) || -+ NS_WARN_IF(event->state != -+ (aEvent->state & GDK_MODIFIER_MASK))) { -+ continue; -+ } -+ } -+ return i; -+ } -+ return mEvents.NoIndex; -+ } -+ }; -+ // OnKeyEvent() append mPostingKeyEvents when it believes that a key event -+ // is posted to other IME process. -+ GdkEventKeyQueue mPostingKeyEvents; ++ Real wl_data_offer_accept() for actualy requested data mime type is ++ called from nsDragService::GetData(). ++ */ ++ if (mTargetMIMETypes[0]) { ++ wl_data_offer_accept(mWaylandDataOffer, aTime, ++ gdk_atom_name(mTargetMIMETypes[0])); ++ } ++} + - struct Range - { - uint32_t mOffset; -@@ -167,7 +311,8 @@ protected: - Range mCompositionTargetRange; - - // mCompositionState indicates current status of composition. -- enum eCompositionState { -+ enum eCompositionState : uint8_t -+ { - eCompositionState_NotComposing, - eCompositionState_CompositionStartDispatched, - eCompositionState_CompositionChangeEventDispatched -@@ -219,6 +364,10 @@ protected: - } - } - -+ // mIMContextID indicates the ID of mContext. This is actually indicates -+ // IM which user selected. -+ IMContextID mIMContextID; ++void ++WaylandDataOffer::SetSelectedDragAction(uint32_t aWaylandAction) ++{ ++ mSelectedDragAction = aWaylandAction; ++} + - struct Selection final - { - nsString mString; -@@ -268,16 +417,20 @@ protected: - // mIsIMFocused is set to TRUE when we call gtk_im_context_focus_in(). And - // it's set to FALSE when we call gtk_im_context_focus_out(). - bool mIsIMFocused; -- // mFilterKeyEvent is used by OnKeyEvent(). If the commit event should -- // be processed as simple key event, this is set to TRUE by the commit -- // handler. -- bool mFilterKeyEvent; -- // mKeyDownEventWasSent is used by OnKeyEvent() and -- // DispatchCompositionStart(). DispatchCompositionStart() dispatches -- // a keydown event if the composition start is caused by a native -- // keypress event. If this is true, the keydown event has been dispatched. -- // Then, DispatchCompositionStart() doesn't dispatch keydown event. -- bool mKeyDownEventWasSent; -+ // mFallbackToKeyEvent is set to false when this class starts to handle -+ // a native key event (at that time, mProcessingKeyEvent is set to the -+ // native event). If active IME just commits composition with a character -+ // which is produced by the key with current keyboard layout, this is set -+ // to true. -+ bool mFallbackToKeyEvent; -+ // mKeyboardEventWasDispatched is used by OnKeyEvent() and -+ // MaybeDispatchKeyEventAsProcessedByIME(). -+ // MaybeDispatchKeyEventAsProcessedByIME() dispatches an eKeyDown or -+ // eKeyUp event event if the composition is caused by a native -+ // key press event. If this is true, a keyboard event has been dispatched -+ // for the native event. If so, MaybeDispatchKeyEventAsProcessedByIME() -+ // won't dispatch keyboard event anymore. -+ bool mKeyboardEventWasDispatched; - // mIsDeletingSurrounding is true while OnDeleteSurroundingNative() is - // trying to delete the surrounding text. - bool mIsDeletingSurrounding; -@@ -298,6 +451,24 @@ protected: - // mRetrieveSurroundingSignalReceived is true after "retrieve_surrounding" - // signal is received until selection is changed in Gecko. - bool mRetrieveSurroundingSignalReceived; -+ // mMaybeInDeadKeySequence is set to true when we detect a dead key press -+ // and set to false when we're sure dead key sequence has been finished. -+ // Note that we cannot detect which key event causes ending a dead key -+ // sequence. For example, when you press dead key grave with ibus Spanish -+ // keyboard layout, it just consumes the key event when we call -+ // gtk_im_context_filter_keypress(). Then, pressing "Escape" key cancels -+ // the dead key sequence but we don't receive any signal and it's consumed -+ // by gtk_im_context_filter_keypress() normally. On the other hand, when -+ // pressing "Shift" key causes exactly same behavior but dead key sequence -+ // isn't finished yet. -+ bool mMaybeInDeadKeySequence; -+ // mIsIMInAsyncKeyHandlingMode is set to true if we know that IM handles -+ // key events asynchronously. I.e., filtered key event may come again -+ // later. -+ bool mIsIMInAsyncKeyHandlingMode; -+ // mIsKeySnooped is set to true if IM uses key snooper to listen key events. -+ // In such case, we won't receive key events if IME consumes the event. -+ bool mIsKeySnooped; - - // sLastFocusedContext is a pointer to the last focused instance of this - // class. When a instance is destroyed and sLastFocusedContext refers it, -@@ -448,12 +619,31 @@ protected: - * Following methods dispatch gecko events. Then, the focused widget - * can be destroyed, and also it can be stolen focus. If they returns - * FALSE, callers cannot continue the composition. -+ * - MaybeDispatchKeyEventAsProcessedByIME - * - DispatchCompositionStart - * - DispatchCompositionChangeEvent - * - DispatchCompositionCommitEvent - */ - - /** -+ * Dispatch an eKeyDown or eKeyUp event whose mKeyCode value is -+ * NS_VK_PROCESSKEY and mKeyNameIndex is KEY_NAME_INDEX_Process if -+ * we're not in a dead key sequence, mProcessingKeyEvent is nullptr -+ * but mPostingKeyEvents is not empty or mProcessingKeyEvent is not -+ * nullptr and mKeyboardEventWasDispatched is still false. If this -+ * dispatches a keyboard event, this sets mKeyboardEventWasDispatched -+ * to true. -+ * -+ * @param aFollowingEvent The following event message. -+ * @return If the caller can continue to handle -+ * composition, returns true. Otherwise, -+ * false. For example, if focus is moved -+ * by dispatched keyboard event, returns -+ * false. -+ */ -+ bool MaybeDispatchKeyEventAsProcessedByIME(EventMessage aFollowingEvent); ++GdkDragAction ++WaylandDataOffer::GetSelectedDragAction() ++{ ++ return wl_to_gdk_actions(mSelectedDragAction); ++} + -+ /** - * Dispatches a composition start event. - * - * @param aContext A GtkIMContext which is being handled. -diff -up thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h.wayland thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h ---- thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h 2018-11-20 12:04:43.733787362 +0100 -@@ -3,8 +3,8 @@ - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - --#ifndef widget_gtk_InProcessGtkCompositorWidgetParent_h --#define widget_gtk_InProcessGtkCompositorWidgetParent_h -+#ifndef widget_gtk_InProcessGtkCompositorWidget_h -+#define widget_gtk_InProcessGtkCompositorWidget_h - - #include "GtkCompositorWidget.h" - -@@ -28,4 +28,4 @@ public: - } // namespace widget - } // namespace mozilla - --#endif // widget_gtk_InProcessGtkCompositorWidgetParent_h -+#endif // widget_gtk_InProcessGtkCompositorWidget_h -diff -up thunderbird-60.3.0/widget/gtk/moz.build.wayland thunderbird-60.3.0/widget/gtk/moz.build ---- thunderbird-60.3.0/widget/gtk/moz.build.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/moz.build 2018-11-20 12:09:34.756903818 +0100 -@@ -123,6 +123,7 @@ include('/ipc/chromium/chromium-config.m - FINAL_LIBRARY = 'xul' - - LOCAL_INCLUDES += [ -+ '/layout/base', - '/layout/generic', - '/layout/xul', - '/other-licenses/atk-1.0', -diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.3.0/widget/gtk/mozcontainer.cpp ---- thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/mozcontainer.cpp 2018-11-20 12:04:43.733787362 +0100 -@@ -10,6 +10,7 @@ - #ifdef MOZ_WAYLAND - #include - #include -+#include - #endif - #include - #include -@@ -207,6 +208,12 @@ moz_container_init (MozContainer *contai - - #if defined(MOZ_WAYLAND) - { -+ container->subcompositor = nullptr; -+ container->surface = nullptr; -+ container->subsurface = nullptr; -+ container->eglwindow = nullptr; -+ container->parent_surface_committed = false; ++void ++WaylandDataOffer::SetAvailableDragActions(uint32_t aWaylandActions) ++{ ++ mAvailableDragAction = aWaylandActions; ++} + - GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container)); - if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) { - // Available as of GTK 3.8+ -@@ -225,12 +232,21 @@ moz_container_init (MozContainer *contai - } - - #if defined(MOZ_WAYLAND) -+static void -+moz_container_commited_handler(GdkFrameClock *clock, MozContainer *container) ++GdkDragAction ++WaylandDataOffer::GetAvailableDragActions() +{ -+ container->parent_surface_committed = true; -+ g_signal_handler_disconnect(clock, -+ container->parent_surface_committed_handler); -+ container->parent_surface_committed_handler = 0; ++ return wl_to_gdk_actions(mAvailableDragAction); +} + - /* We want to draw to GdkWindow owned by mContainer from Compositor thread but - * Gtk+ can be used in main thread only. So we create wayland wl_surface - * and attach it as an overlay to GdkWindow. - * - * see gtk_clutter_embed_ensure_subsurface() at gtk-clutter-embed.c --* for reference. -+ * for reference. - */ - static gboolean - moz_container_map_surface(MozContainer *container) -@@ -242,6 +258,9 @@ moz_container_map_surface(MozContainer * - static auto sGdkWaylandWindowGetWlSurface = - (wl_surface *(*)(GdkWindow *)) - dlsym(RTLD_DEFAULT, "gdk_wayland_window_get_wl_surface"); -+ static auto sGdkWindowGetFrameClock = -+ (GdkFrameClock *(*)(GdkWindow *)) -+ dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock"); - - GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container)); - if (GDK_IS_X11_DISPLAY(display)) -@@ -250,6 +269,18 @@ moz_container_map_surface(MozContainer * - if (container->subsurface && container->surface) - return true; + static void + data_offer_offer (void *data, + struct wl_data_offer *wl_data_offer, +@@ -164,25 +258,39 @@ data_offer_offer (void * + offer->AddMIMEType(type); + } -+ if (!container->parent_surface_committed) { -+ if (!container->parent_surface_committed_handler) { -+ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); -+ GdkFrameClock *clock = sGdkWindowGetFrameClock(window); -+ container->parent_surface_committed_handler = -+ g_signal_connect_after(clock, "after-paint", -+ G_CALLBACK(moz_container_commited_handler), -+ container); -+ } -+ return false; -+ } -+ - if (!container->surface) { - struct wl_compositor *compositor; - compositor = sGdkWaylandDisplayGetWlCompositor(display); -@@ -289,8 +320,22 @@ moz_container_map_surface(MozContainer * ++/* Advertise all available drag and drop actions from source. ++ * We don't use that but follow gdk_wayland_drag_context_commit_status() ++ * from gdkdnd-wayland.c here. ++ */ static void - moz_container_unmap_surface(MozContainer *container) + data_offer_source_actions(void *data, + struct wl_data_offer *wl_data_offer, + uint32_t source_actions) { -+ g_clear_pointer(&container->eglwindow, wl_egl_window_destroy); - g_clear_pointer(&container->subsurface, wl_subsurface_destroy); - g_clear_pointer(&container->surface, wl_surface_destroy); -+ -+ if (container->parent_surface_committed_handler) { -+ static auto sGdkWindowGetFrameClock = -+ (GdkFrameClock *(*)(GdkWindow *)) -+ dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock"); -+ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); -+ GdkFrameClock *clock = sGdkWindowGetFrameClock(window); -+ -+ g_signal_handler_disconnect(clock, -+ container->parent_surface_committed_handler); -+ container->parent_surface_committed_handler = 0; -+ } -+ container->parent_surface_committed = false; ++ auto *offer = static_cast(data); ++ offer->SetAvailableDragActions(source_actions); } - #endif -@@ -434,6 +479,11 @@ moz_container_size_allocate (GtkWidget - gdk_window_get_position(gtk_widget_get_window(widget), &x, &y); - wl_subsurface_set_position(container->subsurface, x, y); - } -+ if (container->eglwindow) { -+ wl_egl_window_resize(container->eglwindow, -+ allocation->width, allocation->height, -+ 0, 0); -+ } - #endif ++/* Advertise recently selected drag and drop action by compositor, based ++ * on source actions and user choice (key modifiers, etc.). ++ */ + static void + data_offer_action(void *data, + struct wl_data_offer *wl_data_offer, + uint32_t dnd_action) + { ++ auto *offer = static_cast(data); ++ offer->SetSelectedDragAction(dnd_action); } -@@ -555,8 +605,40 @@ moz_container_get_wl_surface(MozContaine - return nullptr; - - moz_container_map_surface(container); -+ // Set the scale factor for the buffer right after we create it. -+ if (container->surface) { -+ static auto sGdkWindowGetScaleFactorPtr = (gint (*)(GdkWindow*)) -+ dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor"); -+ if (sGdkWindowGetScaleFactorPtr && window) { -+ gint scaleFactor = (*sGdkWindowGetScaleFactorPtr)(window); -+ wl_surface_set_buffer_scale(container->surface, scaleFactor); -+ } -+ } + /* wl_data_offer callback description: + * + * data_offer_offer - Is called for each MIME type available at wl_data_offer. +- * data_offer_source_actions - Exposes all available D&D actions. +- * data_offer_action - Expose one actually selected D&D action. ++ * data_offer_source_actions - This event indicates the actions offered by ++ * the data source. ++ * data_offer_action - This event indicates the action selected by ++ * the compositor after matching the source/destination ++ * side actions. + */ + static const struct wl_data_offer_listener data_offer_listener = { + data_offer_offer, +@@ -246,12 +354,94 @@ PrimaryDataOffer::~PrimaryDataOffer(void } - - return container->surface; } + ++NS_IMPL_ISUPPORTS(nsWaylandDragContext, nsISupports); + -+struct wl_egl_window * -+moz_container_get_wl_egl_window(MozContainer *container) -+{ -+ if (!container->eglwindow) { -+ struct wl_surface *wlsurf = moz_container_get_wl_surface(container); -+ if (!wlsurf) -+ return nullptr; -+ -+ GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container)); -+ container->eglwindow -+ = wl_egl_window_create(wlsurf, -+ gdk_window_get_width(window), -+ gdk_window_get_height(window)); -+ } -+ return container->eglwindow; ++nsWaylandDragContext::nsWaylandDragContext(WaylandDataOffer* aDataOffer, ++ wl_display *aDisplay) ++ : mDataOffer(aDataOffer) ++ , mDisplay(aDisplay) ++ , mTime(0) ++ , mGtkWidget(nullptr) ++ , mX(0) ++ , mY(0) ++{ +} + -+gboolean -+moz_container_has_wl_egl_window(MozContainer *container) ++void ++nsWaylandDragContext::DropDataEnter(GtkWidget* aGtkWidget, uint32_t aTime, ++ nscoord aX, nscoord aY) +{ -+ return container->eglwindow ? true : false; ++ mTime = aTime; ++ mGtkWidget = aGtkWidget; ++ mX = aX; ++ mY = aY; +} - #endif -diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.h.wayland thunderbird-60.3.0/widget/gtk/mozcontainer.h ---- thunderbird-60.3.0/widget/gtk/mozcontainer.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/mozcontainer.h 2018-11-20 12:04:43.733787362 +0100 -@@ -72,6 +72,9 @@ struct _MozContainer - struct wl_subcompositor *subcompositor; - struct wl_surface *surface; - struct wl_subsurface *subsurface; -+ struct wl_egl_window *eglwindow; -+ gboolean parent_surface_committed; -+ gulong parent_surface_committed_handler; - #endif - }; - -@@ -95,6 +98,8 @@ void moz_container_move ( - - #ifdef MOZ_WAYLAND - struct wl_surface* moz_container_get_wl_surface(MozContainer *container); -+struct wl_egl_window* moz_container_get_wl_egl_window(MozContainer *container); -+gboolean moz_container_has_wl_egl_window(MozContainer *container); - #endif - - #endif /* __MOZ_CONTAINER_H__ */ -diff -up thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c ---- thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c 2018-11-20 12:04:43.734787359 +0100 -@@ -135,6 +135,8 @@ STUB(gdk_x11_get_xatom_by_name) - STUB(gdk_x11_get_xatom_by_name_for_display) - STUB(gdk_x11_lookup_xdisplay) - STUB(gdk_x11_screen_get_xscreen) -+STUB(gdk_x11_screen_get_screen_number) -+STUB(gdk_x11_screen_lookup_visual) - STUB(gdk_x11_screen_supports_net_wm_hint) - STUB(gdk_x11_visual_get_xvisual) - STUB(gdk_x11_window_foreign_new_for_display) -@@ -266,6 +268,7 @@ STUB(gtk_im_context_set_client_window) - STUB(gtk_im_context_set_cursor_location) - STUB(gtk_im_context_set_surrounding) - STUB(gtk_im_context_simple_new) -+STUB(gtk_im_multicontext_get_context_id) - STUB(gtk_im_multicontext_get_type) - STUB(gtk_im_multicontext_new) - STUB(gtk_info_bar_get_type) -diff -up thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c.wayland thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c ---- thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c 2018-11-20 12:04:43.734787359 +0100 -@@ -271,3 +271,21 @@ wl_log_set_handler_client(wl_log_func_t - { - } - -+MOZ_EXPORT struct wl_egl_window * -+wl_egl_window_create(struct wl_surface *surface, -+ int width, int height) ++ + void +-nsRetrievalContextWayland::RegisterDataOffer(wl_data_offer *aWaylandDataOffer) ++nsWaylandDragContext::DropMotion(uint32_t aTime, nscoord aX, nscoord aY) +{ -+ return NULL; ++ mTime = aTime; ++ mX = aX; ++ mY = aY; +} + -+MOZ_EXPORT void -+wl_egl_window_destroy(struct wl_egl_window *egl_window) ++void ++nsWaylandDragContext::GetLastDropInfo(uint32_t *aTime, nscoord *aX, nscoord *aY) +{ ++ *aTime = mTime; ++ *aX = mX; ++ *aY = mY; +} + -+MOZ_EXPORT void -+wl_egl_window_resize(struct wl_egl_window *egl_window, -+ int width, int height, -+ int dx, int dy) ++void ++nsWaylandDragContext::SetDragStatus(GdkDragAction aAction) +{ ++ mDataOffer->SetDragStatus(aAction, mTime); +} -diff -up thunderbird-60.3.0/widget/gtk/nsAppShell.cpp.wayland thunderbird-60.3.0/widget/gtk/nsAppShell.cpp ---- thunderbird-60.3.0/widget/gtk/nsAppShell.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsAppShell.cpp 2018-11-20 12:04:43.734787359 +0100 -@@ -14,7 +14,8 @@ - #include "nsWindow.h" - #include "mozilla/Logging.h" - #include "prenv.h" --#include "mozilla/HangMonitor.h" -+#include "mozilla/BackgroundHangMonitor.h" -+#include "mozilla/Hal.h" - #include "mozilla/Unused.h" - #include "mozilla/WidgetUtils.h" - #include "GeckoProfiler.h" -@@ -46,13 +47,14 @@ static GPollFunc sPollFunc; - static gint - PollWrapper(GPollFD *ufds, guint nfsd, gint timeout_) - { -- mozilla::HangMonitor::Suspend(); -+ mozilla::BackgroundHangMonitor().NotifyWait(); - gint result; - { -+ AUTO_PROFILER_LABEL("PollWrapper", IDLE); - AUTO_PROFILER_THREAD_SLEEP; - result = (*sPollFunc)(ufds, nfsd, timeout_); - } -- mozilla::HangMonitor::NotifyActivity(); -+ mozilla::BackgroundHangMonitor().NotifyActivity(); - return result; - } - -@@ -133,6 +135,8 @@ nsAppShell::EventProcessorCallback(GIOCh - - nsAppShell::~nsAppShell() - { -+ mozilla::hal::Shutdown(); -+ - if (mTag) - g_source_remove(mTag); - if (mPipeFDs[0]) -@@ -150,6 +154,8 @@ nsAppShell::Init() - // is a no-op. - g_type_init(); - -+ mozilla::hal::Init(); + - #ifdef MOZ_ENABLE_DBUS - if (XRE_IsParentProcess()) { - nsCOMPtr powerManagerService = -diff -up thunderbird-60.3.0/widget/gtk/nsClipboard.cpp.wayland thunderbird-60.3.0/widget/gtk/nsClipboard.cpp ---- thunderbird-60.3.0/widget/gtk/nsClipboard.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsClipboard.cpp 2018-11-20 12:04:43.734787359 +0100 -@@ -671,11 +671,9 @@ void ConvertHTMLtoUCS2(const char* data, - *unicodeData = - reinterpret_cast - (moz_xmalloc((outUnicodeLen + sizeof('\0')) * sizeof(char16_t))); -- if (*unicodeData) { -- memcpy(*unicodeData, data + sizeof(char16_t), -- outUnicodeLen * sizeof(char16_t)); -- (*unicodeData)[outUnicodeLen] = '\0'; -- } -+ memcpy(*unicodeData, data + sizeof(char16_t), -+ outUnicodeLen * sizeof(char16_t)); -+ (*unicodeData)[outUnicodeLen] = '\0'; - } else if (charset.EqualsLiteral("UNKNOWN")) { - outUnicodeLen = 0; - return; -@@ -701,27 +699,25 @@ void ConvertHTMLtoUCS2(const char* data, - if (needed.value()) { - *unicodeData = reinterpret_cast( - moz_xmalloc((needed.value() + 1) * sizeof(char16_t))); -- if (*unicodeData) { -- uint32_t result; -- size_t read; -- size_t written; -- bool hadErrors; -- Tie(result, read, written, hadErrors) = -- decoder->DecodeToUTF16(AsBytes(MakeSpan(data, dataLength)), -- MakeSpan(*unicodeData, needed.value()), -- true); -- MOZ_ASSERT(result == kInputEmpty); -- MOZ_ASSERT(read == size_t(dataLength)); -- MOZ_ASSERT(written <= needed.value()); -- Unused << hadErrors; -+ uint32_t result; -+ size_t read; -+ size_t written; -+ bool hadErrors; -+ Tie(result, read, written, hadErrors) = -+ decoder->DecodeToUTF16(AsBytes(MakeSpan(data, dataLength)), -+ MakeSpan(*unicodeData, needed.value()), -+ true); -+ MOZ_ASSERT(result == kInputEmpty); -+ MOZ_ASSERT(read == size_t(dataLength)); -+ MOZ_ASSERT(written <= needed.value()); -+ Unused << hadErrors; - #ifdef DEBUG_CLIPBOARD -- if (read != dataLength) -- printf("didn't consume all the bytes\n"); -+ if (read != dataLength) -+ printf("didn't consume all the bytes\n"); - #endif -- outUnicodeLen = written; -- // null terminate. -- (*unicodeData)[outUnicodeLen] = '\0'; -- } -+ outUnicodeLen = written; -+ // null terminate. -+ (*unicodeData)[outUnicodeLen] = '\0'; - } // if valid length - } - } -diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp ---- thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp 2018-11-20 12:04:43.735787356 +0100 -@@ -23,6 +23,7 @@ - #include "mozilla/Services.h" - #include "mozilla/RefPtr.h" - #include "mozilla/TimeStamp.h" -+#include "nsDragService.h" - - #include "imgIContainer.h" - -@@ -46,6 +47,44 @@ nsRetrievalContextWayland::sTextMimeType - "COMPOUND_TEXT" - }; - -+static inline GdkDragAction -+wl_to_gdk_actions(uint32_t dnd_actions) ++GdkDragAction ++nsWaylandDragContext::GetSelectedDragAction() +{ -+ GdkDragAction actions = GdkDragAction(0); ++ GdkDragAction gdkAction = mDataOffer->GetSelectedDragAction(); + -+ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) -+ actions = GdkDragAction(actions|GDK_ACTION_COPY); -+ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) -+ actions = GdkDragAction(actions|GDK_ACTION_MOVE); ++ // We emulate gdk_drag_context_get_actions() here. ++ if (!gdkAction) { ++ gdkAction = mDataOffer->GetAvailableDragActions(); ++ } + -+ return actions; ++ return gdkAction; +} + -+static inline uint32_t -+gdk_to_wl_actions(GdkDragAction action) ++GList* ++nsWaylandDragContext::GetTargets() +{ -+ uint32_t dnd_actions = 0; ++ int targetNums; ++ GdkAtom *atoms = mDataOffer->GetTargets(&targetNums); + -+ if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_PRIVATE)) -+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; -+ if (action & GDK_ACTION_MOVE) -+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; ++ GList* targetList = nullptr; ++ for (int i = 0; i < targetNums; i++) { ++ targetList = g_list_append(targetList, GDK_ATOM_TO_POINTER(atoms[i])); ++ } + -+ return dnd_actions; ++ return targetList; +} + -+static GtkWidget* -+get_gtk_widget_for_wl_surface(struct wl_surface *surface) ++char* ++nsWaylandDragContext::GetData(const char* aMimeType, uint32_t* aContentLength) +{ -+ GdkWindow *gdkParentWindow = -+ static_cast(wl_surface_get_user_data(surface)); -+ -+ gpointer user_data = nullptr; -+ gdk_window_get_user_data(gdkParentWindow, &user_data); -+ -+ return GTK_WIDGET(user_data); ++ mDataOffer->DragOfferAccept(aMimeType, mTime); ++ return mDataOffer->GetData(mDisplay, aMimeType, aContentLength); +} + - void - DataOffer::AddMIMEType(const char *aMimeType) ++void ++nsRetrievalContextWayland::RegisterNewDataOffer(wl_data_offer *aWaylandDataOffer) { -@@ -114,7 +153,7 @@ DataOffer::GetData(wl_display* aDisplay, - - GIOChannel *channel = g_io_channel_unix_new(pipe_fd[0]); - GError* error = nullptr; -- char* clipboardData; -+ char* clipboardData = nullptr; - - g_io_channel_set_encoding(channel, nullptr, &error); - if (!error) { -@@ -155,6 +194,61 @@ WaylandDataOffer::RequestDataTransfer(co - return false; - } - -+void -+WaylandDataOffer::DragOfferAccept(const char* aMimeType, uint32_t aTime) -+{ -+ wl_data_offer_accept(mWaylandDataOffer, aTime, aMimeType); -+} -+ -+/* We follow logic of gdk_wayland_drag_context_commit_status()/gdkdnd-wayland.c -+ * here. -+ */ -+void -+WaylandDataOffer::SetDragStatus(GdkDragAction aAction, uint32_t aTime) -+{ -+ uint32_t dnd_actions = gdk_to_wl_actions(aAction); -+ uint32_t all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | -+ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; -+ -+ wl_data_offer_set_actions(mWaylandDataOffer, all_actions, dnd_actions); -+ -+ /* Workaround Wayland D&D architecture here. To get the data_device_drop() -+ signal (which routes to nsDragService::GetData() call) we need to -+ accept at least one mime type before data_device_leave(). -+ -+ Real wl_data_offer_accept() for actualy requested data mime type is -+ called from nsDragService::GetData(). -+ */ -+ if (mTargetMIMETypes[0]) { -+ wl_data_offer_accept(mWaylandDataOffer, aTime, -+ gdk_atom_name(mTargetMIMETypes[0])); -+ } -+} -+ -+void -+WaylandDataOffer::SetSelectedDragAction(uint32_t aWaylandAction) -+{ -+ mSelectedDragAction = aWaylandAction; -+} -+ -+GdkDragAction -+WaylandDataOffer::GetSelectedDragAction() -+{ -+ return wl_to_gdk_actions(mSelectedDragAction); -+} -+ -+void -+WaylandDataOffer::SetAvailableDragActions(uint32_t aWaylandActions) -+{ -+ mAvailableDragAction = aWaylandActions; -+} -+ -+GdkDragAction -+WaylandDataOffer::GetAvailableDragActions() -+{ -+ return wl_to_gdk_actions(mAvailableDragAction); -+} -+ - static void - data_offer_offer (void *data, - struct wl_data_offer *wl_data_offer, -@@ -164,25 +258,39 @@ data_offer_offer (void * - offer->AddMIMEType(type); - } - -+/* Advertise all available drag and drop actions from source. -+ * We don't use that but follow gdk_wayland_drag_context_commit_status() -+ * from gdkdnd-wayland.c here. -+ */ - static void - data_offer_source_actions(void *data, - struct wl_data_offer *wl_data_offer, - uint32_t source_actions) - { -+ auto *offer = static_cast(data); -+ offer->SetAvailableDragActions(source_actions); - } - -+/* Advertise recently selected drag and drop action by compositor, based -+ * on source actions and user choice (key modifiers, etc.). -+ */ - static void - data_offer_action(void *data, - struct wl_data_offer *wl_data_offer, - uint32_t dnd_action) - { -+ auto *offer = static_cast(data); -+ offer->SetSelectedDragAction(dnd_action); - } - - /* wl_data_offer callback description: - * - * data_offer_offer - Is called for each MIME type available at wl_data_offer. -- * data_offer_source_actions - Exposes all available D&D actions. -- * data_offer_action - Expose one actually selected D&D action. -+ * data_offer_source_actions - This event indicates the actions offered by -+ * the data source. -+ * data_offer_action - This event indicates the action selected by -+ * the compositor after matching the source/destination -+ * side actions. - */ - static const struct wl_data_offer_listener data_offer_listener = { - data_offer_offer, -@@ -246,12 +354,94 @@ PrimaryDataOffer::~PrimaryDataOffer(void - } - } - -+NS_IMPL_ISUPPORTS(nsWaylandDragContext, nsISupports); -+ -+nsWaylandDragContext::nsWaylandDragContext(WaylandDataOffer* aDataOffer, -+ wl_display *aDisplay) -+ : mDataOffer(aDataOffer) -+ , mDisplay(aDisplay) -+ , mTime(0) -+ , mGtkWidget(nullptr) -+ , mX(0) -+ , mY(0) -+{ -+} -+ -+void -+nsWaylandDragContext::DropDataEnter(GtkWidget* aGtkWidget, uint32_t aTime, -+ nscoord aX, nscoord aY) -+{ -+ mTime = aTime; -+ mGtkWidget = aGtkWidget; -+ mX = aX; -+ mY = aY; -+} -+ - void --nsRetrievalContextWayland::RegisterDataOffer(wl_data_offer *aWaylandDataOffer) -+nsWaylandDragContext::DropMotion(uint32_t aTime, nscoord aX, nscoord aY) -+{ -+ mTime = aTime; -+ mX = aX; -+ mY = aY; -+} -+ -+void -+nsWaylandDragContext::GetLastDropInfo(uint32_t *aTime, nscoord *aX, nscoord *aY) -+{ -+ *aTime = mTime; -+ *aX = mX; -+ *aY = mY; -+} -+ -+void -+nsWaylandDragContext::SetDragStatus(GdkDragAction aAction) -+{ -+ mDataOffer->SetDragStatus(aAction, mTime); -+} -+ -+GdkDragAction -+nsWaylandDragContext::GetSelectedDragAction() -+{ -+ GdkDragAction gdkAction = mDataOffer->GetSelectedDragAction(); -+ -+ // We emulate gdk_drag_context_get_actions() here. -+ if (!gdkAction) { -+ gdkAction = mDataOffer->GetAvailableDragActions(); -+ } -+ -+ return gdkAction; -+} -+ -+GList* -+nsWaylandDragContext::GetTargets() -+{ -+ int targetNums; -+ GdkAtom *atoms = mDataOffer->GetTargets(&targetNums); -+ -+ GList* targetList = nullptr; -+ for (int i = 0; i < targetNums; i++) { -+ targetList = g_list_append(targetList, GDK_ATOM_TO_POINTER(atoms[i])); -+ } -+ -+ return targetList; -+} -+ -+char* -+nsWaylandDragContext::GetData(const char* aMimeType, uint32_t* aContentLength) -+{ -+ mDataOffer->DragOfferAccept(aMimeType, mTime); -+ return mDataOffer->GetData(mDisplay, aMimeType, aContentLength); -+} -+ -+void -+nsRetrievalContextWayland::RegisterNewDataOffer(wl_data_offer *aWaylandDataOffer) - { - DataOffer* dataOffer = - static_cast(g_hash_table_lookup(mActiveOffers, - aWaylandDataOffer)); -+ MOZ_ASSERT(dataOffer == nullptr, -+ "Registered WaylandDataOffer already exists. Wayland protocol error?"); -+ - if (!dataOffer) { - dataOffer = new WaylandDataOffer(aWaylandDataOffer); - g_hash_table_insert(mActiveOffers, aWaylandDataOffer, dataOffer); -@@ -259,12 +449,15 @@ nsRetrievalContextWayland::RegisterDataO + DataOffer* dataOffer = + static_cast(g_hash_table_lookup(mActiveOffers, + aWaylandDataOffer)); ++ MOZ_ASSERT(dataOffer == nullptr, ++ "Registered WaylandDataOffer already exists. Wayland protocol error?"); ++ + if (!dataOffer) { + dataOffer = new WaylandDataOffer(aWaylandDataOffer); + g_hash_table_insert(mActiveOffers, aWaylandDataOffer, dataOffer); +@@ -259,12 +449,15 @@ nsRetrievalContextWayland::RegisterDataO } void @@ -2914,7 +918,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland thunderbir return GetClipboardData(sTextMimeTypes[i], aWhichClipboard, diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h.wayland thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h --- thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h 2018-11-20 12:04:43.735787356 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h 2018-11-21 13:42:00.759025657 +0100 @@ -32,6 +32,7 @@ public: private: virtual bool RequestDataTransfer(const char* aMimeType, int fd) = 0; @@ -3021,52 +1025,9 @@ diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h.wayland thunderbird- int mClipboardRequestNumber; char* mClipboardData; -diff -up thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp.wayland thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp ---- thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp 2018-11-20 12:04:43.735787356 +0100 -@@ -33,6 +33,9 @@ - #include - #include - -+// To check if we need to use flatpak portal for printing -+#include "nsIGIOService.h" -+ - using namespace mozilla; - - using mozilla::gfx::IntSize; -@@ -355,6 +358,20 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::En - // If you're not familiar with umasks, they contain the bits of what NOT to set in the permissions - // (thats because files and directories have different numbers of bits for their permissions) - destFile->SetPermissions(0666 & ~(mask)); -+ -+ // Notify flatpak printing portal that file is completely written -+ nsCOMPtr giovfs = -+ do_GetService(NS_GIOSERVICE_CONTRACTID); -+ bool shouldUsePortal; -+ if (giovfs) { -+ giovfs->ShouldUseFlatpakPortal(&shouldUsePortal); -+ if (shouldUsePortal) { -+ // Use the name of the file for printing to match with nsFlatpakPrintPortal -+ nsCOMPtr os = mozilla::services::GetObserverService(); -+ // Pass filename to be sure that observer process the right data -+ os->NotifyObservers(nullptr, "print-to-file-finished", targetPath.get()); -+ } -+ } - } - return NS_OK; - } -@@ -421,7 +438,7 @@ nsPrinterEnumeratorGTK::InitPrintSetting - } - - if (path) { -- CopyUTF8toUTF16(path, filename); -+ CopyUTF8toUTF16(MakeStringSpan(path), filename); - filename.AppendLiteral("/mozilla.pdf"); - } else { - filename.AssignLiteral("mozilla.pdf"); diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60.3.0/widget/gtk/nsDragService.cpp --- thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsDragService.cpp 2018-11-20 12:04:43.736787353 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsDragService.cpp 2018-11-21 13:42:00.759025657 +0100 @@ -34,7 +34,6 @@ #include "nsPresContext.h" #include "nsIContent.h" @@ -3096,81 +1057,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. { // We have to destroy the hidden widget before the event loop stops // running. -@@ -179,7 +185,7 @@ nsDragService::Observe(nsISupports *aSub - } - TargetResetData(); - } else { -- NS_NOTREACHED("unexpected topic"); -+ MOZ_ASSERT_UNREACHABLE("unexpected topic"); - return NS_ERROR_UNEXPECTED; - } - -@@ -269,13 +275,12 @@ OnSourceGrabEventAfter(GtkWidget *widget - } - - static GtkWindow* --GetGtkWindow(nsIDOMDocument *aDocument) -+GetGtkWindow(nsIDocument *aDocument) - { -- nsCOMPtr doc = do_QueryInterface(aDocument); -- if (!doc) -+ if (!aDocument) - return nullptr; - -- nsCOMPtr presShell = doc->GetShell(); -+ nsCOMPtr presShell = aDocument->GetShell(); - if (!presShell) - return nullptr; - -@@ -304,10 +309,9 @@ GetGtkWindow(nsIDOMDocument *aDocument) - // nsIDragService - - NS_IMETHODIMP --nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, -+nsDragService::InvokeDragSession(nsINode *aDOMNode, - const nsACString& aPrincipalURISpec, - nsIArray * aArrayTransferables, -- nsIScriptableRegion * aRegion, - uint32_t aActionType, - nsContentPolicyType aContentPolicyType = - nsIContentPolicy::TYPE_OTHER) -@@ -323,14 +327,14 @@ nsDragService::InvokeDragSession(nsIDOMN - - return nsBaseDragService::InvokeDragSession(aDOMNode, aPrincipalURISpec, - aArrayTransferables, -- aRegion, aActionType, -+ aActionType, - aContentPolicyType); - } - - // nsBaseDragService - nsresult - nsDragService::InvokeDragSessionImpl(nsIArray* aArrayTransferables, -- nsIScriptableRegion* aRegion, -+ const Maybe& aRegion, - uint32_t aActionType) - { - // make sure that we have an array of transferables to use -@@ -346,9 +350,6 @@ nsDragService::InvokeDragSessionImpl(nsI - if (!sourceList) - return NS_OK; - -- // stored temporarily until the drag-begin signal has been received -- mSourceRegion = aRegion; -- - // save our action type - GdkDragAction action = GDK_ACTION_DEFAULT; - -@@ -391,8 +392,6 @@ nsDragService::InvokeDragSessionImpl(nsI - 1, - &event); - -- mSourceRegion = nullptr; -- - nsresult rv; - if (context) { - StartDragSession(); -@@ -516,6 +515,9 @@ nsDragService::EndDragSession(bool aDone +@@ -516,6 +522,9 @@ nsDragService::EndDragSession(bool aDone // We're done with the drag context. mTargetDragContextForRemote = nullptr; @@ -3180,7 +1067,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. return nsBaseDragService::EndDragSession(aDoneDrag, aKeyModifiers); } -@@ -636,6 +638,14 @@ nsDragService::GetNumDropItems(uint32_t +@@ -636,6 +645,14 @@ nsDragService::GetNumDropItems(uint32_t return NS_OK; } @@ -3195,7 +1082,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. bool isList = IsTargetContextList(); if (isList) mSourceDataItems->GetLength(aNumItems); -@@ -1027,9 +1037,18 @@ nsDragService::IsDataFlavorSupported(con +@@ -1027,9 +1044,18 @@ nsDragService::IsDataFlavorSupported(con } // check the target context vs. this flavor, one at a time @@ -3217,7 +1104,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. /* Bug 331198 */ GdkAtom atom = GDK_POINTER_TO_ATOM(tmp->data); gchar *name = nullptr; -@@ -1074,6 +1093,15 @@ nsDragService::IsDataFlavorSupported(con +@@ -1074,6 +1100,15 @@ nsDragService::IsDataFlavorSupported(con } g_free(name); } @@ -3233,7 +1120,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. return NS_OK; } -@@ -1105,6 +1133,36 @@ nsDragService::ReplyToDragMotion(GdkDrag +@@ -1105,6 +1140,36 @@ nsDragService::ReplyToDragMotion(GdkDrag gdk_drag_status(aDragContext, action, mTargetTime); } @@ -3270,7 +1157,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. void nsDragService::TargetDataReceived(GtkWidget *aWidget, GdkDragContext *aContext, -@@ -1136,6 +1194,12 @@ nsDragService::IsTargetContextList(void) +@@ -1136,6 +1201,12 @@ nsDragService::IsTargetContextList(void) { bool retval = false; @@ -3283,7 +1170,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // gMimeListType drags only work for drags within a single process. The // gtk_drag_get_source_widget() function will return nullptr if the source // of the drag is another app, so we use it to check if a gMimeListType -@@ -1174,17 +1238,28 @@ nsDragService::GetTargetDragData(GdkAtom +@@ -1174,17 +1245,28 @@ nsDragService::GetTargetDragData(GdkAtom mTargetDragContext.get())); // reset our target data areas TargetResetData(); @@ -3321,7 +1208,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. MOZ_LOG(sDragLm, LogLevel::Debug, ("finished inner iteration\n")); } -@@ -1435,7 +1510,7 @@ nsDragService::SourceEndDragSession(GdkD +@@ -1435,7 +1517,7 @@ nsDragService::SourceEndDragSession(GdkD } // Schedule the appropriate drag end dom events. @@ -3330,18 +1217,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. } static void -@@ -1642,8 +1717,8 @@ void nsDragService::SetDragIcon(GdkDragC - LayoutDeviceIntRect dragRect; - nsPresContext* pc; - RefPtr surface; -- DrawDrag(mSourceNode, mSourceRegion, mScreenPosition, -- &dragRect, &surface, &pc); -+ DrawDrag(mSourceNode, mRegion, -+ mScreenPosition, &dragRect, &surface, &pc); - if (!pc) - return; - -@@ -1785,9 +1860,10 @@ invisibleSourceDragEnd(GtkWidget +@@ -1785,9 +1867,10 @@ invisibleSourceDragEnd(GtkWidget gboolean nsDragService::ScheduleMotionEvent(nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3353,7 +1229,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // The drag source has sent another motion message before we've // replied to the previous. That shouldn't happen with Xdnd. The // spec for Motif drags is less clear, but we'll just update the -@@ -1798,7 +1874,7 @@ nsDragService::ScheduleMotionEvent(nsWin +@@ -1798,7 +1881,7 @@ nsDragService::ScheduleMotionEvent(nsWin // Returning TRUE means we'll reply with a status message, unless we first // get a leave. @@ -3362,7 +1238,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. aWindowPoint, aTime); } -@@ -1808,7 +1884,8 @@ nsDragService::ScheduleLeaveEvent() +@@ -1808,7 +1891,8 @@ nsDragService::ScheduleLeaveEvent() // We don't know at this stage whether a drop signal will immediately // follow. If the drop signal gets sent it will happen before we return // to the main loop and the scheduled leave task will be replaced. @@ -3372,7 +1248,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. NS_WARNING("Drag leave after drop"); } } -@@ -1816,10 +1893,11 @@ nsDragService::ScheduleLeaveEvent() +@@ -1816,10 +1900,11 @@ nsDragService::ScheduleLeaveEvent() gboolean nsDragService::ScheduleDropEvent(nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3385,7 +1261,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. NS_WARNING("Additional drag drop ignored"); return FALSE; } -@@ -1833,6 +1911,7 @@ nsDragService::ScheduleDropEvent(nsWindo +@@ -1833,6 +1918,7 @@ nsDragService::ScheduleDropEvent(nsWindo gboolean nsDragService::Schedule(DragTask aTask, nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3393,7 +1269,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. LayoutDeviceIntPoint aWindowPoint, guint aTime) { // If there is an existing leave or motion task scheduled, then that -@@ -1851,6 +1930,9 @@ nsDragService::Schedule(DragTask aTask, +@@ -1851,6 +1937,9 @@ nsDragService::Schedule(DragTask aTask, mScheduledTask = aTask; mPendingWindow = aWindow; mPendingDragContext = aDragContext; @@ -3403,7 +1279,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. mPendingWindowPoint = aWindowPoint; mPendingTime = aTime; -@@ -1927,6 +2009,9 @@ nsDragService::RunScheduledTask() +@@ -1927,6 +2016,9 @@ nsDragService::RunScheduledTask() // succeeed. mTargetWidget = mTargetWindow->GetMozContainerWidget(); mTargetDragContext.steal(mPendingDragContext); @@ -3413,7 +1289,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. mTargetTime = mPendingTime; // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model -@@ -1958,10 +2043,20 @@ nsDragService::RunScheduledTask() +@@ -1958,10 +2050,20 @@ nsDragService::RunScheduledTask() if (task == eDragTaskMotion) { if (TakeDragEventDispatchedToChildProcess()) { mTargetDragContextForRemote = mTargetDragContext; @@ -3435,7 +1311,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. } } } -@@ -1972,8 +2067,10 @@ nsDragService::RunScheduledTask() +@@ -1972,8 +2074,10 @@ nsDragService::RunScheduledTask() // Perhaps we should set the del parameter to TRUE when the drag // action is move, but we don't know whether the data was successfully // transferred. @@ -3448,7 +1324,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // This drag is over, so clear out our reference to the previous // window. -@@ -1986,6 +2083,9 @@ nsDragService::RunScheduledTask() +@@ -1986,6 +2090,9 @@ nsDragService::RunScheduledTask() // We're done with the drag context. mTargetWidget = nullptr; mTargetDragContext = nullptr; @@ -3458,7 +1334,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // If we got another drag signal while running the sheduled task, that // must have happened while running a nested event loop. Leave the task -@@ -2015,7 +2115,16 @@ nsDragService::UpdateDragAction() +@@ -2015,7 +2122,16 @@ nsDragService::UpdateDragAction() // default is to do nothing int action = nsIDragService::DRAGDROP_ACTION_NONE; @@ -3476,7 +1352,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // set the default just in case nothing matches below if (gdkAction & GDK_ACTION_DEFAULT) -@@ -2044,6 +2153,12 @@ nsDragService::UpdateDragEffect() +@@ -2044,6 +2160,12 @@ nsDragService::UpdateDragEffect() ReplyToDragMotion(mTargetDragContextForRemote); mTargetDragContextForRemote = nullptr; } @@ -3491,7 +1367,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3.0/widget/gtk/nsDragService.h --- thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland 2018-10-30 12:45:37.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsDragService.h 2018-11-20 12:04:43.736787353 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsDragService.h 2018-11-21 13:42:00.759025657 +0100 @@ -14,6 +14,7 @@ #include @@ -3500,23 +1376,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. namespace mozilla { namespace gfx { -@@ -60,13 +61,12 @@ public: - - // nsBaseDragService - virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables, -- nsIScriptableRegion* aRegion, -+ const mozilla::Maybe& aRegion, - uint32_t aActionType) override; - // nsIDragService -- NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, -+ NS_IMETHOD InvokeDragSession (nsINode *aDOMNode, - const nsACString& aPrincipalURISpec, - nsIArray * anArrayTransferables, -- nsIScriptableRegion * aRegion, - uint32_t aActionType, - nsContentPolicyType aContentPolicyType) override; - NS_IMETHOD StartDragSession() override; -@@ -98,11 +98,13 @@ public: +@@ -98,11 +99,13 @@ public: gboolean ScheduleMotionEvent(nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3530,7 +1390,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime); -@@ -158,6 +160,9 @@ private: +@@ -158,6 +161,9 @@ private: RefPtr mPendingWindow; mozilla::LayoutDeviceIntPoint mPendingWindowPoint; nsCountedRef mPendingDragContext; @@ -3540,7 +1400,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. guint mPendingTime; // mTargetWindow and mTargetWindowPoint record the position of the last -@@ -169,9 +174,15 @@ private: +@@ -169,9 +175,15 @@ private: // motion or drop events. mTime records the corresponding timestamp. nsCountedRef mTargetWidget; nsCountedRef mTargetDragContext; @@ -3556,16 +1416,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. guint mTargetTime; // is it OK to drop on us? -@@ -197,8 +208,6 @@ private: - // our source data items - nsCOMPtr mSourceDataItems; - -- nsCOMPtr mSourceRegion; -- - // get a list of the sources in gtk's format - GtkTargetList *GetSourceList(void); - -@@ -212,6 +221,7 @@ private: +@@ -212,6 +224,7 @@ private: gboolean Schedule(DragTask aTask, nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3573,7 +1424,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime); // Callback for g_idle_add_full() to run mScheduledTask. -@@ -220,9 +230,11 @@ private: +@@ -220,9 +233,11 @@ private: void UpdateDragAction(); void DispatchMotionEvents(); void ReplyToDragMotion(GdkDragContext* aDragContext); @@ -3586,21 +1437,9 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. #endif // nsDragService_h__ - -diff -up thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp.wayland thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp ---- thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp 2018-11-20 12:04:43.736787353 +0100 -@@ -346,7 +346,7 @@ nsFilePicker::GetFiles(nsISimpleEnumerat - NS_ENSURE_ARG_POINTER(aFiles); - - if (mMode == nsIFilePicker::modeOpenMultiple) { -- return NS_NewArrayEnumerator(aFiles, mFiles); -+ return NS_NewArrayEnumerator(aFiles, mFiles, NS_GET_IID(nsIFile)); - } - - return NS_ERROR_FAILURE; diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp --- thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp 2018-11-20 12:04:43.736787353 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp 2018-11-21 13:42:00.760025653 +0100 @@ -28,6 +28,10 @@ #include "mozilla/MouseEvents.h" #include "mozilla/TextEvents.h" @@ -3847,44 +1686,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland thunderbird-60. KeymapWrapper::~KeymapWrapper() { gdk_window_remove_filter(nullptr, FilterEvents, this); -@@ -931,14 +1141,19 @@ KeymapWrapper::ComputeDOMCodeNameIndex(c - - /* static */ void - KeymapWrapper::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, -- GdkEventKey* aGdkKeyEvent) -+ GdkEventKey* aGdkKeyEvent, -+ bool aIsProcessedByIME) - { -+ MOZ_ASSERT(!aIsProcessedByIME || aKeyEvent.mMessage != eKeyPress, -+ "If the key event is handled by IME, keypress event shouldn't be fired"); -+ - KeymapWrapper* keymapWrapper = GetInstance(); - - aKeyEvent.mCodeNameIndex = ComputeDOMCodeNameIndex(aGdkKeyEvent); - MOZ_ASSERT(aKeyEvent.mCodeNameIndex != CODE_NAME_INDEX_USE_STRING); - aKeyEvent.mKeyNameIndex = -- keymapWrapper->ComputeDOMKeyNameIndex(aGdkKeyEvent); -+ aIsProcessedByIME ? KEY_NAME_INDEX_Process : -+ keymapWrapper->ComputeDOMKeyNameIndex(aGdkKeyEvent); - if (aKeyEvent.mKeyNameIndex == KEY_NAME_INDEX_Unidentified) { - uint32_t charCode = GetCharCodeFor(aGdkKeyEvent); - if (!charCode) { -@@ -951,10 +1166,11 @@ KeymapWrapper::InitKeyEvent(WidgetKeyboa - AppendUCS4ToUTF16(charCode, aKeyEvent.mKeyValue); - } - } -- aKeyEvent.mKeyCode = ComputeDOMKeyCode(aGdkKeyEvent); - -- if (aKeyEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING || -- aKeyEvent.mMessage != eKeyPress) { -+ if (aIsProcessedByIME) { -+ aKeyEvent.mKeyCode = NS_VK_PROCESSKEY; -+ } else if (aKeyEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING || -+ aKeyEvent.mMessage != eKeyPress) { - aKeyEvent.mKeyCode = ComputeDOMKeyCode(aGdkKeyEvent); - } else { - aKeyEvent.mKeyCode = 0; -@@ -1405,6 +1621,14 @@ void +@@ -1405,6 +1615,14 @@ void KeymapWrapper::WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent, GdkEventKey* aGdkKeyEvent) { @@ -3901,7 +1703,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland thunderbird-60. MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h --- thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h 2018-11-20 12:04:43.737787350 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h 2018-11-21 13:42:00.760025653 +0100 @@ -13,6 +13,10 @@ #include @@ -3913,20 +1715,15 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.3. namespace mozilla { namespace widget { -@@ -131,9 +135,11 @@ public: +@@ -131,6 +135,7 @@ public: * @param aKeyEvent It's an WidgetKeyboardEvent which needs to be * initialized. * @param aGdkKeyEvent A native GDK key event. + * @param aIsProcessedByIME true if aGdkKeyEvent is handled by IME. */ static void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, -- GdkEventKey* aGdkKeyEvent); -+ GdkEventKey* aGdkKeyEvent, -+ bool aIsProcessedByIME); - - /** - * WillDispatchKeyboardEvent() is called via -@@ -148,6 +154,14 @@ public: + GdkEventKey* aGdkKeyEvent); +@@ -148,6 +153,14 @@ public: static void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyEvent, GdkEventKey* aGdkKeyEvent); @@ -3941,2101 +1738,175 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.3. /** * Destroys the singleton KeymapWrapper instance, if it exists. */ -@@ -172,7 +186,10 @@ protected: - */ - void Init(); - void InitXKBExtension(); -- void InitBySystemSettings(); -+ void InitBySystemSettingsX11(); -+#ifdef MOZ_WAYLAND -+ void InitBySystemSettingsWayland(); -+#endif - - /** - * mModifierKeys stores each hardware key information. -@@ -374,6 +391,15 @@ protected: - */ - void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent, - GdkEventKey* aGdkKeyEvent); -+ -+#ifdef MOZ_WAYLAND -+ /** -+ * Utility function to set Xkb modifier key mask. -+ */ -+ void SetModifierMask(xkb_keymap *aKeymap, -+ ModifierIndex aModifierIndex, -+ const char* aModifierName); -+#endif - }; - - } // namespace widget -diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp ---- thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp 2018-11-20 12:04:43.737787350 +0100 -@@ -18,6 +18,7 @@ - - #include - #include "gfxPlatformGtk.h" -+#include "mozilla/FontPropertyTypes.h" - #include "ScreenHelperGTK.h" - - #include "gtkdrawing.h" -@@ -31,7 +32,9 @@ - #include - #include "WidgetStyleCache.h" - #include "prenv.h" -+#include "nsCSSColorUtils.h" - -+using namespace mozilla; - using mozilla::LookAndFeel; - - #define GDK_COLOR_TO_NS_RGB(c) \ -@@ -182,7 +185,7 @@ GetBorderColors(GtkStyleContext* aContex - // GTK has an initial value of zero for border-widths, and so themes - // need to explicitly set border-widths to make borders visible. - GtkBorder border; -- gtk_style_context_get_border(aContext, GTK_STATE_FLAG_NORMAL, &border); -+ gtk_style_context_get_border(aContext, state, &border); - visible = border.top != 0 || border.right != 0 || - border.bottom != 0 || border.left != 0; - } -@@ -213,6 +216,58 @@ GetBorderColors(GtkStyleContext* aContex - return ret; - } - -+// Finds ideal cell highlight colors used for unfocused+selected cells distinct -+// from both Highlight, used as focused+selected background, and the listbox -+// background which is assumed to be similar to -moz-field -+nsresult -+nsLookAndFeel::InitCellHighlightColors() { -+ // NS_SUFFICIENT_LUMINOSITY_DIFFERENCE is the a11y standard for text -+ // on a background. Use 20% of that standard since we have a background -+ // on top of another background -+ int32_t minLuminosityDifference = NS_SUFFICIENT_LUMINOSITY_DIFFERENCE / 5; -+ int32_t backLuminosityDifference = NS_LUMINOSITY_DIFFERENCE( -+ mMozWindowBackground, mMozFieldBackground); -+ if (backLuminosityDifference >= minLuminosityDifference) { -+ mMozCellHighlightBackground = mMozWindowBackground; -+ mMozCellHighlightText = mMozWindowText; -+ return NS_OK; -+ } -+ -+ uint16_t hue, sat, luminance; -+ uint8_t alpha; -+ mMozCellHighlightBackground = mMozFieldBackground; -+ mMozCellHighlightText = mMozFieldText; -+ -+ NS_RGB2HSV(mMozCellHighlightBackground, hue, sat, luminance, alpha); -+ -+ uint16_t step = 30; -+ // Lighten the color if the color is very dark -+ if (luminance <= step) { -+ luminance += step; -+ } -+ // Darken it if it is very light -+ else if (luminance >= 255 - step) { -+ luminance -= step; -+ } -+ // Otherwise, compute what works best depending on the text luminance. -+ else { -+ uint16_t textHue, textSat, textLuminance; -+ uint8_t textAlpha; -+ NS_RGB2HSV(mMozCellHighlightText, textHue, textSat, textLuminance, -+ textAlpha); -+ // Text is darker than background, use a lighter shade -+ if (textLuminance < luminance) { -+ luminance += step; -+ } -+ // Otherwise, use a darker shade -+ else { -+ luminance -= step; -+ } -+ } -+ NS_HSV2RGB(mMozCellHighlightBackground, hue, sat, luminance, alpha); -+ return NS_OK; -+} -+ - void - nsLookAndFeel::NativeInit() - { -@@ -269,7 +324,6 @@ nsLookAndFeel::NativeGetColor(ColorID aI - case eColorID_IMESelectedRawTextBackground: - case eColorID_IMESelectedConvertedTextBackground: - case eColorID__moz_dragtargetzone: -- case eColorID__moz_cellhighlight: - case eColorID__moz_html_cellhighlight: - case eColorID_highlight: // preference selected item, - aColor = mTextSelectedBackground; -@@ -279,10 +333,15 @@ nsLookAndFeel::NativeGetColor(ColorID aI - case eColorID_IMESelectedRawTextForeground: - case eColorID_IMESelectedConvertedTextForeground: - case eColorID_highlighttext: -- case eColorID__moz_cellhighlighttext: - case eColorID__moz_html_cellhighlighttext: - aColor = mTextSelectedText; - break; -+ case eColorID__moz_cellhighlight: -+ aColor = mMozCellHighlightBackground; -+ break; -+ case eColorID__moz_cellhighlighttext: -+ aColor = mMozCellHighlightText; -+ break; - case eColorID_Widget3DHighlight: - aColor = NS_RGB(0xa0,0xa0,0xa0); - break; -@@ -668,6 +727,17 @@ nsLookAndFeel::GetIntImpl(IntID aID, int - EnsureInit(); - aResult = mCSDCloseButton; - break; -+ case eIntID_PrefersReducedMotion: { -+ GtkSettings *settings; -+ gboolean enableAnimations; -+ -+ settings = gtk_settings_get_default(); -+ g_object_get(settings, -+ "gtk-enable-animations", -+ &enableAnimations, nullptr); -+ aResult = enableAnimations ? 0 : 1; -+ break; -+ } - default: - aResult = 0; - res = NS_ERROR_FAILURE; -@@ -708,7 +778,7 @@ GetSystemFontInfo(GtkStyleContext *aStyl - nsString *aFontName, - gfxFontStyle *aFontStyle) - { -- aFontStyle->style = NS_FONT_STYLE_NORMAL; -+ aFontStyle->style = FontSlantStyle::Normal(); - - // As in - // https://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?h=3.22.19#n10333 -@@ -722,10 +792,10 @@ GetSystemFontInfo(GtkStyleContext *aStyl - NS_ConvertUTF8toUTF16 family(pango_font_description_get_family(desc)); - *aFontName = quote + family + quote; - -- aFontStyle->weight = pango_font_description_get_weight(desc); -+ aFontStyle->weight = FontWeight(pango_font_description_get_weight(desc)); - - // FIXME: Set aFontStyle->stretch correctly! -- aFontStyle->stretch = NS_FONT_STRETCH_NORMAL; -+ aFontStyle->stretch = FontStretch::Normal(); - - float size = float(pango_font_description_get_size(desc)) / PANGO_SCALE; - -@@ -1009,6 +1079,9 @@ nsLookAndFeel::EnsureInit() - mOddCellBackground = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_restore(style); - -+ // Compute cell highlight colors -+ InitCellHighlightColors(); -+ - // GtkFrame has a "border" subnode on which Adwaita draws the border. - // Some themes do not draw on this node but draw a border on the widget - // root node, so check the root node if no border is found on the border -diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h.wayland thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h ---- thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h 2018-11-20 12:04:43.737787350 +0100 -@@ -77,6 +77,8 @@ protected: - nscolor mMozWindowActiveBorder; - nscolor mMozWindowInactiveBorder; - nscolor mMozWindowInactiveCaption; -+ nscolor mMozCellHighlightBackground; -+ nscolor mMozCellHighlightText; - nscolor mTextSelectedText; - nscolor mTextSelectedBackground; - nscolor mMozScrollbar; -@@ -91,6 +93,9 @@ protected: - bool mInitialized; - - void EnsureInit(); -+ -+private: -+ nsresult InitCellHighlightColors(); - }; - - #endif -diff -up thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp.wayland thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp ---- thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp 2018-11-20 12:04:43.738787347 +0100 -@@ -4,7 +4,7 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - #include "nsNativeThemeGTK.h" --#include "nsThemeConstants.h" -+#include "nsStyleConsts.h" - #include "gtkdrawing.h" - #include "ScreenHelperGTK.h" - -@@ -39,6 +39,8 @@ - #include "mozilla/gfx/HelpersCairo.h" - #include "mozilla/gfx/PathHelpers.h" - #include "mozilla/Preferences.h" -+#include "mozilla/layers/StackingContextHelper.h" -+#include "mozilla/StaticPrefs.h" - - #ifdef MOZ_X11 - # ifdef CAIRO_HAS_XLIB_SURFACE -@@ -119,7 +121,7 @@ nsNativeThemeGTK::Observe(nsISupports *a - if (!nsCRT::strcmp(aTopic, "xpcom-shutdown")) { - moz_gtk_shutdown(); - } else { -- NS_NOTREACHED("unexpected topic"); -+ MOZ_ASSERT_UNREACHABLE("unexpected topic"); - return NS_ERROR_UNEXPECTED; - } - -@@ -149,41 +151,43 @@ static bool IsFrameContentNodeInNamespac - return content->IsInNamespace(aNamespace); - } - --static bool IsWidgetTypeDisabled(uint8_t* aDisabledVector, uint8_t aWidgetType) { -- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); -- return (aDisabledVector[aWidgetType >> 3] & (1 << (aWidgetType & 7))) != 0; -+static bool IsWidgetTypeDisabled(uint8_t* aDisabledVector, StyleAppearance aWidgetType) { -+ auto type = static_cast(aWidgetType); -+ MOZ_ASSERT(type < static_cast(mozilla::StyleAppearance::Count)); -+ return (aDisabledVector[type >> 3] & (1 << (type & 7))) != 0; - } - --static void SetWidgetTypeDisabled(uint8_t* aDisabledVector, uint8_t aWidgetType) { -- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); -- aDisabledVector[aWidgetType >> 3] |= (1 << (aWidgetType & 7)); -+static void SetWidgetTypeDisabled(uint8_t* aDisabledVector, StyleAppearance aWidgetType) { -+ auto type = static_cast(aWidgetType); -+ MOZ_ASSERT(type < static_cast(mozilla::StyleAppearance::Count)); -+ aDisabledVector[type >> 3] |= (1 << (type & 7)); - } - - static inline uint16_t --GetWidgetStateKey(uint8_t aWidgetType, GtkWidgetState *aWidgetState) -+GetWidgetStateKey(StyleAppearance aWidgetType, GtkWidgetState *aWidgetState) - { - return (aWidgetState->active | - aWidgetState->focused << 1 | - aWidgetState->inHover << 2 | - aWidgetState->disabled << 3 | - aWidgetState->isDefault << 4 | -- aWidgetType << 5); -+ static_cast(aWidgetType) << 5); - } - - static bool IsWidgetStateSafe(uint8_t* aSafeVector, -- uint8_t aWidgetType, -- GtkWidgetState *aWidgetState) -+ StyleAppearance aWidgetType, -+ GtkWidgetState *aWidgetState) - { -- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); -+ MOZ_ASSERT(static_cast(aWidgetType) < static_cast(mozilla::StyleAppearance::Count)); - uint16_t key = GetWidgetStateKey(aWidgetType, aWidgetState); - return (aSafeVector[key >> 3] & (1 << (key & 7))) != 0; - } - - static void SetWidgetStateSafe(uint8_t *aSafeVector, -- uint8_t aWidgetType, -+ StyleAppearance aWidgetType, - GtkWidgetState *aWidgetState) - { -- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); -+ MOZ_ASSERT(static_cast(aWidgetType) < static_cast(mozilla::StyleAppearance::Count)); - uint16_t key = GetWidgetStateKey(aWidgetType, aWidgetState); - aSafeVector[key >> 3] |= (1 << (key & 7)); - } -@@ -213,33 +217,38 @@ nsNativeThemeGTK::GetTabMarginPixels(nsI - } - - static bool ShouldScrollbarButtonBeDisabled(int32_t aCurpos, int32_t aMaxpos, -- uint8_t aWidgetType) -+ StyleAppearance aWidgetType) - { -- return ((aCurpos == 0 && (aWidgetType == NS_THEME_SCROLLBARBUTTON_UP || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT)) -- || (aCurpos == aMaxpos && (aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT))); -+ return ((aCurpos == 0 && (aWidgetType == StyleAppearance::ScrollbarbuttonUp || -+ aWidgetType == StyleAppearance::ScrollbarbuttonLeft)) -+ || (aCurpos == aMaxpos && (aWidgetType == StyleAppearance::ScrollbarbuttonDown || -+ aWidgetType == StyleAppearance::ScrollbarbuttonRight))); - } - - bool --nsNativeThemeGTK::GetGtkWidgetAndState(uint8_t aWidgetType, nsIFrame* aFrame, -+nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aWidgetType, nsIFrame* aFrame, - WidgetNodeType& aGtkWidgetType, - GtkWidgetState* aState, - gint* aWidgetFlags) - { -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } -+ - if (aState) { - // For XUL checkboxes and radio buttons, the state of the parent - // determines our state. - nsIFrame *stateFrame = aFrame; -- if (aFrame && ((aWidgetFlags && (aWidgetType == NS_THEME_CHECKBOX || -- aWidgetType == NS_THEME_RADIO)) || -- aWidgetType == NS_THEME_CHECKBOX_LABEL || -- aWidgetType == NS_THEME_RADIO_LABEL)) { -+ if (aFrame && ((aWidgetFlags && (aWidgetType == StyleAppearance::Checkbox || -+ aWidgetType == StyleAppearance::Radio)) || -+ aWidgetType == StyleAppearance::CheckboxLabel || -+ aWidgetType == StyleAppearance::RadioLabel)) { - - nsAtom* atom = nullptr; - if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) { -- if (aWidgetType == NS_THEME_CHECKBOX_LABEL || -- aWidgetType == NS_THEME_RADIO_LABEL) { -+ if (aWidgetType == StyleAppearance::CheckboxLabel || -+ aWidgetType == StyleAppearance::RadioLabel) { - // Adjust stateFrame so GetContentState finds the correct state. - stateFrame = aFrame = aFrame->GetParent()->GetParent(); - } else { -@@ -249,8 +258,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - if (aWidgetFlags) { - if (!atom) { -- atom = (aWidgetType == NS_THEME_CHECKBOX || -- aWidgetType == NS_THEME_CHECKBOX_LABEL) ? nsGkAtoms::checked -+ atom = (aWidgetType == StyleAppearance::Checkbox || -+ aWidgetType == StyleAppearance::CheckboxLabel) ? nsGkAtoms::checked - : nsGkAtoms::selected; - } - *aWidgetFlags = CheckBooleanAttr(aFrame, atom); -@@ -258,7 +267,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } else { - if (aWidgetFlags) { - *aWidgetFlags = 0; -- HTMLInputElement* inputElt = HTMLInputElement::FromContent(aFrame->GetContent()); -+ HTMLInputElement* inputElt = HTMLInputElement::FromNode(aFrame->GetContent()); - if (inputElt && inputElt->Checked()) - *aWidgetFlags |= MOZ_GTK_WIDGET_CHECKED; - -@@ -266,12 +275,12 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - *aWidgetFlags |= MOZ_GTK_WIDGET_INCONSISTENT; - } - } -- } else if (aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN || -- aWidgetType == NS_THEME_TREEHEADERSORTARROW || -- aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS || -- aWidgetType == NS_THEME_BUTTON_ARROW_NEXT || -- aWidgetType == NS_THEME_BUTTON_ARROW_UP || -- aWidgetType == NS_THEME_BUTTON_ARROW_DOWN) { -+ } else if (aWidgetType == StyleAppearance::ToolbarbuttonDropdown || -+ aWidgetType == StyleAppearance::Treeheadersortarrow || -+ aWidgetType == StyleAppearance::ButtonArrowPrevious || -+ aWidgetType == StyleAppearance::ButtonArrowNext || -+ aWidgetType == StyleAppearance::ButtonArrowUp || -+ aWidgetType == StyleAppearance::ButtonArrowDown) { - // The state of an arrow comes from its parent. - stateFrame = aFrame = aFrame->GetParent(); - } -@@ -287,7 +296,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - aState->canDefault = FALSE; // XXX fix me - aState->depressed = FALSE; - -- if (aWidgetType == NS_THEME_FOCUS_OUTLINE) { -+ if (aWidgetType == StyleAppearance::FocusOutline) { - aState->disabled = FALSE; - aState->active = FALSE; - aState->inHover = FALSE; -@@ -296,15 +305,16 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - aState->focused = TRUE; - aState->depressed = TRUE; // see moz_gtk_entry_paint() -- } else if (aWidgetType == NS_THEME_BUTTON || -- aWidgetType == NS_THEME_TOOLBARBUTTON || -- aWidgetType == NS_THEME_DUALBUTTON || -- aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN || -- aWidgetType == NS_THEME_MENULIST || -- aWidgetType == NS_THEME_MENULIST_BUTTON) { -+ } else if (aWidgetType == StyleAppearance::Button || -+ aWidgetType == StyleAppearance::Toolbarbutton || -+ aWidgetType == StyleAppearance::Dualbutton || -+ aWidgetType == StyleAppearance::ToolbarbuttonDropdown || -+ aWidgetType == StyleAppearance::Menulist || -+ aWidgetType == StyleAppearance::MenulistButton || -+ aWidgetType == StyleAppearance::MozMenulistButton) { - aState->active &= aState->inHover; -- } else if (aWidgetType == NS_THEME_TREETWISTY || -- aWidgetType == NS_THEME_TREETWISTYOPEN) { -+ } else if (aWidgetType == StyleAppearance::Treetwisty || -+ aWidgetType == StyleAppearance::Treetwistyopen) { - nsTreeBodyFrame *treeBodyFrame = do_QueryFrame(aFrame); - if (treeBodyFrame) { - const mozilla::AtomArray& atoms = -@@ -318,22 +328,22 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - // For these widget types, some element (either a child or parent) - // actually has element focus, so we check the focused attribute - // to see whether to draw in the focused state. -- if (aWidgetType == NS_THEME_NUMBER_INPUT || -- aWidgetType == NS_THEME_TEXTFIELD || -- aWidgetType == NS_THEME_TEXTFIELD_MULTILINE || -- aWidgetType == NS_THEME_MENULIST_TEXTFIELD || -- aWidgetType == NS_THEME_SPINNER_TEXTFIELD || -- aWidgetType == NS_THEME_RADIO_CONTAINER || -- aWidgetType == NS_THEME_RADIO_LABEL) { -+ if (aWidgetType == StyleAppearance::NumberInput || -+ aWidgetType == StyleAppearance::Textfield || -+ aWidgetType == StyleAppearance::TextfieldMultiline || -+ aWidgetType == StyleAppearance::MenulistTextfield || -+ aWidgetType == StyleAppearance::SpinnerTextfield || -+ aWidgetType == StyleAppearance::RadioContainer || -+ aWidgetType == StyleAppearance::RadioLabel) { - aState->focused = IsFocused(aFrame); -- } else if (aWidgetType == NS_THEME_RADIO || -- aWidgetType == NS_THEME_CHECKBOX) { -+ } else if (aWidgetType == StyleAppearance::Radio || -+ aWidgetType == StyleAppearance::Checkbox) { - // In XUL, checkboxes and radios shouldn't have focus rings, their labels do - aState->focused = FALSE; - } - -- if (aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL || -- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL) { -+ if (aWidgetType == StyleAppearance::ScrollbarthumbVertical || -+ aWidgetType == StyleAppearance::ScrollbarthumbHorizontal) { - // for scrollbars we need to go up two to go from the thumb to - // the slider to the actual scrollbar object - nsIFrame *tmpFrame = aFrame->GetParent()->GetParent(); -@@ -348,10 +358,10 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - } - -- if (aWidgetType == NS_THEME_SCROLLBARBUTTON_UP || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) { -+ if (aWidgetType == StyleAppearance::ScrollbarbuttonUp || -+ aWidgetType == StyleAppearance::ScrollbarbuttonDown || -+ aWidgetType == StyleAppearance::ScrollbarbuttonLeft || -+ aWidgetType == StyleAppearance::ScrollbarbuttonRight) { - // set the state to disabled when the scrollbar is scrolled to - // the beginning or the end, depending on the button type. - int32_t curpos = CheckIntAttr(aFrame, nsGkAtoms::curpos, 0); -@@ -369,7 +379,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - if (aWidgetFlags) { - *aWidgetFlags = GetScrollbarButtonType(aFrame); -- if (aWidgetType - NS_THEME_SCROLLBARBUTTON_UP < 2) -+ if (static_cast(aWidgetType) - -+ static_cast(StyleAppearance::ScrollbarbuttonUp) < 2) - *aWidgetFlags |= MOZ_GTK_STEPPER_VERTICAL; - } - } -@@ -379,11 +390,11 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - // menus which are children of a menu bar are only marked as prelight - // if they are open, not on normal hover. - -- if (aWidgetType == NS_THEME_MENUITEM || -- aWidgetType == NS_THEME_CHECKMENUITEM || -- aWidgetType == NS_THEME_RADIOMENUITEM || -- aWidgetType == NS_THEME_MENUSEPARATOR || -- aWidgetType == NS_THEME_MENUARROW) { -+ if (aWidgetType == StyleAppearance::Menuitem || -+ aWidgetType == StyleAppearance::Checkmenuitem || -+ aWidgetType == StyleAppearance::Radiomenuitem || -+ aWidgetType == StyleAppearance::Menuseparator || -+ aWidgetType == StyleAppearance::Menuarrow) { - bool isTopLevel = false; - nsMenuFrame *menuFrame = do_QueryFrame(aFrame); - if (menuFrame) { -@@ -398,8 +409,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - aState->active = FALSE; - -- if (aWidgetType == NS_THEME_CHECKMENUITEM || -- aWidgetType == NS_THEME_RADIOMENUITEM) { -+ if (aWidgetType == StyleAppearance::Checkmenuitem || -+ aWidgetType == StyleAppearance::Radiomenuitem) { - *aWidgetFlags = 0; - if (aFrame && aFrame->GetContent() && - aFrame->GetContent()->IsElement()) { -@@ -412,12 +423,13 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - // A button with drop down menu open or an activated toggle button - // should always appear depressed. -- if (aWidgetType == NS_THEME_BUTTON || -- aWidgetType == NS_THEME_TOOLBARBUTTON || -- aWidgetType == NS_THEME_DUALBUTTON || -- aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN || -- aWidgetType == NS_THEME_MENULIST || -- aWidgetType == NS_THEME_MENULIST_BUTTON) { -+ if (aWidgetType == StyleAppearance::Button || -+ aWidgetType == StyleAppearance::Toolbarbutton || -+ aWidgetType == StyleAppearance::Dualbutton || -+ aWidgetType == StyleAppearance::ToolbarbuttonDropdown || -+ aWidgetType == StyleAppearance::Menulist || -+ aWidgetType == StyleAppearance::MenulistButton || -+ aWidgetType == StyleAppearance::MozMenulistButton) { - bool menuOpen = IsOpenButton(aFrame); - aState->depressed = IsCheckedButton(aFrame) || menuOpen; - // we must not highlight buttons with open drop down menus on hover. -@@ -426,79 +438,81 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - // When the input field of the drop down button has focus, some themes - // should draw focus for the drop down button as well. -- if (aWidgetType == NS_THEME_MENULIST_BUTTON && aWidgetFlags) { -+ if ((aWidgetType == StyleAppearance::MenulistButton || -+ aWidgetType == StyleAppearance::MozMenulistButton) && -+ aWidgetFlags) { - *aWidgetFlags = CheckBooleanAttr(aFrame, nsGkAtoms::parentfocused); - } - } - } - - switch (aWidgetType) { -- case NS_THEME_BUTTON: -+ case StyleAppearance::Button: - if (aWidgetFlags) - *aWidgetFlags = GTK_RELIEF_NORMAL; - aGtkWidgetType = MOZ_GTK_BUTTON; - break; -- case NS_THEME_TOOLBARBUTTON: -- case NS_THEME_DUALBUTTON: -+ case StyleAppearance::Toolbarbutton: -+ case StyleAppearance::Dualbutton: - if (aWidgetFlags) - *aWidgetFlags = GTK_RELIEF_NONE; - aGtkWidgetType = MOZ_GTK_TOOLBAR_BUTTON; - break; -- case NS_THEME_FOCUS_OUTLINE: -+ case StyleAppearance::FocusOutline: - aGtkWidgetType = MOZ_GTK_ENTRY; - break; -- case NS_THEME_CHECKBOX: -- case NS_THEME_RADIO: -- aGtkWidgetType = (aWidgetType == NS_THEME_RADIO) ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON; -- break; -- case NS_THEME_SCROLLBARBUTTON_UP: -- case NS_THEME_SCROLLBARBUTTON_DOWN: -- case NS_THEME_SCROLLBARBUTTON_LEFT: -- case NS_THEME_SCROLLBARBUTTON_RIGHT: -+ case StyleAppearance::Checkbox: -+ case StyleAppearance::Radio: -+ aGtkWidgetType = (aWidgetType == StyleAppearance::Radio) ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON; -+ break; -+ case StyleAppearance::ScrollbarbuttonUp: -+ case StyleAppearance::ScrollbarbuttonDown: -+ case StyleAppearance::ScrollbarbuttonLeft: -+ case StyleAppearance::ScrollbarbuttonRight: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_BUTTON; - break; -- case NS_THEME_SCROLLBAR_VERTICAL: -+ case StyleAppearance::ScrollbarVertical: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_VERTICAL; - if (GetWidgetTransparency(aFrame, aWidgetType) == eOpaque) - *aWidgetFlags = MOZ_GTK_TRACK_OPAQUE; - else - *aWidgetFlags = 0; - break; -- case NS_THEME_SCROLLBAR_HORIZONTAL: -+ case StyleAppearance::ScrollbarHorizontal: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_HORIZONTAL; - if (GetWidgetTransparency(aFrame, aWidgetType) == eOpaque) - *aWidgetFlags = MOZ_GTK_TRACK_OPAQUE; - else - *aWidgetFlags = 0; - break; -- case NS_THEME_SCROLLBARTRACK_HORIZONTAL: -+ case StyleAppearance::ScrollbartrackHorizontal: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL; - break; -- case NS_THEME_SCROLLBARTRACK_VERTICAL: -+ case StyleAppearance::ScrollbartrackVertical: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL; - break; -- case NS_THEME_SCROLLBARTHUMB_VERTICAL: -+ case StyleAppearance::ScrollbarthumbVertical: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL; - break; -- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: -+ case StyleAppearance::ScrollbarthumbHorizontal: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; - break; -- case NS_THEME_INNER_SPIN_BUTTON: -+ case StyleAppearance::InnerSpinButton: - aGtkWidgetType = MOZ_GTK_INNER_SPIN_BUTTON; - break; -- case NS_THEME_SPINNER: -+ case StyleAppearance::Spinner: - aGtkWidgetType = MOZ_GTK_SPINBUTTON; - break; -- case NS_THEME_SPINNER_UPBUTTON: -+ case StyleAppearance::SpinnerUpbutton: - aGtkWidgetType = MOZ_GTK_SPINBUTTON_UP; - break; -- case NS_THEME_SPINNER_DOWNBUTTON: -+ case StyleAppearance::SpinnerDownbutton: - aGtkWidgetType = MOZ_GTK_SPINBUTTON_DOWN; - break; -- case NS_THEME_SPINNER_TEXTFIELD: -+ case StyleAppearance::SpinnerTextfield: - aGtkWidgetType = MOZ_GTK_SPINBUTTON_ENTRY; - break; -- case NS_THEME_RANGE: -+ case StyleAppearance::Range: - { - if (IsRangeHorizontal(aFrame)) { - if (aWidgetFlags) -@@ -511,7 +525,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - break; - } -- case NS_THEME_RANGE_THUMB: -+ case StyleAppearance::RangeThumb: - { - if (IsRangeHorizontal(aFrame)) { - if (aWidgetFlags) -@@ -524,51 +538,51 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - break; - } -- case NS_THEME_SCALE_HORIZONTAL: -+ case StyleAppearance::ScaleHorizontal: - if (aWidgetFlags) - *aWidgetFlags = GTK_ORIENTATION_HORIZONTAL; - aGtkWidgetType = MOZ_GTK_SCALE_HORIZONTAL; - break; -- case NS_THEME_SCALETHUMB_HORIZONTAL: -+ case StyleAppearance::ScalethumbHorizontal: - if (aWidgetFlags) - *aWidgetFlags = GTK_ORIENTATION_HORIZONTAL; - aGtkWidgetType = MOZ_GTK_SCALE_THUMB_HORIZONTAL; - break; -- case NS_THEME_SCALE_VERTICAL: -+ case StyleAppearance::ScaleVertical: - if (aWidgetFlags) - *aWidgetFlags = GTK_ORIENTATION_VERTICAL; - aGtkWidgetType = MOZ_GTK_SCALE_VERTICAL; - break; -- case NS_THEME_SEPARATOR: -+ case StyleAppearance::Separator: - aGtkWidgetType = MOZ_GTK_TOOLBAR_SEPARATOR; - break; -- case NS_THEME_SCALETHUMB_VERTICAL: -+ case StyleAppearance::ScalethumbVertical: - if (aWidgetFlags) - *aWidgetFlags = GTK_ORIENTATION_VERTICAL; - aGtkWidgetType = MOZ_GTK_SCALE_THUMB_VERTICAL; - break; -- case NS_THEME_TOOLBARGRIPPER: -+ case StyleAppearance::Toolbargripper: - aGtkWidgetType = MOZ_GTK_GRIPPER; - break; -- case NS_THEME_RESIZER: -+ case StyleAppearance::Resizer: - aGtkWidgetType = MOZ_GTK_RESIZER; - break; -- case NS_THEME_NUMBER_INPUT: -- case NS_THEME_TEXTFIELD: -+ case StyleAppearance::NumberInput: -+ case StyleAppearance::Textfield: - aGtkWidgetType = MOZ_GTK_ENTRY; - break; -- case NS_THEME_TEXTFIELD_MULTILINE: -+ case StyleAppearance::TextfieldMultiline: - #ifdef MOZ_WIDGET_GTK - aGtkWidgetType = MOZ_GTK_TEXT_VIEW; - #else - aGtkWidgetType = MOZ_GTK_ENTRY; - #endif - break; -- case NS_THEME_LISTBOX: -- case NS_THEME_TREEVIEW: -+ case StyleAppearance::Listbox: -+ case StyleAppearance::Treeview: - aGtkWidgetType = MOZ_GTK_TREEVIEW; - break; -- case NS_THEME_TREEHEADERCELL: -+ case StyleAppearance::Treeheadercell: - if (aWidgetFlags) { - // In this case, the flag denotes whether the header is the sorted one or not - if (GetTreeSortDirection(aFrame) == eTreeSortDirection_Natural) -@@ -578,7 +592,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - aGtkWidgetType = MOZ_GTK_TREE_HEADER_CELL; - break; -- case NS_THEME_TREEHEADERSORTARROW: -+ case StyleAppearance::Treeheadersortarrow: - if (aWidgetFlags) { - switch (GetTreeSortDirection(aFrame)) { - case eTreeSortDirection_Ascending: -@@ -598,74 +612,75 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - aGtkWidgetType = MOZ_GTK_TREE_HEADER_SORTARROW; - break; -- case NS_THEME_TREETWISTY: -+ case StyleAppearance::Treetwisty: - aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER; - if (aWidgetFlags) - *aWidgetFlags = GTK_EXPANDER_COLLAPSED; - break; -- case NS_THEME_TREETWISTYOPEN: -+ case StyleAppearance::Treetwistyopen: - aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER; - if (aWidgetFlags) - *aWidgetFlags = GTK_EXPANDER_EXPANDED; - break; -- case NS_THEME_MENULIST: -+ case StyleAppearance::Menulist: - aGtkWidgetType = MOZ_GTK_DROPDOWN; - if (aWidgetFlags) - *aWidgetFlags = IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XHTML); - break; -- case NS_THEME_MENULIST_TEXT: -+ case StyleAppearance::MenulistText: - return false; // nothing to do, but prevents the bg from being drawn -- case NS_THEME_MENULIST_TEXTFIELD: -+ case StyleAppearance::MenulistTextfield: - aGtkWidgetType = MOZ_GTK_DROPDOWN_ENTRY; - break; -- case NS_THEME_MENULIST_BUTTON: -+ case StyleAppearance::MenulistButton: -+ case StyleAppearance::MozMenulistButton: - aGtkWidgetType = MOZ_GTK_DROPDOWN_ARROW; - break; -- case NS_THEME_TOOLBARBUTTON_DROPDOWN: -- case NS_THEME_BUTTON_ARROW_DOWN: -- case NS_THEME_BUTTON_ARROW_UP: -- case NS_THEME_BUTTON_ARROW_NEXT: -- case NS_THEME_BUTTON_ARROW_PREVIOUS: -+ case StyleAppearance::ToolbarbuttonDropdown: -+ case StyleAppearance::ButtonArrowDown: -+ case StyleAppearance::ButtonArrowUp: -+ case StyleAppearance::ButtonArrowNext: -+ case StyleAppearance::ButtonArrowPrevious: - aGtkWidgetType = MOZ_GTK_TOOLBARBUTTON_ARROW; - if (aWidgetFlags) { - *aWidgetFlags = GTK_ARROW_DOWN; - -- if (aWidgetType == NS_THEME_BUTTON_ARROW_UP) -+ if (aWidgetType == StyleAppearance::ButtonArrowUp) - *aWidgetFlags = GTK_ARROW_UP; -- else if (aWidgetType == NS_THEME_BUTTON_ARROW_NEXT) -+ else if (aWidgetType == StyleAppearance::ButtonArrowNext) - *aWidgetFlags = GTK_ARROW_RIGHT; -- else if (aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS) -+ else if (aWidgetType == StyleAppearance::ButtonArrowPrevious) - *aWidgetFlags = GTK_ARROW_LEFT; - } - break; -- case NS_THEME_CHECKBOX_CONTAINER: -+ case StyleAppearance::CheckboxContainer: - aGtkWidgetType = MOZ_GTK_CHECKBUTTON_CONTAINER; - break; -- case NS_THEME_RADIO_CONTAINER: -+ case StyleAppearance::RadioContainer: - aGtkWidgetType = MOZ_GTK_RADIOBUTTON_CONTAINER; - break; -- case NS_THEME_CHECKBOX_LABEL: -+ case StyleAppearance::CheckboxLabel: - aGtkWidgetType = MOZ_GTK_CHECKBUTTON_LABEL; - break; -- case NS_THEME_RADIO_LABEL: -+ case StyleAppearance::RadioLabel: - aGtkWidgetType = MOZ_GTK_RADIOBUTTON_LABEL; - break; -- case NS_THEME_TOOLBAR: -+ case StyleAppearance::Toolbar: - aGtkWidgetType = MOZ_GTK_TOOLBAR; - break; -- case NS_THEME_TOOLTIP: -+ case StyleAppearance::Tooltip: - aGtkWidgetType = MOZ_GTK_TOOLTIP; - break; -- case NS_THEME_STATUSBARPANEL: -- case NS_THEME_RESIZERPANEL: -+ case StyleAppearance::Statusbarpanel: -+ case StyleAppearance::Resizerpanel: - aGtkWidgetType = MOZ_GTK_FRAME; - break; -- case NS_THEME_PROGRESSBAR: -- case NS_THEME_PROGRESSBAR_VERTICAL: -+ case StyleAppearance::Progressbar: -+ case StyleAppearance::ProgressbarVertical: - aGtkWidgetType = MOZ_GTK_PROGRESSBAR; - break; -- case NS_THEME_PROGRESSCHUNK: -- case NS_THEME_PROGRESSCHUNK_VERTICAL: -+ case StyleAppearance::Progresschunk: -+ case StyleAppearance::ProgresschunkVertical: - { - nsIFrame* stateFrame = aFrame->GetParent(); - EventStates eventStates = GetContentState(stateFrame, aWidgetType); -@@ -677,17 +692,17 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - : MOZ_GTK_PROGRESS_CHUNK; - } - break; -- case NS_THEME_TAB_SCROLL_ARROW_BACK: -- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: -+ case StyleAppearance::TabScrollArrowBack: -+ case StyleAppearance::TabScrollArrowForward: - if (aWidgetFlags) -- *aWidgetFlags = aWidgetType == NS_THEME_TAB_SCROLL_ARROW_BACK ? -+ *aWidgetFlags = aWidgetType == StyleAppearance::TabScrollArrowBack ? - GTK_ARROW_LEFT : GTK_ARROW_RIGHT; - aGtkWidgetType = MOZ_GTK_TAB_SCROLLARROW; - break; -- case NS_THEME_TABPANELS: -+ case StyleAppearance::Tabpanels: - aGtkWidgetType = MOZ_GTK_TABPANELS; - break; -- case NS_THEME_TAB: -+ case StyleAppearance::Tab: - { - if (IsBottomTab(aFrame)) { - aGtkWidgetType = MOZ_GTK_TAB_BOTTOM; -@@ -709,19 +724,19 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - } - break; -- case NS_THEME_SPLITTER: -+ case StyleAppearance::Splitter: - if (IsHorizontal(aFrame)) - aGtkWidgetType = MOZ_GTK_SPLITTER_VERTICAL; - else - aGtkWidgetType = MOZ_GTK_SPLITTER_HORIZONTAL; - break; -- case NS_THEME_MENUBAR: -+ case StyleAppearance::Menubar: - aGtkWidgetType = MOZ_GTK_MENUBAR; - break; -- case NS_THEME_MENUPOPUP: -+ case StyleAppearance::Menupopup: - aGtkWidgetType = MOZ_GTK_MENUPOPUP; - break; -- case NS_THEME_MENUITEM: -+ case StyleAppearance::Menuitem: - { - nsMenuFrame *menuFrame = do_QueryFrame(aFrame); - if (menuFrame && menuFrame->IsOnMenuBar()) { -@@ -731,41 +746,41 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - aGtkWidgetType = MOZ_GTK_MENUITEM; - break; -- case NS_THEME_MENUSEPARATOR: -+ case StyleAppearance::Menuseparator: - aGtkWidgetType = MOZ_GTK_MENUSEPARATOR; - break; -- case NS_THEME_MENUARROW: -+ case StyleAppearance::Menuarrow: - aGtkWidgetType = MOZ_GTK_MENUARROW; - break; -- case NS_THEME_CHECKMENUITEM: -+ case StyleAppearance::Checkmenuitem: - aGtkWidgetType = MOZ_GTK_CHECKMENUITEM; - break; -- case NS_THEME_RADIOMENUITEM: -+ case StyleAppearance::Radiomenuitem: - aGtkWidgetType = MOZ_GTK_RADIOMENUITEM; - break; -- case NS_THEME_WINDOW: -- case NS_THEME_DIALOG: -+ case StyleAppearance::Window: -+ case StyleAppearance::Dialog: - aGtkWidgetType = MOZ_GTK_WINDOW; - break; -- case NS_THEME_GTK_INFO_BAR: -+ case StyleAppearance::MozGtkInfoBar: - aGtkWidgetType = MOZ_GTK_INFO_BAR; - break; -- case NS_THEME_WINDOW_TITLEBAR: -+ case StyleAppearance::MozWindowTitlebar: - aGtkWidgetType = MOZ_GTK_HEADER_BAR; - break; -- case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED: -+ case StyleAppearance::MozWindowTitlebarMaximized: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_MAXIMIZED; - break; -- case NS_THEME_WINDOW_BUTTON_CLOSE: -+ case StyleAppearance::MozWindowButtonClose: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_CLOSE; - break; -- case NS_THEME_WINDOW_BUTTON_MINIMIZE: -+ case StyleAppearance::MozWindowButtonMinimize: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE; - break; -- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: -+ case StyleAppearance::MozWindowButtonMaximize: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE; - break; -- case NS_THEME_WINDOW_BUTTON_RESTORE: -+ case StyleAppearance::MozWindowButtonRestore: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE; - break; - default: -@@ -1025,7 +1040,8 @@ DrawThemeWithCairo(gfxContext* aContext, - } - - bool --nsNativeThemeGTK::GetExtraSizeForWidget(nsIFrame* aFrame, uint8_t aWidgetType, -+nsNativeThemeGTK::GetExtraSizeForWidget(nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - nsIntMargin* aExtra) - { - *aExtra = nsIntMargin(0,0,0,0); -@@ -1033,14 +1049,14 @@ nsNativeThemeGTK::GetExtraSizeForWidget( - // GTK2 themes (Ximian Industrial, Bluecurve, Misty, at least); - // We modify the frame's overflow area. See bug 297508. - switch (aWidgetType) { -- case NS_THEME_SCROLLBARTHUMB_VERTICAL: -+ case StyleAppearance::ScrollbarthumbVertical: - aExtra->top = aExtra->bottom = 1; - break; -- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: -+ case StyleAppearance::ScrollbarthumbHorizontal: - aExtra->left = aExtra->right = 1; - break; - -- case NS_THEME_BUTTON : -+ case StyleAppearance::Button : - { - if (IsDefaultButton(aFrame)) { - // Some themes draw a default indicator outside the widget, -@@ -1055,14 +1071,14 @@ nsNativeThemeGTK::GetExtraSizeForWidget( - } - return false; - } -- case NS_THEME_FOCUS_OUTLINE: -+ case StyleAppearance::FocusOutline: - { - moz_gtk_get_focus_outline_size(&aExtra->left, &aExtra->top); - aExtra->right = aExtra->left; - aExtra->bottom = aExtra->top; - break; - } -- case NS_THEME_TAB : -+ case StyleAppearance::Tab : - { - if (!IsSelectedTab(aFrame)) - return false; -@@ -1097,7 +1113,7 @@ nsNativeThemeGTK::GetExtraSizeForWidget( - NS_IMETHODIMP - nsNativeThemeGTK::DrawWidgetBackground(gfxContext* aContext, - nsIFrame* aFrame, -- uint8_t aWidgetType, -+ StyleAppearance aWidgetType, - const nsRect& aRect, - const nsRect& aDirtyRect) - { -@@ -1191,8 +1207,8 @@ nsNativeThemeGTK::DrawWidgetBackground(g - #ifdef DEBUG - printf("GTK theme failed for widget type %d, error was %d, state was " - "[active=%d,focused=%d,inHover=%d,disabled=%d]\n", -- aWidgetType, gLastGdkError, state.active, state.focused, -- state.inHover, state.disabled); -+ static_cast(aWidgetType), gLastGdkError, state.active, -+ state.focused, state.inHover, state.disabled); - #endif - NS_WARNING("GTK theme failed; disabling unsafe widget"); - SetWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType); -@@ -1221,16 +1237,16 @@ nsNativeThemeGTK::CreateWebRenderCommand - const mozilla::layers::StackingContextHelper& aSc, - mozilla::layers::WebRenderLayerManager* aManager, - nsIFrame* aFrame, -- uint8_t aWidgetType, -+ StyleAppearance aWidgetType, - const nsRect& aRect) - { - nsPresContext* presContext = aFrame->PresContext(); -- wr::LayoutRect bounds = aSc.ToRelativeLayoutRect( -+ wr::LayoutRect bounds = wr::ToRoundedLayoutRect( - LayoutDeviceRect::FromAppUnits(aRect, presContext->AppUnitsPerDevPixel())); - - switch (aWidgetType) { -- case NS_THEME_WINDOW: -- case NS_THEME_DIALOG: -+ case StyleAppearance::Window: -+ case StyleAppearance::Dialog: - aBuilder.PushRect(bounds, bounds, true, - wr::ToColorF(Color::FromABGR( - LookAndFeel::GetColor(LookAndFeel::eColorID_WindowBackground, -@@ -1243,7 +1259,7 @@ nsNativeThemeGTK::CreateWebRenderCommand - } - - WidgetNodeType --nsNativeThemeGTK::NativeThemeToGtkTheme(uint8_t aWidgetType, nsIFrame* aFrame) -+nsNativeThemeGTK::NativeThemeToGtkTheme(StyleAppearance aWidgetType, nsIFrame* aFrame) - { - WidgetNodeType gtkWidgetType; - gint unusedFlags; -@@ -1258,9 +1274,10 @@ nsNativeThemeGTK::NativeThemeToGtkTheme( - } - - void --nsNativeThemeGTK::GetCachedWidgetBorder(nsIFrame* aFrame, uint8_t aWidgetType, -+nsNativeThemeGTK::GetCachedWidgetBorder(nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - GtkTextDirection aDirection, -- nsIntMargin* aResult) -+ LayoutDeviceIntMargin* aResult) - { - aResult->SizeTo(0, 0, 0, 0); - -@@ -1277,7 +1294,7 @@ nsNativeThemeGTK::GetCachedWidgetBorder( - } else { - moz_gtk_get_widget_border(gtkWidgetType, &aResult->left, &aResult->top, - &aResult->right, &aResult->bottom, aDirection); -- if (aWidgetType != MOZ_GTK_DROPDOWN) { // depends on aDirection -+ if (gtkWidgetType != MOZ_GTK_DROPDOWN) { // depends on aDirection - mBorderCacheValid[cacheIndex] |= cacheBit; - mBorderCache[gtkWidgetType] = *aResult; - } -@@ -1285,49 +1302,52 @@ nsNativeThemeGTK::GetCachedWidgetBorder( - } - } - --NS_IMETHODIMP --nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, -- uint8_t aWidgetType, nsIntMargin* aResult) -+LayoutDeviceIntMargin -+nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, -+ nsIFrame* aFrame, -+ StyleAppearance aWidgetType) - { -+ LayoutDeviceIntMargin result; - GtkTextDirection direction = GetTextDirection(aFrame); -- aResult->top = aResult->left = aResult->right = aResult->bottom = 0; - switch (aWidgetType) { -- case NS_THEME_SCROLLBAR_HORIZONTAL: -- case NS_THEME_SCROLLBAR_VERTICAL: -+ case StyleAppearance::ScrollbarHorizontal: -+ case StyleAppearance::ScrollbarVertical: - { - GtkOrientation orientation = -- aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? -+ aWidgetType == StyleAppearance::ScrollbarHorizontal ? - GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; -- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); -+ const ScrollbarGTKMetrics* metrics = -+ GetActiveScrollbarMetrics(orientation); - - const GtkBorder& border = metrics->border.scrollbar; -- aResult->top = border.top; -- aResult->right = border.right; -- aResult->bottom = border.bottom; -- aResult->left = border.left; -+ result.top = border.top; -+ result.right = border.right; -+ result.bottom = border.bottom; -+ result.left = border.left; - } - break; -- case NS_THEME_SCROLLBARTRACK_HORIZONTAL: -- case NS_THEME_SCROLLBARTRACK_VERTICAL: -+ case StyleAppearance::ScrollbartrackHorizontal: -+ case StyleAppearance::ScrollbartrackVertical: - { - GtkOrientation orientation = -- aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL ? -+ aWidgetType == StyleAppearance::ScrollbartrackHorizontal ? - GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; -- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); -+ const ScrollbarGTKMetrics* metrics = -+ GetActiveScrollbarMetrics(orientation); - - const GtkBorder& border = metrics->border.track; -- aResult->top = border.top; -- aResult->right = border.right; -- aResult->bottom = border.bottom; -- aResult->left = border.left; -+ result.top = border.top; -+ result.right = border.right; -+ result.bottom = border.bottom; -+ result.left = border.left; - } - break; -- case NS_THEME_TOOLBOX: -+ case StyleAppearance::Toolbox: - // gtk has no toolbox equivalent. So, although we map toolbox to - // gtk's 'toolbar' for purposes of painting the widget background, - // we don't use the toolbar border for toolbox. - break; -- case NS_THEME_DUALBUTTON: -+ case StyleAppearance::Dualbutton: - // TOOLBAR_DUAL_BUTTON is an interesting case. We want a border to draw - // around the entire button + dropdown, and also an inner border if you're - // over the button part. But, we want the inner button to be right up -@@ -1335,23 +1355,23 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi - // To make this happen, we draw a button border for the outer button, - // but don't reserve any space for it. - break; -- case NS_THEME_TAB: -+ case StyleAppearance::Tab: - { - WidgetNodeType gtkWidgetType; - gint flags; - - if (!GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nullptr, -- &flags)) -- return NS_OK; -- -- moz_gtk_get_tab_border(&aResult->left, &aResult->top, -- &aResult->right, &aResult->bottom, direction, -+ &flags)) { -+ return result; -+ } -+ moz_gtk_get_tab_border(&result.left, &result.top, -+ &result.right, &result.bottom, direction, - (GtkTabFlags)flags, gtkWidgetType); - } - break; -- case NS_THEME_MENUITEM: -- case NS_THEME_CHECKMENUITEM: -- case NS_THEME_RADIOMENUITEM: -+ case StyleAppearance::Menuitem: -+ case StyleAppearance::Checkmenuitem: -+ case StyleAppearance::Radiomenuitem: - // For regular menuitems, we will be using GetWidgetPadding instead of - // GetWidgetBorder to pad up the widget's internals; other menuitems - // will need to fall through and use the default case as before. -@@ -1360,50 +1380,57 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi - MOZ_FALLTHROUGH; - default: - { -- GetCachedWidgetBorder(aFrame, aWidgetType, direction, aResult); -+ GetCachedWidgetBorder(aFrame, aWidgetType, direction, &result); - } - } - - gint scale = GetMonitorScaleFactor(aFrame); -- aResult->top *= scale; -- aResult->right *= scale; -- aResult->bottom *= scale; -- aResult->left *= scale; -- return NS_OK; -+ result.top *= scale; -+ result.right *= scale; -+ result.bottom *= scale; -+ result.left *= scale; -+ return result; - } - - bool - nsNativeThemeGTK::GetWidgetPadding(nsDeviceContext* aContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -- nsIntMargin* aResult) --{ -+ nsIFrame* aFrame, -+ StyleAppearance aWidgetType, -+ LayoutDeviceIntMargin* aResult) -+{ -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } -+ - switch (aWidgetType) { -- case NS_THEME_BUTTON_FOCUS: -- case NS_THEME_TOOLBARBUTTON: -- case NS_THEME_WINDOW_BUTTON_CLOSE: -- case NS_THEME_WINDOW_BUTTON_MINIMIZE: -- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: -- case NS_THEME_WINDOW_BUTTON_RESTORE: -- case NS_THEME_DUALBUTTON: -- case NS_THEME_TAB_SCROLL_ARROW_BACK: -- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: -- case NS_THEME_MENULIST_BUTTON: -- case NS_THEME_TOOLBARBUTTON_DROPDOWN: -- case NS_THEME_BUTTON_ARROW_UP: -- case NS_THEME_BUTTON_ARROW_DOWN: -- case NS_THEME_BUTTON_ARROW_NEXT: -- case NS_THEME_BUTTON_ARROW_PREVIOUS: -- case NS_THEME_RANGE_THUMB: -+ case StyleAppearance::ButtonFocus: -+ case StyleAppearance::Toolbarbutton: -+ case StyleAppearance::MozWindowButtonClose: -+ case StyleAppearance::MozWindowButtonMinimize: -+ case StyleAppearance::MozWindowButtonMaximize: -+ case StyleAppearance::MozWindowButtonRestore: -+ case StyleAppearance::Dualbutton: -+ case StyleAppearance::TabScrollArrowBack: -+ case StyleAppearance::TabScrollArrowForward: -+ case StyleAppearance::MenulistButton: -+ case StyleAppearance::MozMenulistButton: -+ case StyleAppearance::ToolbarbuttonDropdown: -+ case StyleAppearance::ButtonArrowUp: -+ case StyleAppearance::ButtonArrowDown: -+ case StyleAppearance::ButtonArrowNext: -+ case StyleAppearance::ButtonArrowPrevious: -+ case StyleAppearance::RangeThumb: - // Radios and checkboxes return a fixed size in GetMinimumWidgetSize - // and have a meaningful baseline, so they can't have - // author-specified padding. -- case NS_THEME_CHECKBOX: -- case NS_THEME_RADIO: -+ case StyleAppearance::Checkbox: -+ case StyleAppearance::Radio: - aResult->SizeTo(0, 0, 0, 0); - return true; -- case NS_THEME_MENUITEM: -- case NS_THEME_CHECKMENUITEM: -- case NS_THEME_RADIOMENUITEM: -+ case StyleAppearance::Menuitem: -+ case StyleAppearance::Checkmenuitem: -+ case StyleAppearance::Radiomenuitem: - { - // Menubar and menulist have their padding specified in CSS. - if (!IsRegularMenuItem(aFrame)) -@@ -1413,8 +1440,7 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev - aResult); - - gint horizontal_padding; -- -- if (aWidgetType == NS_THEME_MENUITEM) -+ if (aWidgetType == StyleAppearance::Menuitem) - moz_gtk_menuitem_get_horizontal_padding(&horizontal_padding); - else - moz_gtk_checkmenuitem_get_horizontal_padding(&horizontal_padding); -@@ -1430,6 +1456,8 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev - - return true; - } -+ default: -+ break; - } - - return false; -@@ -1437,7 +1465,8 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev - - bool - nsNativeThemeGTK::GetWidgetOverflow(nsDeviceContext* aContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -+ nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - nsRect* aOverflowRect) - { - nsIntMargin extraSize; -@@ -1456,37 +1485,43 @@ nsNativeThemeGTK::GetWidgetOverflow(nsDe - - NS_IMETHODIMP - nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -+ nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - LayoutDeviceIntSize* aResult, - bool* aIsOverridable) - { - aResult->width = aResult->height = 0; - *aIsOverridable = true; +@@ -172,7 +185,10 @@ protected: + */ + void Init(); + void InitXKBExtension(); +- void InitBySystemSettings(); ++ void InitBySystemSettingsX11(); ++#ifdef MOZ_WAYLAND ++ void InitBySystemSettingsWayland(); ++#endif -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } + /** + * mModifierKeys stores each hardware key information. +@@ -374,6 +390,15 @@ protected: + */ + void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent, + GdkEventKey* aGdkKeyEvent); + - switch (aWidgetType) { -- case NS_THEME_SCROLLBARBUTTON_UP: -- case NS_THEME_SCROLLBARBUTTON_DOWN: -+ case StyleAppearance::ScrollbarbuttonUp: -+ case StyleAppearance::ScrollbarbuttonDown: - { - const ScrollbarGTKMetrics* metrics = -- GetScrollbarMetrics(GTK_ORIENTATION_VERTICAL, true); -+ GetActiveScrollbarMetrics(GTK_ORIENTATION_VERTICAL); - - aResult->width = metrics->size.button.width; - aResult->height = metrics->size.button.height; - *aIsOverridable = false; - } - break; -- case NS_THEME_SCROLLBARBUTTON_LEFT: -- case NS_THEME_SCROLLBARBUTTON_RIGHT: -+ case StyleAppearance::ScrollbarbuttonLeft: -+ case StyleAppearance::ScrollbarbuttonRight: - { - const ScrollbarGTKMetrics* metrics = -- GetScrollbarMetrics(GTK_ORIENTATION_HORIZONTAL, true); -+ GetActiveScrollbarMetrics(GTK_ORIENTATION_HORIZONTAL); - - aResult->width = metrics->size.button.width; - aResult->height = metrics->size.button.height; - *aIsOverridable = false; - } - break; -- case NS_THEME_SPLITTER: -+ case StyleAppearance::Splitter: - { - gint metrics; - if (IsHorizontal(aFrame)) { -@@ -1501,8 +1536,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; - } - break; -- case NS_THEME_SCROLLBAR_HORIZONTAL: -- case NS_THEME_SCROLLBAR_VERTICAL: -+ case StyleAppearance::ScrollbarHorizontal: -+ case StyleAppearance::ScrollbarVertical: - { - /* While we enforce a minimum size for the thumb, this is ignored - * for the some scrollbars if buttons are hidden (bug 513006) because -@@ -1510,28 +1545,30 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - * or track. So add a minimum size to the track as well to prevent a - * 0-width scrollbar. */ - GtkOrientation orientation = -- aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? -+ aWidgetType == StyleAppearance::ScrollbarHorizontal ? - GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; -- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); -+ const ScrollbarGTKMetrics* metrics = -+ GetActiveScrollbarMetrics(orientation); - - aResult->width = metrics->size.scrollbar.width; - aResult->height = metrics->size.scrollbar.height; - } - break; -- case NS_THEME_SCROLLBARTHUMB_VERTICAL: -- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: -+ case StyleAppearance::ScrollbarthumbVertical: -+ case StyleAppearance::ScrollbarthumbHorizontal: - { - GtkOrientation orientation = -- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL ? -+ aWidgetType == StyleAppearance::ScrollbarthumbHorizontal ? - GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; -- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); -+ const ScrollbarGTKMetrics* metrics = -+ GetActiveScrollbarMetrics(orientation); - - aResult->width = metrics->size.thumb.width; - aResult->height = metrics->size.thumb.height; - *aIsOverridable = false; - } - break; -- case NS_THEME_RANGE_THUMB: -+ case StyleAppearance::RangeThumb: - { - gint thumb_length, thumb_height; - -@@ -1546,7 +1583,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; - } - break; -- case NS_THEME_RANGE: -+ case StyleAppearance::Range: - { - gint scale_width, scale_height; - -@@ -1559,12 +1596,12 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = true; - } - break; -- case NS_THEME_SCALETHUMB_HORIZONTAL: -- case NS_THEME_SCALETHUMB_VERTICAL: -+ case StyleAppearance::ScalethumbHorizontal: -+ case StyleAppearance::ScalethumbVertical: - { - gint thumb_length, thumb_height; - -- if (aWidgetType == NS_THEME_SCALETHUMB_VERTICAL) { -+ if (aWidgetType == StyleAppearance::ScalethumbVertical) { - moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_length, &thumb_height); - aResult->width = thumb_height; - aResult->height = thumb_length; -@@ -1577,21 +1614,22 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; - } - break; -- case NS_THEME_TAB_SCROLL_ARROW_BACK: -- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: -+ case StyleAppearance::TabScrollArrowBack: -+ case StyleAppearance::TabScrollArrowForward: - { - moz_gtk_get_tab_scroll_arrow_size(&aResult->width, &aResult->height); - *aIsOverridable = false; - } - break; -- case NS_THEME_MENULIST_BUTTON: -+ case StyleAppearance::MenulistButton: -+ case StyleAppearance::MozMenulistButton: - { - moz_gtk_get_combo_box_entry_button_size(&aResult->width, - &aResult->height); - *aIsOverridable = false; - } - break; -- case NS_THEME_MENUSEPARATOR: -+ case StyleAppearance::Menuseparator: - { - gint separator_height; ++#ifdef MOZ_WAYLAND ++ /** ++ * Utility function to set Xkb modifier key mask. ++ */ ++ void SetModifierMask(xkb_keymap *aKeymap, ++ ModifierIndex aModifierIndex, ++ const char* aModifierName); ++#endif + }; -@@ -1601,26 +1639,26 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; - } - break; -- case NS_THEME_CHECKBOX: -- case NS_THEME_RADIO: -+ case StyleAppearance::Checkbox: -+ case StyleAppearance::Radio: - { -- const ToggleGTKMetrics* metrics = GetToggleMetrics(aWidgetType == NS_THEME_RADIO); -+ const ToggleGTKMetrics* metrics = GetToggleMetrics(aWidgetType == StyleAppearance::Radio); - aResult->width = metrics->minSizeWithBorder.width; - aResult->height = metrics->minSizeWithBorder.height; - } - break; -- case NS_THEME_TOOLBARBUTTON_DROPDOWN: -- case NS_THEME_BUTTON_ARROW_UP: -- case NS_THEME_BUTTON_ARROW_DOWN: -- case NS_THEME_BUTTON_ARROW_NEXT: -- case NS_THEME_BUTTON_ARROW_PREVIOUS: -+ case StyleAppearance::ToolbarbuttonDropdown: -+ case StyleAppearance::ButtonArrowUp: -+ case StyleAppearance::ButtonArrowDown: -+ case StyleAppearance::ButtonArrowNext: -+ case StyleAppearance::ButtonArrowPrevious: - { - moz_gtk_get_arrow_size(MOZ_GTK_TOOLBARBUTTON_ARROW, - &aResult->width, &aResult->height); - *aIsOverridable = false; - } - break; -- case NS_THEME_WINDOW_BUTTON_CLOSE: -+ case StyleAppearance::MozWindowButtonClose: - { - const ToolbarButtonGTKMetrics* metrics = - GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_CLOSE); -@@ -1628,7 +1666,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - aResult->height = metrics->minSizeWithBorderMargin.height; - break; - } -- case NS_THEME_WINDOW_BUTTON_MINIMIZE: -+ case StyleAppearance::MozWindowButtonMinimize: - { - const ToolbarButtonGTKMetrics* metrics = - GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE); -@@ -1636,8 +1674,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - aResult->height = metrics->minSizeWithBorderMargin.height; - break; - } -- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: -- case NS_THEME_WINDOW_BUTTON_RESTORE: -+ case StyleAppearance::MozWindowButtonMaximize: -+ case StyleAppearance::MozWindowButtonRestore: - { - const ToolbarButtonGTKMetrics* metrics = - GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE); -@@ -1645,16 +1683,16 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - aResult->height = metrics->minSizeWithBorderMargin.height; - break; - } -- case NS_THEME_CHECKBOX_CONTAINER: -- case NS_THEME_RADIO_CONTAINER: -- case NS_THEME_CHECKBOX_LABEL: -- case NS_THEME_RADIO_LABEL: -- case NS_THEME_BUTTON: -- case NS_THEME_MENULIST: -- case NS_THEME_TOOLBARBUTTON: -- case NS_THEME_TREEHEADERCELL: -+ case StyleAppearance::CheckboxContainer: -+ case StyleAppearance::RadioContainer: -+ case StyleAppearance::CheckboxLabel: -+ case StyleAppearance::RadioLabel: -+ case StyleAppearance::Button: -+ case StyleAppearance::Menulist: -+ case StyleAppearance::Toolbarbutton: -+ case StyleAppearance::Treeheadercell: - { -- if (aWidgetType == NS_THEME_MENULIST) { -+ if (aWidgetType == StyleAppearance::Menulist) { - // Include the arrow size. - moz_gtk_get_arrow_size(MOZ_GTK_DROPDOWN, - &aResult->width, &aResult->height); -@@ -1663,21 +1701,21 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - // descendants; the value returned here will not be helpful, but the - // box model may consider border and padding with child minimum sizes. - -- nsIntMargin border; -+ LayoutDeviceIntMargin border; - GetCachedWidgetBorder(aFrame, aWidgetType, GetTextDirection(aFrame), &border); - aResult->width += border.left + border.right; - aResult->height += border.top + border.bottom; - } - break; - #ifdef MOZ_WIDGET_GTK -- case NS_THEME_NUMBER_INPUT: -- case NS_THEME_TEXTFIELD: -+ case StyleAppearance::NumberInput: -+ case StyleAppearance::Textfield: - { - moz_gtk_get_entry_min_height(&aResult->height); - } - break; - #endif -- case NS_THEME_SEPARATOR: -+ case StyleAppearance::Separator: - { - gint separator_width; + } // namespace widget +diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp +--- thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp 2018-11-21 13:42:00.760025653 +0100 +@@ -31,7 +31,9 @@ + #include + #include "WidgetStyleCache.h" + #include "prenv.h" ++#include "nsCSSColorUtils.h" -@@ -1686,26 +1724,26 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - aResult->width = separator_width; - } - break; -- case NS_THEME_INNER_SPIN_BUTTON: -- case NS_THEME_SPINNER: -+ case StyleAppearance::InnerSpinButton: -+ case StyleAppearance::Spinner: - // hard code these sizes - aResult->width = 14; - aResult->height = 26; - break; -- case NS_THEME_TREEHEADERSORTARROW: -- case NS_THEME_SPINNER_UPBUTTON: -- case NS_THEME_SPINNER_DOWNBUTTON: -+ case StyleAppearance::Treeheadersortarrow: -+ case StyleAppearance::SpinnerUpbutton: -+ case StyleAppearance::SpinnerDownbutton: - // hard code these sizes - aResult->width = 14; - aResult->height = 13; - break; -- case NS_THEME_RESIZER: -+ case StyleAppearance::Resizer: - // same as Windows to make our lives easier - aResult->width = aResult->height = 15; - *aIsOverridable = false; - break; -- case NS_THEME_TREETWISTY: -- case NS_THEME_TREETWISTYOPEN: -+ case StyleAppearance::Treetwisty: -+ case StyleAppearance::Treetwistyopen: - { - gint expander_size; ++using namespace mozilla; + using mozilla::LookAndFeel; -@@ -1714,6 +1752,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; + #define GDK_COLOR_TO_NS_RGB(c) \ +@@ -182,7 +184,7 @@ GetBorderColors(GtkStyleContext* aContex + // GTK has an initial value of zero for border-widths, and so themes + // need to explicitly set border-widths to make borders visible. + GtkBorder border; +- gtk_style_context_get_border(aContext, GTK_STATE_FLAG_NORMAL, &border); ++ gtk_style_context_get_border(aContext, state, &border); + visible = border.top != 0 || border.right != 0 || + border.bottom != 0 || border.left != 0; } - break; -+ default: -+ break; - } - - *aResult = *aResult * GetMonitorScaleFactor(aFrame); -@@ -1722,41 +1762,42 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n +@@ -213,6 +215,58 @@ GetBorderColors(GtkStyleContext* aContex + return ret; } - NS_IMETHODIMP --nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, -+nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - nsAtom* aAttribute, bool* aShouldRepaint, - const nsAttrValue* aOldValue) - { - // Some widget types just never change state. -- if (aWidgetType == NS_THEME_TOOLBOX || -- aWidgetType == NS_THEME_TOOLBAR || -- aWidgetType == NS_THEME_STATUSBAR || -- aWidgetType == NS_THEME_STATUSBARPANEL || -- aWidgetType == NS_THEME_RESIZERPANEL || -- aWidgetType == NS_THEME_PROGRESSCHUNK || -- aWidgetType == NS_THEME_PROGRESSCHUNK_VERTICAL || -- aWidgetType == NS_THEME_PROGRESSBAR || -- aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL || -- aWidgetType == NS_THEME_MENUBAR || -- aWidgetType == NS_THEME_MENUPOPUP || -- aWidgetType == NS_THEME_TOOLTIP || -- aWidgetType == NS_THEME_MENUSEPARATOR || -- aWidgetType == NS_THEME_WINDOW || -- aWidgetType == NS_THEME_DIALOG) { -+ if (aWidgetType == StyleAppearance::Toolbox || -+ aWidgetType == StyleAppearance::Toolbar || -+ aWidgetType == StyleAppearance::Statusbar || -+ aWidgetType == StyleAppearance::Statusbarpanel || -+ aWidgetType == StyleAppearance::Resizerpanel || -+ aWidgetType == StyleAppearance::Progresschunk || -+ aWidgetType == StyleAppearance::ProgresschunkVertical || -+ aWidgetType == StyleAppearance::Progressbar || -+ aWidgetType == StyleAppearance::ProgressbarVertical || -+ aWidgetType == StyleAppearance::Menubar || -+ aWidgetType == StyleAppearance::Menupopup || -+ aWidgetType == StyleAppearance::Tooltip || -+ aWidgetType == StyleAppearance::Menuseparator || -+ aWidgetType == StyleAppearance::Window || -+ aWidgetType == StyleAppearance::Dialog) { - *aShouldRepaint = false; - return NS_OK; - } - -- if ((aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL || -- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL) && -+ if ((aWidgetType == StyleAppearance::ScrollbarthumbVertical || -+ aWidgetType == StyleAppearance::ScrollbarthumbHorizontal) && - aAttribute == nsGkAtoms::active) { - *aShouldRepaint = true; - return NS_OK; - } - -- if ((aWidgetType == NS_THEME_SCROLLBARBUTTON_UP || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) && -+ if ((aWidgetType == StyleAppearance::ScrollbarbuttonUp || -+ aWidgetType == StyleAppearance::ScrollbarbuttonDown || -+ aWidgetType == StyleAppearance::ScrollbarbuttonLeft || -+ aWidgetType == StyleAppearance::ScrollbarbuttonRight) && - (aAttribute == nsGkAtoms::curpos || - aAttribute == nsGkAtoms::maxpos)) { - // If 'curpos' has changed and we are passed its old value, we can -@@ -1820,120 +1861,135 @@ nsNativeThemeGTK::ThemeChanged() - NS_IMETHODIMP_(bool) - nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext, - nsIFrame* aFrame, -- uint8_t aWidgetType) -+ StyleAppearance aWidgetType) - { - if (IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType)) - return false; - -+ if (IsWidgetScrollbarPart(aWidgetType)) { -+ ComputedStyle* cs = nsLayoutUtils::StyleForScrollbar(aFrame); -+ if (cs->StyleUI()->HasCustomScrollbars() || -+ // We cannot handle thin scrollbar on GTK+ widget directly as well. -+ cs->StyleUIReset()->mScrollbarWidth == StyleScrollbarWidth::Thin) { -+ return false; ++// Finds ideal cell highlight colors used for unfocused+selected cells distinct ++// from both Highlight, used as focused+selected background, and the listbox ++// background which is assumed to be similar to -moz-field ++nsresult ++nsLookAndFeel::InitCellHighlightColors() { ++ // NS_SUFFICIENT_LUMINOSITY_DIFFERENCE is the a11y standard for text ++ // on a background. Use 20% of that standard since we have a background ++ // on top of another background ++ int32_t minLuminosityDifference = NS_SUFFICIENT_LUMINOSITY_DIFFERENCE / 5; ++ int32_t backLuminosityDifference = NS_LUMINOSITY_DIFFERENCE( ++ mMozWindowBackground, mMozFieldBackground); ++ if (backLuminosityDifference >= minLuminosityDifference) { ++ mMozCellHighlightBackground = mMozWindowBackground; ++ mMozCellHighlightText = mMozWindowText; ++ return NS_OK; + } -+ } + -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } ++ uint16_t hue, sat, luminance; ++ uint8_t alpha; ++ mMozCellHighlightBackground = mMozFieldBackground; ++ mMozCellHighlightText = mMozFieldText; + - switch (aWidgetType) { - // Combobox dropdowns don't support native theming in vertical mode. -- case NS_THEME_MENULIST: -- case NS_THEME_MENULIST_TEXT: -- case NS_THEME_MENULIST_TEXTFIELD: -+ case StyleAppearance::Menulist: -+ case StyleAppearance::MenulistText: -+ case StyleAppearance::MenulistTextfield: - if (aFrame && aFrame->GetWritingMode().IsVertical()) { - return false; - } - MOZ_FALLTHROUGH; - -- case NS_THEME_BUTTON: -- case NS_THEME_BUTTON_FOCUS: -- case NS_THEME_RADIO: -- case NS_THEME_CHECKBOX: -- case NS_THEME_TOOLBOX: // N/A -- case NS_THEME_TOOLBAR: -- case NS_THEME_TOOLBARBUTTON: -- case NS_THEME_DUALBUTTON: // so we can override the border with 0 -- case NS_THEME_TOOLBARBUTTON_DROPDOWN: -- case NS_THEME_BUTTON_ARROW_UP: -- case NS_THEME_BUTTON_ARROW_DOWN: -- case NS_THEME_BUTTON_ARROW_NEXT: -- case NS_THEME_BUTTON_ARROW_PREVIOUS: -- case NS_THEME_SEPARATOR: -- case NS_THEME_TOOLBARGRIPPER: -- case NS_THEME_STATUSBAR: -- case NS_THEME_STATUSBARPANEL: -- case NS_THEME_RESIZERPANEL: -- case NS_THEME_RESIZER: -- case NS_THEME_LISTBOX: -- // case NS_THEME_LISTITEM: -- case NS_THEME_TREEVIEW: -- // case NS_THEME_TREEITEM: -- case NS_THEME_TREETWISTY: -- // case NS_THEME_TREELINE: -- // case NS_THEME_TREEHEADER: -- case NS_THEME_TREEHEADERCELL: -- case NS_THEME_TREEHEADERSORTARROW: -- case NS_THEME_TREETWISTYOPEN: -- case NS_THEME_PROGRESSBAR: -- case NS_THEME_PROGRESSCHUNK: -- case NS_THEME_PROGRESSBAR_VERTICAL: -- case NS_THEME_PROGRESSCHUNK_VERTICAL: -- case NS_THEME_TAB: -- // case NS_THEME_TABPANEL: -- case NS_THEME_TABPANELS: -- case NS_THEME_TAB_SCROLL_ARROW_BACK: -- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: -- case NS_THEME_TOOLTIP: -- case NS_THEME_INNER_SPIN_BUTTON: -- case NS_THEME_SPINNER: -- case NS_THEME_SPINNER_UPBUTTON: -- case NS_THEME_SPINNER_DOWNBUTTON: -- case NS_THEME_SPINNER_TEXTFIELD: -- // case NS_THEME_SCROLLBAR: (n/a for gtk) -- // case NS_THEME_SCROLLBAR_SMALL: (n/a for gtk) -- case NS_THEME_SCROLLBARBUTTON_UP: -- case NS_THEME_SCROLLBARBUTTON_DOWN: -- case NS_THEME_SCROLLBARBUTTON_LEFT: -- case NS_THEME_SCROLLBARBUTTON_RIGHT: -- case NS_THEME_SCROLLBAR_HORIZONTAL: -- case NS_THEME_SCROLLBAR_VERTICAL: -- case NS_THEME_SCROLLBARTRACK_HORIZONTAL: -- case NS_THEME_SCROLLBARTRACK_VERTICAL: -- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: -- case NS_THEME_SCROLLBARTHUMB_VERTICAL: -- case NS_THEME_NUMBER_INPUT: -- case NS_THEME_TEXTFIELD: -- case NS_THEME_TEXTFIELD_MULTILINE: -- case NS_THEME_RANGE: -- case NS_THEME_RANGE_THUMB: -- case NS_THEME_SCALE_HORIZONTAL: -- case NS_THEME_SCALETHUMB_HORIZONTAL: -- case NS_THEME_SCALE_VERTICAL: -- case NS_THEME_SCALETHUMB_VERTICAL: -- // case NS_THEME_SCALETHUMBSTART: -- // case NS_THEME_SCALETHUMBEND: -- // case NS_THEME_SCALETHUMBTICK: -- case NS_THEME_CHECKBOX_CONTAINER: -- case NS_THEME_RADIO_CONTAINER: -- case NS_THEME_CHECKBOX_LABEL: -- case NS_THEME_RADIO_LABEL: -- case NS_THEME_MENUBAR: -- case NS_THEME_MENUPOPUP: -- case NS_THEME_MENUITEM: -- case NS_THEME_MENUARROW: -- case NS_THEME_MENUSEPARATOR: -- case NS_THEME_CHECKMENUITEM: -- case NS_THEME_RADIOMENUITEM: -- case NS_THEME_SPLITTER: -- case NS_THEME_WINDOW: -- case NS_THEME_DIALOG: -+ case StyleAppearance::Button: -+ case StyleAppearance::ButtonFocus: -+ case StyleAppearance::Radio: -+ case StyleAppearance::Checkbox: -+ case StyleAppearance::Toolbox: // N/A -+ case StyleAppearance::Toolbar: -+ case StyleAppearance::Toolbarbutton: -+ case StyleAppearance::Dualbutton: // so we can override the border with 0 -+ case StyleAppearance::ToolbarbuttonDropdown: -+ case StyleAppearance::ButtonArrowUp: -+ case StyleAppearance::ButtonArrowDown: -+ case StyleAppearance::ButtonArrowNext: -+ case StyleAppearance::ButtonArrowPrevious: -+ case StyleAppearance::Separator: -+ case StyleAppearance::Toolbargripper: -+ case StyleAppearance::Statusbar: -+ case StyleAppearance::Statusbarpanel: -+ case StyleAppearance::Resizerpanel: -+ case StyleAppearance::Resizer: -+ case StyleAppearance::Listbox: -+ // case StyleAppearance::Listitem: -+ case StyleAppearance::Treeview: -+ // case StyleAppearance::Treeitem: -+ case StyleAppearance::Treetwisty: -+ // case StyleAppearance::Treeline: -+ // case StyleAppearance::Treeheader: -+ case StyleAppearance::Treeheadercell: -+ case StyleAppearance::Treeheadersortarrow: -+ case StyleAppearance::Treetwistyopen: -+ case StyleAppearance::Progressbar: -+ case StyleAppearance::Progresschunk: -+ case StyleAppearance::ProgressbarVertical: -+ case StyleAppearance::ProgresschunkVertical: -+ case StyleAppearance::Tab: -+ // case StyleAppearance::Tabpanel: -+ case StyleAppearance::Tabpanels: -+ case StyleAppearance::TabScrollArrowBack: -+ case StyleAppearance::TabScrollArrowForward: -+ case StyleAppearance::Tooltip: -+ case StyleAppearance::InnerSpinButton: -+ case StyleAppearance::Spinner: -+ case StyleAppearance::SpinnerUpbutton: -+ case StyleAppearance::SpinnerDownbutton: -+ case StyleAppearance::SpinnerTextfield: -+ // case StyleAppearance::Scrollbar: (n/a for gtk) -+ // case StyleAppearance::ScrollbarSmall: (n/a for gtk) -+ case StyleAppearance::ScrollbarbuttonUp: -+ case StyleAppearance::ScrollbarbuttonDown: -+ case StyleAppearance::ScrollbarbuttonLeft: -+ case StyleAppearance::ScrollbarbuttonRight: -+ case StyleAppearance::ScrollbarHorizontal: -+ case StyleAppearance::ScrollbarVertical: -+ case StyleAppearance::ScrollbartrackHorizontal: -+ case StyleAppearance::ScrollbartrackVertical: -+ case StyleAppearance::ScrollbarthumbHorizontal: -+ case StyleAppearance::ScrollbarthumbVertical: -+ case StyleAppearance::NumberInput: -+ case StyleAppearance::Textfield: -+ case StyleAppearance::TextfieldMultiline: -+ case StyleAppearance::Range: -+ case StyleAppearance::RangeThumb: -+ case StyleAppearance::ScaleHorizontal: -+ case StyleAppearance::ScalethumbHorizontal: -+ case StyleAppearance::ScaleVertical: -+ case StyleAppearance::ScalethumbVertical: -+ // case StyleAppearance::Scalethumbstart: -+ // case StyleAppearance::Scalethumbend: -+ // case StyleAppearance::Scalethumbtick: -+ case StyleAppearance::CheckboxContainer: -+ case StyleAppearance::RadioContainer: -+ case StyleAppearance::CheckboxLabel: -+ case StyleAppearance::RadioLabel: -+ case StyleAppearance::Menubar: -+ case StyleAppearance::Menupopup: -+ case StyleAppearance::Menuitem: -+ case StyleAppearance::Menuarrow: -+ case StyleAppearance::Menuseparator: -+ case StyleAppearance::Checkmenuitem: -+ case StyleAppearance::Radiomenuitem: -+ case StyleAppearance::Splitter: -+ case StyleAppearance::Window: -+ case StyleAppearance::Dialog: - #ifdef MOZ_WIDGET_GTK -- case NS_THEME_GTK_INFO_BAR: -+ case StyleAppearance::MozGtkInfoBar: - #endif - return !IsWidgetStyled(aPresContext, aFrame, aWidgetType); - -- case NS_THEME_WINDOW_BUTTON_CLOSE: -- case NS_THEME_WINDOW_BUTTON_MINIMIZE: -- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: -- case NS_THEME_WINDOW_BUTTON_RESTORE: -- case NS_THEME_WINDOW_TITLEBAR: -- case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED: -+ case StyleAppearance::MozWindowButtonClose: -+ case StyleAppearance::MozWindowButtonMinimize: -+ case StyleAppearance::MozWindowButtonMaximize: -+ case StyleAppearance::MozWindowButtonRestore: -+ case StyleAppearance::MozWindowTitlebar: -+ case StyleAppearance::MozWindowTitlebarMaximized: - // GtkHeaderBar is available on GTK 3.10+, which is used for styling - // title bars and title buttons. - return gtk_check_version(3, 10, 0) == nullptr && - !IsWidgetStyled(aPresContext, aFrame, aWidgetType); - -- case NS_THEME_MENULIST_BUTTON: -+ case StyleAppearance::MenulistButton: -+ case StyleAppearance::MozMenulistButton: - if (aFrame && aFrame->GetWritingMode().IsVertical()) { - return false; - } -@@ -1942,37 +1998,50 @@ nsNativeThemeGTK::ThemeSupportsWidget(ns - return (!aFrame || IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) && - !IsWidgetStyled(aPresContext, aFrame, aWidgetType); - -- case NS_THEME_FOCUS_OUTLINE: -+ case StyleAppearance::FocusOutline: - return true; -+ default: -+ break; - } - - return false; - } - - NS_IMETHODIMP_(bool) --nsNativeThemeGTK::WidgetIsContainer(uint8_t aWidgetType) -+nsNativeThemeGTK::WidgetIsContainer(StyleAppearance aWidgetType) - { -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } ++ NS_RGB2HSV(mMozCellHighlightBackground, hue, sat, luminance, alpha); + - // XXXdwh At some point flesh all of this out. -- if (aWidgetType == NS_THEME_MENULIST_BUTTON || -- aWidgetType == NS_THEME_RADIO || -- aWidgetType == NS_THEME_RANGE_THUMB || -- aWidgetType == NS_THEME_CHECKBOX || -- aWidgetType == NS_THEME_TAB_SCROLL_ARROW_BACK || -- aWidgetType == NS_THEME_TAB_SCROLL_ARROW_FORWARD || -- aWidgetType == NS_THEME_BUTTON_ARROW_UP || -- aWidgetType == NS_THEME_BUTTON_ARROW_DOWN || -- aWidgetType == NS_THEME_BUTTON_ARROW_NEXT || -- aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS) -+ if (aWidgetType == StyleAppearance::MenulistButton || -+ aWidgetType == StyleAppearance::MozMenulistButton || -+ aWidgetType == StyleAppearance::Radio || -+ aWidgetType == StyleAppearance::RangeThumb || -+ aWidgetType == StyleAppearance::Checkbox || -+ aWidgetType == StyleAppearance::TabScrollArrowBack || -+ aWidgetType == StyleAppearance::TabScrollArrowForward || -+ aWidgetType == StyleAppearance::ButtonArrowUp || -+ aWidgetType == StyleAppearance::ButtonArrowDown || -+ aWidgetType == StyleAppearance::ButtonArrowNext || -+ aWidgetType == StyleAppearance::ButtonArrowPrevious) - return false; - return true; - } - - bool --nsNativeThemeGTK::ThemeDrawsFocusForWidget(uint8_t aWidgetType) -+nsNativeThemeGTK::ThemeDrawsFocusForWidget(StyleAppearance aWidgetType) - { -- if (aWidgetType == NS_THEME_MENULIST || -- aWidgetType == NS_THEME_BUTTON || -- aWidgetType == NS_THEME_TREEHEADERCELL) -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } ++ uint16_t step = 30; ++ // Lighten the color if the color is very dark ++ if (luminance <= step) { ++ luminance += step; ++ } ++ // Darken it if it is very light ++ else if (luminance >= 255 - step) { ++ luminance -= step; ++ } ++ // Otherwise, compute what works best depending on the text luminance. ++ else { ++ uint16_t textHue, textSat, textLuminance; ++ uint8_t textAlpha; ++ NS_RGB2HSV(mMozCellHighlightText, textHue, textSat, textLuminance, ++ textAlpha); ++ // Text is darker than background, use a lighter shade ++ if (textLuminance < luminance) { ++ luminance += step; ++ } ++ // Otherwise, use a darker shade ++ else { ++ luminance -= step; ++ } ++ } ++ NS_HSV2RGB(mMozCellHighlightBackground, hue, sat, luminance, alpha); ++ return NS_OK; ++} + -+ if (aWidgetType == StyleAppearance::Menulist || -+ aWidgetType == StyleAppearance::Button || -+ aWidgetType == StyleAppearance::Treeheadercell) - return true; - - return false; -@@ -1985,16 +2054,17 @@ nsNativeThemeGTK::ThemeNeedsComboboxDrop - } - - nsITheme::Transparency --nsNativeThemeGTK::GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) -+nsNativeThemeGTK::GetWidgetTransparency(nsIFrame* aFrame, -+ StyleAppearance aWidgetType) + void + nsLookAndFeel::NativeInit() { - switch (aWidgetType) { - // These widgets always draw a default background. -- case NS_THEME_MENUPOPUP: -- case NS_THEME_WINDOW: -- case NS_THEME_DIALOG: -+ case StyleAppearance::Menupopup: -+ case StyleAppearance::Window: -+ case StyleAppearance::Dialog: - return eOpaque; -- case NS_THEME_SCROLLBAR_VERTICAL: -- case NS_THEME_SCROLLBAR_HORIZONTAL: -+ case StyleAppearance::ScrollbarVertical: -+ case StyleAppearance::ScrollbarHorizontal: - #ifdef MOZ_WIDGET_GTK - // Make scrollbar tracks opaque on the window's scroll frame to prevent - // leaf layers from overlapping. See bug 1179780. -@@ -2006,9 +2076,10 @@ nsNativeThemeGTK::GetWidgetTransparency( - return eOpaque; - // Tooltips use gtk_paint_flat_box() on Gtk2 - // but are shaped on Gtk3 -- case NS_THEME_TOOLTIP: -+ case StyleAppearance::Tooltip: - return eTransparent; -+ default: -+ return eUnknownTransparency; - } +@@ -269,7 +323,6 @@ nsLookAndFeel::NativeGetColor(ColorID aI + case eColorID_IMESelectedRawTextBackground: + case eColorID_IMESelectedConvertedTextBackground: + case eColorID__moz_dragtargetzone: +- case eColorID__moz_cellhighlight: + case eColorID__moz_html_cellhighlight: + case eColorID_highlight: // preference selected item, + aColor = mTextSelectedBackground; +@@ -279,10 +332,15 @@ nsLookAndFeel::NativeGetColor(ColorID aI + case eColorID_IMESelectedRawTextForeground: + case eColorID_IMESelectedConvertedTextForeground: + case eColorID_highlighttext: +- case eColorID__moz_cellhighlighttext: + case eColorID__moz_html_cellhighlighttext: + aColor = mTextSelectedText; + break; ++ case eColorID__moz_cellhighlight: ++ aColor = mMozCellHighlightBackground; ++ break; ++ case eColorID__moz_cellhighlighttext: ++ aColor = mMozCellHighlightText; ++ break; + case eColorID_Widget3DHighlight: + aColor = NS_RGB(0xa0,0xa0,0xa0); + break; +@@ -1009,6 +1067,9 @@ nsLookAndFeel::EnsureInit() + mOddCellBackground = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); -- return eUnknownTransparency; - } -diff -up thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h.wayland thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h ---- thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h.wayland 2018-10-30 12:45:37.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h 2018-11-20 12:04:43.739787343 +0100 -@@ -11,7 +11,7 @@ - #include "nsAtom.h" - #include "nsIObserver.h" - #include "nsNativeTheme.h" --#include "nsThemeConstants.h" -+#include "nsStyleConsts.h" ++ // Compute cell highlight colors ++ InitCellHighlightColors(); ++ + // GtkFrame has a "border" subnode on which Adwaita draws the border. + // Some themes do not draw on this node but draw a border on the widget + // root node, so check the root node if no border is found on the border +diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h.wayland thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h +--- thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h 2018-11-21 13:42:00.760025653 +0100 +@@ -77,6 +77,8 @@ protected: + nscolor mMozWindowActiveBorder; + nscolor mMozWindowInactiveBorder; + nscolor mMozWindowInactiveCaption; ++ nscolor mMozCellHighlightBackground; ++ nscolor mMozCellHighlightText; + nscolor mTextSelectedText; + nscolor mTextSelectedBackground; + nscolor mMozScrollbar; +@@ -91,6 +93,9 @@ protected: + bool mInitialized; - #include - #include "gtkdrawing.h" -@@ -26,7 +26,7 @@ public: - - // The nsITheme interface. - NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -+ nsIFrame* aFrame, WidgetType aWidgetType, - const nsRect& aRect, - const nsRect& aDirtyRect) override; - -@@ -35,29 +35,29 @@ public: - const mozilla::layers::StackingContextHelper& aSc, - mozilla::layers::WebRenderLayerManager* aManager, - nsIFrame* aFrame, -- uint8_t aWidgetType, -+ WidgetType aWidgetType, - const nsRect& aRect) override; - -- NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, -- uint8_t aWidgetType, -- nsIntMargin* aResult) override; -- -- virtual bool GetWidgetPadding(nsDeviceContext* aContext, -- nsIFrame* aFrame, -- uint8_t aWidgetType, -- nsIntMargin* aResult) override; -+ MOZ_MUST_USE LayoutDeviceIntMargin GetWidgetBorder(nsDeviceContext* aContext, -+ nsIFrame* aFrame, -+ WidgetType aWidgetType) override; -+ -+ bool GetWidgetPadding(nsDeviceContext* aContext, -+ nsIFrame* aFrame, -+ WidgetType aWidgetType, -+ LayoutDeviceIntMargin* aResult) override; - - virtual bool GetWidgetOverflow(nsDeviceContext* aContext, - nsIFrame* aFrame, -- uint8_t aWidgetType, -+ WidgetType aWidgetType, - nsRect* aOverflowRect) override; - - NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -+ nsIFrame* aFrame, WidgetType aWidgetType, - mozilla::LayoutDeviceIntSize* aResult, - bool* aIsOverridable) override; - -- NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, -+ NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, WidgetType aWidgetType, - nsAtom* aAttribute, - bool* aShouldRepaint, - const nsAttrValue* aOldValue) override; -@@ -66,16 +66,16 @@ public: - - NS_IMETHOD_(bool) ThemeSupportsWidget(nsPresContext* aPresContext, - nsIFrame* aFrame, -- uint8_t aWidgetType) override; -+ WidgetType aWidgetType) override; - -- NS_IMETHOD_(bool) WidgetIsContainer(uint8_t aWidgetType) override; -+ NS_IMETHOD_(bool) WidgetIsContainer(WidgetType aWidgetType) override; - -- NS_IMETHOD_(bool) ThemeDrawsFocusForWidget(uint8_t aWidgetType) override; -+ NS_IMETHOD_(bool) ThemeDrawsFocusForWidget(WidgetType aWidgetType) override; - - virtual bool ThemeNeedsComboboxDropmarker() override; - - virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, -- uint8_t aWidgetType) override; -+ WidgetType aWidgetType) override; - nsNativeThemeGTK(); - - protected: -@@ -84,26 +84,27 @@ protected: - private: - GtkTextDirection GetTextDirection(nsIFrame* aFrame); - gint GetTabMarginPixels(nsIFrame* aFrame); -- bool GetGtkWidgetAndState(uint8_t aWidgetType, nsIFrame* aFrame, -+ bool GetGtkWidgetAndState(WidgetType aWidgetType, nsIFrame* aFrame, - WidgetNodeType& aGtkWidgetType, - GtkWidgetState* aState, gint* aWidgetFlags); -- bool GetExtraSizeForWidget(nsIFrame* aFrame, uint8_t aWidgetType, -+ bool GetExtraSizeForWidget(nsIFrame* aFrame, WidgetType aWidgetType, - nsIntMargin* aExtra); - - void RefreshWidgetWindow(nsIFrame* aFrame); -- WidgetNodeType NativeThemeToGtkTheme(uint8_t aWidgetType, nsIFrame* aFrame); -+ WidgetNodeType NativeThemeToGtkTheme(WidgetType aWidgetType, nsIFrame* aFrame); - -- uint8_t mDisabledWidgetTypes[(ThemeWidgetType_COUNT + 7) / 8]; -- uint8_t mSafeWidgetStates[ThemeWidgetType_COUNT * 4]; // 32 bits per widget -+ uint8_t mDisabledWidgetTypes[(static_cast(mozilla::StyleAppearance::Count) + 7) / 8]; -+ uint8_t mSafeWidgetStates[static_cast(mozilla::StyleAppearance::Count) * 4]; // 32 bits per widget - static const char* sDisabledEngines[]; - - // Because moz_gtk_get_widget_border can be slow, we cache its results - // by widget type. Each bit in mBorderCacheValid says whether the - // corresponding entry in mBorderCache is valid. -- void GetCachedWidgetBorder(nsIFrame* aFrame, uint8_t aWidgetType, -- GtkTextDirection aDirection, nsIntMargin* aResult); -+ void GetCachedWidgetBorder(nsIFrame* aFrame, WidgetType aWidgetType, -+ GtkTextDirection aDirection, -+ LayoutDeviceIntMargin* aResult); - uint8_t mBorderCacheValid[(MOZ_GTK_WIDGET_NODE_COUNT + 7) / 8]; -- nsIntMargin mBorderCache[MOZ_GTK_WIDGET_NODE_COUNT]; -+ LayoutDeviceIntMargin mBorderCache[MOZ_GTK_WIDGET_NODE_COUNT]; + void EnsureInit(); ++ ++private: ++ nsresult InitCellHighlightColors(); }; #endif diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp --- thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp 2018-11-20 12:04:43.739787343 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp 2018-11-21 13:45:42.405091067 +0100 @@ -24,7 +24,20 @@ #include "nsIBaseWindow.h" #include "nsIDocShellTreeItem.h" @@ -6075,7 +1946,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird- NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); GtkPrintSettings* settings = gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog)); -@@ -513,13 +526,522 @@ nsPrintDialogServiceGTK::Init() +@@ -513,13 +526,521 @@ nsPrintDialogServiceGTK::Init() return NS_OK; } @@ -6556,8 +2427,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird- + // Check for the flatpak portal first + nsCOMPtr giovfs = + do_GetService(NS_GIOSERVICE_CONTRACTID); -+ bool shouldUsePortal; -+ giovfs->ShouldUseFlatpakPortal(&shouldUsePortal); ++ bool shouldUsePortal = false; + if (shouldUsePortal && gtk_check_version(3, 22, 0) == nullptr) { + nsCOMPtr widget = WidgetUtils::DOMWindowToWidget(aParent); + NS_ASSERTION(widget, "Need a widget for dialog to be modal."); @@ -6588,154 +2458,32 @@ diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird- + NS_ENSURE_SUCCESS(rv, rv); + break; + } -+ case GTK_PRINT_OPERATION_RESULT_CANCEL: -+ rv = NS_ERROR_ABORT; -+ break; -+ default: -+ NS_WARNING("Unexpected response"); -+ rv = NS_ERROR_ABORT; -+ } -+ return rv; -+ } - - nsPrintDialogWidgetGTK printDialog(aParent, aSettings); - nsresult rv = printDialog.ImportSettings(aSettings); -@@ -553,8 +1075,8 @@ NS_IMETHODIMP - nsPrintDialogServiceGTK::ShowPageSetup(nsPIDOMWindowOuter *aParent, - nsIPrintSettings *aNSSettings) - { -- NS_PRECONDITION(aParent, "aParent must not be null"); -- NS_PRECONDITION(aNSSettings, "aSettings must not be null"); -+ MOZ_ASSERT(aParent, "aParent must not be null"); -+ MOZ_ASSERT(aNSSettings, "aSettings must not be null"); - NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); - - nsCOMPtr widget = WidgetUtils::DOMWindowToWidget(aParent); -diff -up thunderbird-60.3.0/widget/gtk/nsSound.cpp.wayland thunderbird-60.3.0/widget/gtk/nsSound.cpp ---- thunderbird-60.3.0/widget/gtk/nsSound.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsSound.cpp 2018-11-20 12:04:43.739787343 +0100 -@@ -417,43 +417,3 @@ NS_IMETHODIMP nsSound::PlayEventSound(ui - } - return NS_OK; - } -- --NS_IMETHODIMP nsSound::PlaySystemSound(const nsAString &aSoundAlias) --{ -- if (NS_IsMozAliasSound(aSoundAlias)) { -- NS_WARNING("nsISound::playSystemSound is called with \"_moz_\" events, they are obsolete, use nsISound::playEventSound instead"); -- uint32_t eventId; -- if (aSoundAlias.Equals(NS_SYSSOUND_ALERT_DIALOG)) -- eventId = EVENT_ALERT_DIALOG_OPEN; -- else if (aSoundAlias.Equals(NS_SYSSOUND_CONFIRM_DIALOG)) -- eventId = EVENT_CONFIRM_DIALOG_OPEN; -- else if (aSoundAlias.Equals(NS_SYSSOUND_MAIL_BEEP)) -- eventId = EVENT_NEW_MAIL_RECEIVED; -- else if (aSoundAlias.Equals(NS_SYSSOUND_MENU_EXECUTE)) -- eventId = EVENT_MENU_EXECUTE; -- else if (aSoundAlias.Equals(NS_SYSSOUND_MENU_POPUP)) -- eventId = EVENT_MENU_POPUP; -- else -- return NS_OK; -- return PlayEventSound(eventId); -- } -- -- nsresult rv; -- nsCOMPtr fileURI; -- -- // create a nsIFile and then a nsIFileURL from that -- nsCOMPtr soundFile; -- rv = NS_NewLocalFile(aSoundAlias, true, -- getter_AddRefs(soundFile)); -- NS_ENSURE_SUCCESS(rv,rv); -- -- rv = NS_NewFileURI(getter_AddRefs(fileURI), soundFile); -- NS_ENSURE_SUCCESS(rv,rv); -- -- nsCOMPtr fileURL = do_QueryInterface(fileURI,&rv); -- NS_ENSURE_SUCCESS(rv,rv); -- -- rv = Play(fileURL); -- -- return rv; --} -diff -up thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp.wayland thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp ---- thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp 2018-11-20 12:04:43.739787343 +0100 -@@ -27,6 +27,7 @@ - #ifdef MOZ_WIDGET_GTK - #include "nsApplicationChooser.h" - #endif -+#include "TaskbarProgress.h" - #include "nsColorPicker.h" - #include "nsFilePicker.h" - #include "nsSound.h" -@@ -60,7 +61,6 @@ - using namespace mozilla; - using namespace mozilla::widget; - --NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) -@@ -72,6 +72,7 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR - NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISound, nsSound::GetInstance) - NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToPixbuf) -+NS_GENERIC_FACTORY_CONSTRUCTOR(TaskbarProgress) - - - // from nsWindow.cpp -@@ -196,14 +197,13 @@ nsClipboardConstructor(nsISupports *aOut - return inst->QueryInterface(aIID, aResult); - } - --NS_DEFINE_NAMED_CID(NS_WINDOW_CID); --NS_DEFINE_NAMED_CID(NS_CHILD_CID); - NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); - NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID); - NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); - #ifdef MOZ_WIDGET_GTK - NS_DEFINE_NAMED_CID(NS_APPLICATIONCHOOSER_CID); - #endif -+NS_DEFINE_NAMED_CID(NS_GTK_TASKBARPROGRESS_CID); - NS_DEFINE_NAMED_CID(NS_SOUND_CID); - NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID); - #ifdef MOZ_X11 -@@ -230,14 +230,13 @@ NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); - ++ case GTK_PRINT_OPERATION_RESULT_CANCEL: ++ rv = NS_ERROR_ABORT; ++ break; ++ default: ++ NS_WARNING("Unexpected response"); ++ rv = NS_ERROR_ABORT; ++ } ++ return rv; ++ } - static const mozilla::Module::CIDEntry kWidgetCIDs[] = { -- { &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor }, -- { &kNS_CHILD_CID, false, nullptr, nsWindowConstructor }, - { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor, Module::ALLOW_IN_GPU_PROCESS }, - { &kNS_COLORPICKER_CID, false, nullptr, nsColorPickerConstructor, Module::MAIN_PROCESS_ONLY }, - { &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerConstructor, Module::MAIN_PROCESS_ONLY }, - #ifdef MOZ_WIDGET_GTK - { &kNS_APPLICATIONCHOOSER_CID, false, nullptr, nsApplicationChooserConstructor, Module::MAIN_PROCESS_ONLY }, - #endif -+ { &kNS_GTK_TASKBARPROGRESS_CID, false, nullptr, TaskbarProgressConstructor}, - { &kNS_SOUND_CID, false, nullptr, nsISoundConstructor, Module::MAIN_PROCESS_ONLY }, - { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor }, - #ifdef MOZ_X11 -@@ -266,14 +265,13 @@ static const mozilla::Module::CIDEntry k - }; + nsPrintDialogWidgetGTK printDialog(aParent, aSettings); + nsresult rv = printDialog.ImportSettings(aSettings); +@@ -553,8 +1074,8 @@ NS_IMETHODIMP + nsPrintDialogServiceGTK::ShowPageSetup(nsPIDOMWindowOuter *aParent, + nsIPrintSettings *aNSSettings) + { +- NS_PRECONDITION(aParent, "aParent must not be null"); +- NS_PRECONDITION(aNSSettings, "aSettings must not be null"); ++ MOZ_ASSERT(aParent, "aParent must not be null"); ++ MOZ_ASSERT(aNSSettings, "aSettings must not be null"); + NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); - static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { -- { "@mozilla.org/widget/window/gtk;1", &kNS_WINDOW_CID }, -- { "@mozilla.org/widgets/child_window/gtk;1", &kNS_CHILD_CID }, - { "@mozilla.org/widget/appshell/gtk;1", &kNS_APPSHELL_CID, Module::ALLOW_IN_GPU_PROCESS }, - { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::MAIN_PROCESS_ONLY }, - #ifdef MOZ_WIDGET_GTK - { "@mozilla.org/applicationchooser;1", &kNS_APPLICATIONCHOOSER_CID, Module::MAIN_PROCESS_ONLY }, - #endif -+ { "@mozilla.org/widget/taskbarprogress/gtk;1", &kNS_GTK_TASKBARPROGRESS_CID }, - { "@mozilla.org/sound;1", &kNS_SOUND_CID, Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID }, - #ifdef MOZ_X11 + nsCOMPtr widget = WidgetUtils::DOMWindowToWidget(aParent); diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/widget/gtk/nsWindow.cpp --- thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsWindow.cpp 2018-11-20 12:04:43.741787337 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsWindow.cpp 2018-11-21 13:42:00.762025644 +0100 @@ -18,6 +18,7 @@ #include "mozilla/TouchEvents.h" #include "mozilla/UniquePtrExtensions.h" @@ -6832,41 +2580,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w this); nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); -@@ -838,11 +843,48 @@ nsWindow::GetDesktopToDeviceScale() - return DesktopToLayoutDeviceScale(1.0); - } - -+DesktopToLayoutDeviceScale -+nsWindow::GetDesktopToDeviceScaleByScreen() -+{ -+#ifdef MOZ_WAYLAND -+ GdkDisplay* gdkDisplay = gdk_display_get_default(); -+ // In Wayland there's no way to get absolute position of the window and use it to -+ // determine the screen factor of the monitor on which the window is placed. -+ // The window is notified of the current scale factor but not at this point, -+ // so the GdkScaleFactor can return wrong value which can lead to wrong popup -+ // placement. -+ // We need to use parent's window scale factor for the new one. -+ if (GDK_IS_WAYLAND_DISPLAY(gdkDisplay)) { -+ nsView* view = nsView::GetViewFor(this); -+ if (view) { -+ nsView* parentView = view->GetParent(); -+ if (parentView) { -+ nsIWidget* parentWidget = parentView->GetNearestWidget(nullptr); -+ if (parentWidget) { -+ return DesktopToLayoutDeviceScale(parentWidget->RoundsWidgetCoordinatesTo()); -+ } else { -+ NS_WARNING("Widget has no parent"); -+ } -+ } -+ } else { -+ NS_WARNING("Cannot find widget view"); -+ } -+ } -+#endif -+ return nsBaseWidget::GetDesktopToDeviceScale(); -+} -+ +@@ -841,8 +846,14 @@ nsWindow::GetDesktopToDeviceScale() void nsWindow::SetParent(nsIWidget *aNewParent) { @@ -6883,7 +2597,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w return; } -@@ -886,7 +928,7 @@ nsWindow::WidgetTypeSupportsAcceleration +@@ -886,7 +897,7 @@ nsWindow::WidgetTypeSupportsAcceleration void nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) { @@ -6892,7 +2606,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w NS_ASSERTION(!mIsDestroyed, ""); NS_ASSERTION(!static_cast(aNewParent)->mIsDestroyed, ""); -@@ -1517,7 +1559,7 @@ nsWindow::GetClientBounds() +@@ -1517,7 +1528,7 @@ nsWindow::GetClientBounds() void nsWindow::UpdateClientOffset() { @@ -6901,23 +2615,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w if (!mIsTopLevel || !mShell || !mIsX11Display || gtk_window_get_window_type(GTK_WINDOW(mShell)) == GTK_WINDOW_POPUP) { -@@ -1738,6 +1780,15 @@ nsWindow::GetNativeData(uint32_t aDataTy - case NS_NATIVE_COMPOSITOR_DISPLAY: - return gfxPlatformGtk::GetPlatform()->GetCompositorDisplay(); - #endif // MOZ_X11 -+ case NS_NATIVE_EGL_WINDOW: { -+ if (mIsX11Display) -+ return mGdkWindow ? (void*)GDK_WINDOW_XID(mGdkWindow) : nullptr; -+#ifdef MOZ_WAYLAND -+ if (mContainer) -+ return moz_container_get_wl_egl_window(mContainer); -+#endif -+ return nullptr; -+ } - default: - NS_WARNING("nsWindow::GetNativeData called with bad value"); - return nullptr; -@@ -2057,6 +2108,12 @@ nsWindow::OnExposeEvent(cairo_t *cr) +@@ -2057,6 +2068,12 @@ nsWindow::OnExposeEvent(cairo_t *cr) if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel) return FALSE; @@ -6930,174 +2628,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w nsIWidgetListener *listener = GetListener(); if (!listener) return FALSE; -@@ -2112,10 +2169,7 @@ nsWindow::OnExposeEvent(cairo_t *cr) - - bool shaped = false; - if (eTransparencyTransparent == GetTransparencyMode()) { -- GdkScreen *screen = gdk_window_get_screen(mGdkWindow); -- if (gdk_screen_is_composited(screen) && -- gdk_window_get_visual(mGdkWindow) == -- gdk_screen_get_rgba_visual(screen)) { -+ if (mHasAlphaVisual) { - // Remove possible shape mask from when window manger was not - // previously compositing. - static_cast(GetTopLevelWidget())-> -@@ -2216,12 +2270,9 @@ nsWindow::OnExposeEvent(cairo_t *cr) - bool painted = false; - { - if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { -- GdkScreen *screen = gdk_window_get_screen(mGdkWindow); - if (GetTransparencyMode() == eTransparencyTransparent && - layerBuffering == BufferMode::BUFFER_NONE && -- gdk_screen_is_composited(screen) && -- gdk_window_get_visual(mGdkWindow) == -- gdk_screen_get_rgba_visual(screen)) { -+ mHasAlphaVisual) { - // If our draw target is unbuffered and we use an alpha channel, - // clear the image beforehand to ensure we don't get artifacts from a - // reused SHM image. See bug 1258086. -@@ -2354,7 +2405,7 @@ nsWindow::OnConfigureEvent(GtkWidget *aW - // - // These windows should not be moved by the window manager, and so any - // change in position is a result of our direction. mBounds has -- // already been set in Move() or Resize(), and that is more -+ // already been set in std::move() or Resize(), and that is more - // up-to-date than the position in the ConfigureNotify event if the - // event is from an earlier window move. - // -@@ -2888,7 +2939,7 @@ nsWindow::OnContainerFocusOutEvent(GdkEv - bool shouldRollup = !dragSession; - if (!shouldRollup) { - // we also roll up when a drag is from a different application -- nsCOMPtr sourceNode; -+ nsCOMPtr sourceNode; - dragSession->GetSourceNode(getter_AddRefs(sourceNode)); - shouldRollup = (sourceNode == nullptr); - } -@@ -2915,8 +2966,8 @@ bool - nsWindow::DispatchCommandEvent(nsAtom* aCommand) - { - nsEventStatus status; -- WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, aCommand, this); -- DispatchEvent(&event, status); -+ WidgetCommandEvent appCommandEvent(true, aCommand, this); -+ DispatchEvent(&appCommandEvent, status); - return TRUE; - } - -@@ -2938,30 +2989,44 @@ IsCtrlAltTab(GdkEventKey *aEvent) - } - - bool --nsWindow::DispatchKeyDownEvent(GdkEventKey *aEvent, bool *aCancelled) -+nsWindow::DispatchKeyDownOrKeyUpEvent(GdkEventKey* aEvent, -+ bool aIsProcessedByIME, -+ bool* aIsCancelled) - { -- NS_PRECONDITION(aCancelled, "aCancelled must not be null"); -+ MOZ_ASSERT(aIsCancelled, "aIsCancelled must not be nullptr"); - -- *aCancelled = false; -+ *aIsCancelled = false; - -- if (IsCtrlAltTab(aEvent)) { -+ if (aEvent->type == GDK_KEY_PRESS && IsCtrlAltTab(aEvent)) { - return false; - } - -+ EventMessage message = -+ aEvent->type == GDK_KEY_PRESS ? eKeyDown : eKeyUp; -+ WidgetKeyboardEvent keyEvent(true, message, this); -+ KeymapWrapper::InitKeyEvent(keyEvent, aEvent, aIsProcessedByIME); -+ return DispatchKeyDownOrKeyUpEvent(keyEvent, aIsCancelled); -+} -+bool -+nsWindow::DispatchKeyDownOrKeyUpEvent(WidgetKeyboardEvent& aKeyboardEvent, -+ bool* aIsCancelled) -+{ -+ MOZ_ASSERT(aIsCancelled, "aIsCancelled must not be nullptr"); -+ -+ *aIsCancelled = false; -+ - RefPtr dispatcher = GetTextEventDispatcher(); - nsresult rv = dispatcher->BeginNativeInputTransaction(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return FALSE; - } - -- WidgetKeyboardEvent keydownEvent(true, eKeyDown, this); -- KeymapWrapper::InitKeyEvent(keydownEvent, aEvent); - nsEventStatus status = nsEventStatus_eIgnore; - bool dispatched = -- dispatcher->DispatchKeyboardEvent(eKeyDown, keydownEvent, -- status, aEvent); -- *aCancelled = (status == nsEventStatus_eConsumeNoDefault); -- return dispatched ? TRUE : FALSE; -+ dispatcher->DispatchKeyboardEvent(aKeyboardEvent.mMessage, -+ aKeyboardEvent, status, nullptr); -+ *aIsCancelled = (status == nsEventStatus_eConsumeNoDefault); -+ return dispatched; - } - - WidgetEventTime -@@ -3046,7 +3111,7 @@ nsWindow::OnKeyPressEvent(GdkEventKey *a - // KEYDOWN -> KEYPRESS -> KEYUP -> KEYDOWN -> KEYPRESS -> KEYUP... - - bool isKeyDownCancelled = false; -- if (DispatchKeyDownEvent(aEvent, &isKeyDownCancelled) && -+ if (DispatchKeyDownOrKeyUpEvent(aEvent, false, &isKeyDownCancelled) && - (MOZ_UNLIKELY(mIsDestroyed) || isKeyDownCancelled)) { - return TRUE; - } -@@ -3095,7 +3160,7 @@ nsWindow::OnKeyPressEvent(GdkEventKey *a - } - - WidgetKeyboardEvent keypressEvent(true, eKeyPress, this); -- KeymapWrapper::InitKeyEvent(keypressEvent, aEvent); -+ KeymapWrapper::InitKeyEvent(keypressEvent, aEvent, false); - - // before we dispatch a key, check if it's the context menu key. - // If so, send a context menu key event instead. -@@ -3179,7 +3244,7 @@ nsWindow::MaybeDispatchContextMenuEvent( - } - - gboolean --nsWindow::OnKeyReleaseEvent(GdkEventKey *aEvent) -+nsWindow::OnKeyReleaseEvent(GdkEventKey* aEvent) - { - LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this)); - -@@ -3187,17 +3252,11 @@ nsWindow::OnKeyReleaseEvent(GdkEventKey - return TRUE; - } - -- RefPtr dispatcher = GetTextEventDispatcher(); -- nsresult rv = dispatcher->BeginNativeInputTransaction(); -- if (NS_WARN_IF(NS_FAILED(rv))) { -- return false; -+ bool isCancelled = false; -+ if (NS_WARN_IF(!DispatchKeyDownOrKeyUpEvent(aEvent, false, &isCancelled))) { -+ return FALSE; - } - -- WidgetKeyboardEvent keyupEvent(true, eKeyUp, this); -- KeymapWrapper::InitKeyEvent(keyupEvent, aEvent); -- nsEventStatus status = nsEventStatus_eIgnore; -- dispatcher->DispatchKeyboardEvent(eKeyUp, keyupEvent, status, aEvent); -- - return TRUE; - } - -@@ -3214,7 +3273,7 @@ nsWindow::OnScrollEvent(GdkEventScroll * - return; - #endif - WidgetWheelEvent wheelEvent(true, eWheel, this); -- wheelEvent.mDeltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE; -+ wheelEvent.mDeltaMode = dom::WheelEvent_Binding::DOM_DELTA_LINE; - switch (aEvent->direction) { - #if GTK_CHECK_VERSION(3,4,0) - case GDK_SCROLL_SMOOTH: -@@ -3318,6 +3377,33 @@ nsWindow::OnWindowStateEvent(GtkWidget * +@@ -3318,6 +3335,33 @@ nsWindow::OnWindowStateEvent(GtkWidget * } // else the widget is a shell widget. @@ -7131,7 +2662,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w // We don't care about anything but changes in the maximized/icon/fullscreen // states if ((aEvent->changed_mask -@@ -3404,6 +3490,7 @@ nsWindow::OnDPIChanged() +@@ -3404,6 +3448,7 @@ nsWindow::OnDPIChanged() // Update menu's font size etc presShell->ThemeChanged(); } @@ -7139,81 +2670,26 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } } -@@ -3611,6 +3698,8 @@ nsWindow::Create(nsIWidget* aParent, +@@ -3611,6 +3656,7 @@ nsWindow::Create(nsIWidget* aParent, nsWindow *parentnsWindow = nullptr; GtkWidget *eventWidget = nullptr; bool drawToContainer = false; -+ bool needsAlphaVisual = (mWindowType == eWindowType_popup && -+ aInitData->mSupportTranslucency); ++ bool useAlphaVisual = false; if (aParent) { parentnsWindow = static_cast(aParent); -@@ -3661,23 +3750,47 @@ nsWindow::Create(nsIWidget* aParent, +@@ -3661,8 +3707,8 @@ nsWindow::Create(nsIWidget* aParent, } mShell = gtk_window_new(type); - bool useAlphaVisual = (mWindowType == eWindowType_popup && - aInitData->mSupportTranslucency); -- -- // mozilla.widget.use-argb-visuals is a hidden pref defaulting to false -- // to allow experimentation -- if (Preferences::GetBool("mozilla.widget.use-argb-visuals", false)) -- useAlphaVisual = true; -- -- // We need to select an ARGB visual here instead of in -- // SetTransparencyMode() because it has to be done before the -- // widget is realized. An ARGB visual is only useful if we -- // are on a compositing window manager. -- if (useAlphaVisual) { -- GdkScreen *screen = gtk_widget_get_screen(mShell); -- if (gdk_screen_is_composited(screen)) { -- GdkVisual *visual = gdk_screen_get_rgba_visual(screen); -- gtk_widget_set_visual(mShell, visual); -+#ifdef MOZ_X11 -+ // Ensure gfxPlatform is initialized, since that is what initializes -+ // gfxVars, used below. -+ Unused << gfxPlatform::GetPlatform(); -+ -+ bool useWebRender = gfx::gfxVars::UseWebRender() && -+ AllowWebRenderForThisWindow(); -+ -+ // If using WebRender on X11, we need to select a visual with a depth buffer, -+ // as well as an alpha channel if transparency is requested. This must be done -+ // before the widget is realized. -+ if (mIsX11Display && useWebRender) { -+ auto display = -+ GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(mShell)); -+ auto screen = gtk_widget_get_screen(mShell); -+ int screenNumber = GDK_SCREEN_XNUMBER(screen); -+ int visualId = 0; -+ if (GLContextGLX::FindVisual(display, screenNumber, -+ useWebRender, needsAlphaVisual, -+ &visualId)) { -+ // If we're using CSD, rendering will go through mContainer, but -+ // it will inherit this visual as it is a child of mShell. -+ gtk_widget_set_visual(mShell, -+ gdk_x11_screen_lookup_visual(screen, -+ visualId)); -+ mHasAlphaVisual = needsAlphaVisual; -+ } else { -+ NS_WARNING("We're missing X11 Visual for WebRender!"); -+ } -+ } else -+#endif // MOZ_X11 -+ { -+ if (needsAlphaVisual) { -+ GdkScreen *screen = gtk_widget_get_screen(mShell); -+ if (gdk_screen_is_composited(screen)) { -+ GdkVisual *visual = gdk_screen_get_rgba_visual(screen); -+ if (visual) { -+ gtk_widget_set_visual(mShell, visual); -+ mHasAlphaVisual = true; -+ } -+ } - } - } ++ useAlphaVisual = (mWindowType == eWindowType_popup && ++ aInitData->mSupportTranslucency); -@@ -3784,7 +3897,7 @@ nsWindow::Create(nsIWidget* aParent, + // mozilla.widget.use-argb-visuals is a hidden pref defaulting to false + // to allow experimentation +@@ -3784,7 +3830,7 @@ nsWindow::Create(nsIWidget* aParent, // it explicitly now. gtk_widget_realize(mShell); @@ -7222,7 +2698,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w * * 1) We're running on Gtk+ without client side decorations. * Content is rendered to mShell window and we listen -@@ -3859,17 +3972,7 @@ nsWindow::Create(nsIWidget* aParent, +@@ -3859,17 +3905,7 @@ nsWindow::Create(nsIWidget* aParent, // If the window were to get unredirected, there could be visible // tearing because Gecko does not align its framebuffer updates with // vblank. @@ -7241,7 +2717,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w #endif } break; -@@ -3949,10 +4052,13 @@ nsWindow::Create(nsIWidget* aParent, +@@ -3949,10 +3985,13 @@ nsWindow::Create(nsIWidget* aParent, GtkSettings* default_settings = gtk_settings_get_default(); g_signal_connect_after(default_settings, "notify::gtk-theme-name", @@ -7257,19 +2733,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } if (mContainer) { -@@ -4070,8 +4176,10 @@ nsWindow::Create(nsIWidget* aParent, - GdkVisual* gdkVisual = gdk_window_get_visual(mGdkWindow); - mXVisual = gdk_x11_visual_get_xvisual(gdkVisual); - mXDepth = gdk_visual_get_depth(gdkVisual); -+ bool shaped = needsAlphaVisual && !mHasAlphaVisual; - -- mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth); -+ mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth, -+ shaped); - } - #ifdef MOZ_WAYLAND - else if (!mIsX11Display) { -@@ -4083,60 +4191,70 @@ nsWindow::Create(nsIWidget* aParent, +@@ -4083,60 +4122,70 @@ nsWindow::Create(nsIWidget* aParent, } void @@ -7384,7 +2848,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } void -@@ -4162,6 +4280,8 @@ nsWindow::NativeResize() +@@ -4162,6 +4211,8 @@ nsWindow::NativeResize() size.width, size.height)); if (mIsTopLevel) { @@ -7393,7 +2857,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height); } else if (mContainer) { -@@ -4207,6 +4327,8 @@ nsWindow::NativeMoveResize() +@@ -4207,6 +4258,8 @@ nsWindow::NativeMoveResize() NativeShow(false); } NativeMove(); @@ -7402,7 +2866,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } GdkRectangle size = DevicePixelsToGdkSizeRoundUp(mBounds.Size()); -@@ -4219,6 +4341,8 @@ nsWindow::NativeMoveResize() +@@ -4219,6 +4272,8 @@ nsWindow::NativeMoveResize() // x and y give the position of the window manager frame top-left. gtk_window_move(GTK_WINDOW(mShell), topLeft.x, topLeft.y); // This sets the client window size. @@ -7411,7 +2875,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height); } else if (mContainer) { -@@ -4271,6 +4395,16 @@ nsWindow::NativeShow(bool aAction) +@@ -4271,6 +4326,16 @@ nsWindow::NativeShow(bool aAction) } } else { @@ -7428,7 +2892,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w if (mIsTopLevel) { // Workaround window freezes on GTK versions before 3.21.2 by // ensuring that configure events get dispatched to windows before -@@ -4946,6 +5080,8 @@ FullscreenTransitionWindow::FullscreenTr +@@ -4946,6 +5011,8 @@ FullscreenTransitionWindow::FullscreenTr gdk_screen_get_monitor_geometry(screen, monitorNum, &monitorRect); gtk_window_set_screen(gtkWin, screen); gtk_window_move(gtkWin, monitorRect.x, monitorRect.y); @@ -7437,7 +2901,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w gtk_window_resize(gtkWin, monitorRect.width, monitorRect.height); GdkColor bgColor; -@@ -5951,7 +6087,7 @@ window_state_event_cb (GtkWidget *widget +@@ -5951,7 +6018,7 @@ window_state_event_cb (GtkWidget *widget } static void @@ -7446,7 +2910,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w { RefPtr window = data; window->ThemeChanged(); -@@ -6032,13 +6168,13 @@ nsWindow::InitDragEvent(WidgetDragEvent +@@ -6032,13 +6099,13 @@ nsWindow::InitDragEvent(WidgetDragEvent KeymapWrapper::InitInputEvent(aEvent, modifierState); } @@ -7467,7 +2931,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w { RefPtr window = get_window_for_gtk_widget(aWidget); if (!window) -@@ -6063,15 +6199,24 @@ drag_motion_event_cb(GtkWidget *aWidget, +@@ -6063,15 +6130,24 @@ drag_motion_event_cb(GtkWidget *aWidget, RefPtr dragService = nsDragService::GetInstance(); return dragService-> @@ -7498,7 +2962,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w { RefPtr window = get_window_for_gtk_widget(aWidget); if (!window) -@@ -6104,14 +6249,22 @@ drag_leave_event_cb(GtkWidget *aWidget, +@@ -6104,14 +6180,22 @@ drag_leave_event_cb(GtkWidget *aWidget, dragService->ScheduleLeaveEvent(); } @@ -7528,7 +2992,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w { RefPtr window = get_window_for_gtk_widget(aWidget); if (!window) -@@ -6136,10 +6289,21 @@ drag_drop_event_cb(GtkWidget *aWidget, +@@ -6136,10 +6220,21 @@ drag_drop_event_cb(GtkWidget *aWidget, RefPtr dragService = nsDragService::GetInstance(); return dragService-> @@ -7551,7 +3015,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w static void drag_data_received_event_cb(GtkWidget *aWidget, GdkDragContext *aDragContext, -@@ -6554,12 +6718,6 @@ nsWindow::GetLayerManager(PLayerTransact +@@ -6554,12 +6649,6 @@ nsWindow::GetLayerManager(PLayerTransact return mLayerManager; } @@ -7564,7 +3028,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w return nsBaseWidget::GetLayerManager(aShadowManager, aBackendHint, aPersistence); } -@@ -6601,6 +6759,13 @@ nsWindow::ClearCachedResources() +@@ -6601,6 +6690,13 @@ nsWindow::ClearCachedResources() void nsWindow::UpdateClientOffsetForCSDWindow() { @@ -7578,7 +3042,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w // _NET_FRAME_EXTENTS is not set on client decorated windows, // so we need to read offset between mContainer and toplevel mShell // window. -@@ -6692,6 +6857,15 @@ nsWindow::SetDrawsInTitlebar(bool aState +@@ -6692,6 +6788,15 @@ nsWindow::SetDrawsInTitlebar(bool aState mNeedsShow = true; NativeResize(); @@ -7594,7 +3058,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w // When we use system titlebar setup managed by Gtk+ we also get // _NET_FRAME_EXTENTS property for our toplevel window so we can't // update the client offset it here. -@@ -6998,6 +7172,8 @@ nsWindow::GetSystemCSDSupportLevel() { +@@ -6998,6 +7103,8 @@ nsWindow::GetSystemCSDSupportLevel() { // KDE Plasma } else if (strstr(currentDesktop, "KDE") != nullptr) { sCSDSupportLevel = CSD_SUPPORT_CLIENT; @@ -7603,7 +3067,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } else if (strstr(currentDesktop, "LXDE") != nullptr) { sCSDSupportLevel = CSD_SUPPORT_CLIENT; } else if (strstr(currentDesktop, "openbox") != nullptr) { -@@ -7014,6 +7190,8 @@ nsWindow::GetSystemCSDSupportLevel() { +@@ -7014,6 +7121,8 @@ nsWindow::GetSystemCSDSupportLevel() { sCSDSupportLevel = CSD_SUPPORT_SYSTEM; } else if (strstr(currentDesktop, "LXQt") != nullptr) { sCSDSupportLevel = CSD_SUPPORT_SYSTEM; @@ -7612,7 +3076,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } else { // Release or beta builds are not supposed to be broken // so disable titlebar rendering on untested/unknown systems. -@@ -7066,26 +7244,19 @@ nsWindow::RoundsWidgetCoordinatesTo() +@@ -7066,26 +7175,18 @@ nsWindow::RoundsWidgetCoordinatesTo() void nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) { @@ -7625,7 +3089,6 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w *aInitData = mozilla::widget::GtkCompositorWidgetInitData( (mXWindow != X11None) ? mXWindow : (uintptr_t)nullptr, mXDisplay ? nsCString(XDisplayString(mXDisplay)) : nsCString(), -+ mIsTransparent && !mHasAlphaVisual, GetClientSize()); } @@ -7646,7 +3109,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w #ifdef MOZ_WAYLAND wl_display* nsWindow::GetWaylandDisplay() -@@ -7110,3 +7281,120 @@ nsWindow::GetWaylandSurface() +@@ -7110,3 +7211,85 @@ nsWindow::GetWaylandSurface() return nullptr; } #endif @@ -7731,45 +3194,10 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w +} +#endif + -+nsresult -+nsWindow::SetSystemFont(const nsCString& aFontName) -+{ -+ GtkSettings* settings = gtk_settings_get_default(); -+ g_object_set(settings, "gtk-font-name", aFontName.get(), nullptr); -+ return NS_OK; -+} -+ -+nsresult -+nsWindow::GetSystemFont(nsCString& aFontName) -+{ -+ GtkSettings* settings = gtk_settings_get_default(); -+ gchar* fontName = nullptr; -+ g_object_get(settings, -+ "gtk-font-name", &fontName, -+ nullptr); -+ if (fontName) { -+ aFontName.Assign(fontName); -+ g_free(fontName); -+ } -+ return NS_OK; -+} -+ -+already_AddRefed -+nsIWidget::CreateTopLevelWindow() -+{ -+ nsCOMPtr window = new nsWindow(); -+ return window.forget(); -+} + -+already_AddRefed -+nsIWidget::CreateChildWindow() -+{ -+ nsCOMPtr window = new nsWindow(); -+ return window.forget(); -+} diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/widget/gtk/nsWindow.h --- thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsWindow.h 2018-11-20 12:04:43.741787337 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsWindow.h 2018-11-21 13:42:00.762025644 +0100 @@ -66,6 +66,21 @@ extern mozilla::LazyLogModule gWidgetDra #endif /* MOZ_LOGGING */ @@ -7800,15 +3228,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid typedef mozilla::widget::PlatformCompositorWidgetDelegate PlatformCompositorWidgetDelegate; nsWindow(); -@@ -108,6 +124,7 @@ public: - virtual float GetDPI() override; - virtual double GetDefaultScaleInternal() override; - mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override; -+ mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScaleByScreen() override; - virtual void SetParent(nsIWidget* aNewParent) override; - virtual void SetModal(bool aModal) override; - virtual bool IsVisible() const override; -@@ -115,8 +132,7 @@ public: +@@ -115,8 +131,7 @@ public: int32_t *aX, int32_t *aY) override; virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override; @@ -7818,7 +3238,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid virtual void Show (bool aState) override; virtual void Resize (double aWidth, double aHeight, -@@ -228,6 +244,8 @@ public: +@@ -228,6 +243,8 @@ public: virtual void EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aInvalidRegion) override; @@ -7827,54 +3247,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid private: void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface, nsIntRect aBoundsRect); -@@ -278,10 +296,32 @@ public: - guint aTime); - static void UpdateDragStatus (GdkDragContext *aDragContext, - nsIDragService *aDragService); -- // If this dispatched the keydown event actually, this returns TRUE, -- // otherwise, FALSE. -- bool DispatchKeyDownEvent(GdkEventKey *aEvent, -- bool *aIsCancelled); -+ /** -+ * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event. -+ * -+ * @param aEvent A native GDK_KEY_PRESS or GDK_KEY_RELEASE -+ * event. -+ * @param aProcessedByIME true if the event is handled by IME. -+ * @param aIsCancelled [Out] true if the default is prevented. -+ * @return true if eKeyDown event is actually dispatched. -+ * Otherwise, false. -+ */ -+ bool DispatchKeyDownOrKeyUpEvent(GdkEventKey* aEvent, -+ bool aProcessedByIME, -+ bool* aIsCancelled); -+ -+ /** -+ * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event. -+ * -+ * @param aEvent An eKeyDown or eKeyUp event. This will be -+ * dispatched as is. -+ * @param aIsCancelled [Out] true if the default is prevented. -+ * @return true if eKeyDown event is actually dispatched. -+ * Otherwise, false. -+ */ -+ bool DispatchKeyDownOrKeyUpEvent(WidgetKeyboardEvent& aEvent, -+ bool* aIsCancelled); -+ - WidgetEventTime GetWidgetEventTime(guint32 aEventTime); - mozilla::TimeStamp GetEventTimeStamp(guint32 aEventTime); - mozilla::CurrentX11TimeGetter* GetCurrentTimeGetter(); -@@ -375,6 +415,9 @@ public: - - virtual bool WidgetTypeSupportsAcceleration() override; - -+ nsresult SetSystemFont(const nsCString& aFontName) override; -+ nsresult GetSystemFont(nsCString& aFontName) override; -+ - typedef enum { CSD_SUPPORT_SYSTEM, // CSD including shadows - CSD_SUPPORT_CLIENT, // CSD without shadows - CSD_SUPPORT_NONE, // WM does not support CSD at all -@@ -452,13 +495,24 @@ private: +@@ -452,13 +469,24 @@ private: gint* aRootX, gint* aRootY); void ClearCachedResources(); nsIWidgetListener* GetListener(); @@ -7900,7 +3273,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid GtkWidget *mShell; MozContainer *mContainer; GdkWindow *mGdkWindow; -@@ -558,6 +612,9 @@ private: +@@ -558,6 +586,9 @@ private: // full translucency at this time; each pixel is either fully opaque // or fully transparent. gchar* mTransparencyBitmap; @@ -7910,96 +3283,9 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid // all of our DND stuff void InitDragEvent(mozilla::WidgetDragEvent& aEvent); -diff -up thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh.wayland thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh ---- thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh 2018-11-20 12:04:43.741787337 +0100 -@@ -15,6 +15,7 @@ struct GtkCompositorWidgetInitData - { - uintptr_t XWindow; - nsCString XDisplayString; -+ bool Shaped; - - LayoutDeviceIntSize InitialClientSize; - }; -diff -up thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp.wayland thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp ---- thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp 2018-11-20 12:04:43.741787337 +0100 -@@ -197,7 +197,7 @@ ScreenHelperGTK::RefreshScreens() - } - - ScreenManager& screenManager = ScreenManager::GetSingleton(); -- screenManager.Refresh(Move(screenList)); -+ screenManager.Refresh(std::move(screenList)); - } - - } // namespace widget -diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp ---- thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp 2018-11-20 12:04:43.741787337 +0100 -@@ -31,6 +31,7 @@ WindowSurfaceProvider::WindowSurfaceProv - #ifdef MOZ_WAYLAND - , mWidget(nullptr) - #endif -+ , mIsShaped(false) - { - } - -@@ -38,7 +39,8 @@ void WindowSurfaceProvider::Initialize( - Display* aDisplay, - Window aWindow, - Visual* aVisual, -- int aDepth) -+ int aDepth, -+ bool aIsShaped) - { - // We should not be initialized - MOZ_ASSERT(!mXDisplay); -@@ -50,6 +52,7 @@ void WindowSurfaceProvider::Initialize( - mXWindow = aWindow; - mXVisual = aVisual; - mXDepth = aDepth; -+ mIsShaped = aIsShaped; - mIsX11Display = true; - } - -@@ -88,21 +91,22 @@ WindowSurfaceProvider::CreateWindowSurfa - // 3. XPutImage - - #ifdef MOZ_WIDGET_GTK -- if (gfxVars::UseXRender()) { -+ if (!mIsShaped && gfxVars::UseXRender()) { - LOGDRAW(("Drawing to nsWindow %p using XRender\n", (void*)this)); - return MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); - } - #endif // MOZ_WIDGET_GTK - - #ifdef MOZ_HAVE_SHMIMAGE -- if (nsShmImage::UseShm()) { -+ if (!mIsShaped && nsShmImage::UseShm()) { - LOGDRAW(("Drawing to nsWindow %p using MIT-SHM\n", (void*)this)); - return MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); - } - #endif // MOZ_HAVE_SHMIMAGE - - LOGDRAW(("Drawing to nsWindow %p using XPutImage\n", (void*)this)); -- return MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); -+ return MakeUnique(mXDisplay, mXWindow, mXVisual, -+ mXDepth, mIsShaped); - } - - already_AddRefed -@@ -125,7 +129,7 @@ WindowSurfaceProvider::StartRemoteDrawin - // We can't use WindowSurfaceX11Image fallback on Wayland but - // Lock() call on WindowSurfaceWayland should never fail. - gfxWarningOnce() << "Failed to lock WindowSurface, falling back to XPutImage backend."; -- mWindowSurface = MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); -+ mWindowSurface = MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth, mIsShaped); - dt = mWindowSurface->Lock(aInvalidRegion); - } - return dt.forget(); diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h --- thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h 2018-11-20 12:04:43.742787334 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h 2018-11-21 13:42:00.762025644 +0100 @@ -17,6 +17,7 @@ #include #endif @@ -8008,27 +3294,9 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h.wayland thunderbi class nsWindow; -@@ -43,7 +44,8 @@ public: - Display* aDisplay, - Window aWindow, - Visual* aVisual, -- int aDepth); -+ int aDepth, -+ bool aIsShaped); - - #ifdef MOZ_WAYLAND - void Initialize(nsWindow *aWidget); -@@ -75,6 +77,7 @@ private: - #ifdef MOZ_WAYLAND - nsWindow* mWidget; - #endif -+ bool mIsShaped; - }; - - } // namespace widget diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp --- thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp 2018-11-20 12:04:43.742787334 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp 2018-11-21 13:42:00.763025640 +0100 @@ -151,8 +151,9 @@ static nsWaylandDisplay* WaylandDisplayG static void WaylandDisplayRelease(wl_display *aDisplay); static void WaylandDisplayLoop(wl_display *aDisplay); @@ -8072,16 +3340,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb return gfxPlatform::CreateDrawTargetForData(static_cast(mShmPool.GetImageData()), lockSize, BUFFER_BPP * mWidth, -@@ -551,6 +551,8 @@ frame_callback_handler(void *data, struc - { - auto surface = reinterpret_cast(data); - surface->FrameCallbackHandler(); -+ -+ gfxPlatformGtk::GetPlatform()->SetWaylandLastVsync(time); - } - - static const struct wl_callback_listener frame_listener = { -@@ -560,26 +562,40 @@ static const struct wl_callback_listener +@@ -560,26 +560,40 @@ static const struct wl_callback_listener WindowSurfaceWayland::WindowSurfaceWayland(nsWindow *aWindow) : mWindow(aWindow) , mWaylandDisplay(WaylandDisplayGet(aWindow->GetWaylandDisplay())) @@ -8129,7 +3388,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb if (!mIsMainThread) { // We can be destroyed from main thread even though we was created/used // in compositor thread. We have to unref/delete WaylandDisplay in compositor -@@ -593,162 +609,309 @@ WindowSurfaceWayland::~WindowSurfaceWayl +@@ -593,162 +607,309 @@ WindowSurfaceWayland::~WindowSurfaceWayl } } @@ -8216,13 +3475,14 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + WindowBackBuffer* buffer = GetWaylandBufferToDraw(aWidth, aHeight); + if (buffer) { + return buffer->Lock(); -+ } -+ + } + +- return mFrontBuffer; + NS_WARNING("WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); + return nullptr; -+} -+ -+already_AddRefed + } + + already_AddRefed +WindowSurfaceWayland::LockImageSurface(const gfx::IntSize& aLockSize) +{ + if (!mImageSurface || mImageSurface->CairoStatus() || @@ -8232,15 +3492,14 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + if (mImageSurface->CairoStatus()) { + return nullptr; + } - } - -- return mFrontBuffer; ++ } ++ + return gfxPlatform::CreateDrawTargetForData(mImageSurface->Data(), + mImageSurface->GetSize(), + mImageSurface->Stride(), + mWaylandDisplay->GetSurfaceFormat()); - } - ++} ++ +/* + There are some situations which can happen here: + @@ -8254,7 +3513,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + B) Lock() is requested for part(s) of screen. We need to provide temporary + surface to draw into and copy result (clipped) to target wl_surface. + */ - already_AddRefed ++already_AddRefed WindowSurfaceWayland::Lock(const LayoutDeviceIntRegion& aRegion) { MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); @@ -8287,9 +3546,8 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + // We don't have any front buffer available. Try indirect drawing + // to mImageSurface which is mirrored to front buffer at commit. + mDrawToWaylandBufferDirectly = false; - } - -- return buffer->Lock(aRegion); ++ } ++ + return LockImageSurface(lockSize); +} + @@ -8314,8 +3572,9 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + mImageSurface->Format()); + if (!dt || !surf) { + return false; -+ } -+ + } + +- return buffer->Lock(aRegion); + uint32_t numRects = aRegion.GetNumRects(); + if (numRects != 1) { + AutoTArray rects; @@ -8529,7 +3788,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h --- thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h 2018-11-20 12:04:43.742787334 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h 2018-11-21 13:42:00.763025640 +0100 @@ -8,6 +8,7 @@ #define _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H @@ -8595,237 +3854,3 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h.wayland thunderbir }; } // namespace widget -diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp ---- thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp 2018-11-20 12:04:43.743787331 +0100 -@@ -12,19 +12,42 @@ - #include "gfxPlatform.h" - #include "gfx2DGlue.h" - -+#include -+ - namespace mozilla { - namespace widget { - -+// gfxImageSurface pixel format configuration. -+#define SHAPED_IMAGE_SURFACE_BPP 4 -+#ifdef IS_BIG_ENDIAN -+ #define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 0 -+#else -+ #define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 3 -+#endif -+ - WindowSurfaceX11Image::WindowSurfaceX11Image(Display* aDisplay, - Window aWindow, - Visual* aVisual, -- unsigned int aDepth) -+ unsigned int aDepth, -+ bool aIsShaped) - : WindowSurfaceX11(aDisplay, aWindow, aVisual, aDepth) -+ , mTransparencyBitmap(nullptr) -+ , mTransparencyBitmapWidth(0) -+ , mTransparencyBitmapHeight(0) -+ , mIsShaped(aIsShaped) - { - } - - WindowSurfaceX11Image::~WindowSurfaceX11Image() - { -+ if (mTransparencyBitmap) { -+ delete[] mTransparencyBitmap; -+ -+ Display* xDisplay = mWindowSurface->XDisplay(); -+ Window xDrawable = mWindowSurface->XDrawable(); -+ -+ XShapeCombineMask(xDisplay, xDrawable, ShapeBounding, 0, 0, X11None, ShapeSet); -+ } - } - - already_AddRefed -@@ -50,6 +73,13 @@ WindowSurfaceX11Image::Lock(const Layout - gfx::SurfaceFormat::X8R8G8B8_UINT32; - } - -+ // Use alpha image format for shaped window as we derive -+ // the shape bitmap from alpha channel. Must match SHAPED_IMAGE_SURFACE_BPP -+ // and SHAPED_IMAGE_SURFACE_ALPHA_INDEX. -+ if (mIsShaped) { -+ format = gfx::SurfaceFormat::A8R8G8B8_UINT32; -+ } -+ - mImageSurface = new gfxImageSurface(size, format); - if (mImageSurface->CairoStatus()) { - return nullptr; -@@ -82,6 +112,132 @@ WindowSurfaceX11Image::Lock(const Layout - ImageFormatToSurfaceFormat(format)); - } - -+// The transparency bitmap routines are derived form the ones at nsWindow.cpp. -+// The difference here is that we compose to RGBA image and then create -+// the shape mask from final image alpha channel. -+static inline int32_t -+GetBitmapStride(int32_t width) -+{ -+ return (width+7)/8; -+} -+ -+static bool -+ChangedMaskBits(gchar* aMaskBits, int32_t aMaskWidth, int32_t aMaskHeight, -+ const nsIntRect& aRect, uint8_t* aImageData) -+{ -+ int32_t stride = aMaskWidth*SHAPED_IMAGE_SURFACE_BPP; -+ int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost(); -+ int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth); -+ for (y = aRect.y; y < yMax; y++) { -+ gchar* maskBytes = aMaskBits + y*maskBytesPerRow; -+ uint8_t* alphas = aImageData; -+ for (x = aRect.x; x < xMax; x++) { -+ bool newBit = *(alphas+SHAPED_IMAGE_SURFACE_ALPHA_INDEX) > 0x7f; -+ alphas += SHAPED_IMAGE_SURFACE_BPP; -+ -+ gchar maskByte = maskBytes[x >> 3]; -+ bool maskBit = (maskByte & (1 << (x & 7))) != 0; -+ -+ if (maskBit != newBit) { -+ return true; -+ } -+ } -+ aImageData += stride; -+ } -+ -+ return false; -+} -+ -+static void -+UpdateMaskBits(gchar* aMaskBits, int32_t aMaskWidth, int32_t aMaskHeight, -+ const nsIntRect& aRect, uint8_t* aImageData) -+{ -+ int32_t stride = aMaskWidth*SHAPED_IMAGE_SURFACE_BPP; -+ int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost(); -+ int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth); -+ for (y = aRect.y; y < yMax; y++) { -+ gchar* maskBytes = aMaskBits + y*maskBytesPerRow; -+ uint8_t* alphas = aImageData; -+ for (x = aRect.x; x < xMax; x++) { -+ bool newBit = *(alphas+SHAPED_IMAGE_SURFACE_ALPHA_INDEX) > 0x7f; -+ alphas += SHAPED_IMAGE_SURFACE_BPP; -+ -+ gchar mask = 1 << (x & 7); -+ gchar maskByte = maskBytes[x >> 3]; -+ // Note: '-newBit' turns 0 into 00...00 and 1 into 11...11 -+ maskBytes[x >> 3] = (maskByte & ~mask) | (-newBit & mask); -+ } -+ aImageData += stride; -+ } -+} -+ -+void -+WindowSurfaceX11Image::ResizeTransparencyBitmap(int aWidth, int aHeight) -+{ -+ int32_t actualSize = -+ GetBitmapStride(mTransparencyBitmapWidth)*mTransparencyBitmapHeight; -+ int32_t newSize = GetBitmapStride(aWidth)*aHeight; -+ -+ if (actualSize < newSize) { -+ delete[] mTransparencyBitmap; -+ mTransparencyBitmap = new gchar[newSize]; -+ } -+ -+ mTransparencyBitmapWidth = aWidth; -+ mTransparencyBitmapHeight = aHeight; -+} -+ -+void -+WindowSurfaceX11Image::ApplyTransparencyBitmap() -+{ -+ gfx::IntSize size = mWindowSurface->GetSize(); -+ bool maskChanged = true; -+ -+ if (!mTransparencyBitmap) { -+ mTransparencyBitmapWidth = size.width; -+ mTransparencyBitmapHeight = size.height; -+ -+ int32_t byteSize = -+ GetBitmapStride(mTransparencyBitmapWidth)*mTransparencyBitmapHeight; -+ mTransparencyBitmap = new gchar[byteSize]; -+ } else { -+ bool sizeChanged = (size.width != mTransparencyBitmapWidth || -+ size.height != mTransparencyBitmapHeight); -+ -+ if (sizeChanged) { -+ ResizeTransparencyBitmap(size.width, size.height); -+ } else { -+ maskChanged = ChangedMaskBits(mTransparencyBitmap, -+ mTransparencyBitmapWidth, mTransparencyBitmapHeight, -+ nsIntRect(0, 0, size.width, size.height), -+ (uint8_t*)mImageSurface->Data()); -+ } -+ } -+ -+ if (maskChanged) { -+ UpdateMaskBits(mTransparencyBitmap, -+ mTransparencyBitmapWidth, -+ mTransparencyBitmapHeight, -+ nsIntRect(0, 0, size.width, size.height), -+ (uint8_t*)mImageSurface->Data()); -+ -+ // We use X11 calls where possible, because GDK handles expose events -+ // for shaped windows in a way that's incompatible with us (Bug 635903). -+ // It doesn't occur when the shapes are set through X. -+ Display* xDisplay = mWindowSurface->XDisplay(); -+ Window xDrawable = mWindowSurface->XDrawable(); -+ Pixmap maskPixmap = XCreateBitmapFromData(xDisplay, -+ xDrawable, -+ mTransparencyBitmap, -+ mTransparencyBitmapWidth, -+ mTransparencyBitmapHeight); -+ XShapeCombineMask(xDisplay, xDrawable, -+ ShapeBounding, 0, 0, -+ maskPixmap, ShapeSet); -+ XFreePixmap(xDisplay, maskPixmap); -+ } -+} -+ - void - WindowSurfaceX11Image::Commit(const LayoutDeviceIntRegion& aInvalidRegion) - { -@@ -112,6 +268,10 @@ WindowSurfaceX11Image::Commit(const Layo - dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); - } - -+ if (mIsShaped) { -+ ApplyTransparencyBitmap(); -+ } -+ - dt->DrawSurface(surf, rect, rect); - - if (numRects != 1) { -diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h ---- thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h 2018-11-20 12:04:43.743787331 +0100 -@@ -19,7 +19,7 @@ namespace widget { - class WindowSurfaceX11Image : public WindowSurfaceX11 { - public: - WindowSurfaceX11Image(Display* aDisplay, Window aWindow, Visual* aVisual, -- unsigned int aDepth); -+ unsigned int aDepth, bool aIsShaped); - ~WindowSurfaceX11Image(); - - already_AddRefed Lock(const LayoutDeviceIntRegion& aRegion) override; -@@ -27,8 +27,16 @@ public: - bool IsFallback() const override { return true; } - - private: -+ void ResizeTransparencyBitmap(int aWidth, int aHeight); -+ void ApplyTransparencyBitmap(); -+ - RefPtr mWindowSurface; - RefPtr mImageSurface; -+ -+ gchar* mTransparencyBitmap; -+ int32_t mTransparencyBitmapWidth; -+ int32_t mTransparencyBitmapHeight; -+ bool mIsShaped; - }; - - } // namespace widget diff --git a/thunderbird.spec b/thunderbird.spec index 0f8882c..4fb592a 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -84,7 +84,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.3.0 -Release: 4%{?dist} +Release: 5%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -128,6 +128,7 @@ Patch309: mozilla-1460871-ldap-query.patch Patch310: disable-dbus-remote.patch Patch311: firefox-wayland.patch Patch312: thunderbird-dbus-remote.patch +Patch313: firefox-wayland-crash-mozbz1507475.patch # Upstream patches @@ -189,8 +190,6 @@ BuildRequires: dbus-glib-devel Obsoletes: thunderbird-lightning Provides: thunderbird-lightning Obsoletes: thunderbird-lightning-gdata <= 1:3.3.0.14 -#Conflicts: thunderbird-lightning-gdata <= 1:3.3.0.14 -#Obsoletes: thunderbird-52.9.1 BuildRequires: rust BuildRequires: cargo BuildRequires: clang-devel @@ -271,9 +270,9 @@ debug %{name}, you want to install %{name}-debuginfo instead. #cd .. # TODO - needs fixes -#%patch311 -p1 -b .wayland +%patch311 -p1 -b .wayland #%patch312 -p1 -b .thunderbird-dbus-remote - +%patch313 -p1 -b .mozbz1507475 %if %{official_branding} # Required by Mozilla Corporation @@ -693,6 +692,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Nov 21 2018 Martin Stransky - 60.3.0-5 +- Backported Wayland related code from Firefox 63 +- Added fix for mozbz#1507475 - crash when display changes + * Tue Nov 20 2018 Martin Stransky - 60.3.0-4 - Build with Wayland support - Enabled DBus remote for Wayland