From 7b002e873e9e45f7aef355670f346621a7bfa9a4 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 5 Feb 2019 15:49:40 +0100 Subject: [PATCH] Wayland patches update --- bug1375074-save-restore-x28.patch | 74 - disable-dbus-remote.patch | 12 - firefox-gcc-6.0.patch | 26 - firefox-wayland-crash-mozbz1507475.patch | 94 - firefox-wayland.patch | 6238 ++++++++++++---------- mozbz-1500850-missing-dbus-header.patch | 12 - thunderbird.spec | 13 +- 7 files changed, 3406 insertions(+), 3063 deletions(-) delete mode 100644 bug1375074-save-restore-x28.patch delete mode 100644 disable-dbus-remote.patch delete mode 100644 firefox-gcc-6.0.patch delete mode 100644 firefox-wayland-crash-mozbz1507475.patch delete mode 100644 mozbz-1500850-missing-dbus-header.patch diff --git a/bug1375074-save-restore-x28.patch b/bug1375074-save-restore-x28.patch deleted file mode 100644 index 57a83a2..0000000 --- a/bug1375074-save-restore-x28.patch +++ /dev/null @@ -1,74 +0,0 @@ -# HG changeset patch -# User Lars T Hansen -# Date 1519822672 -3600 -# Wed Feb 28 13:57:52 2018 +0100 -# Node ID 672f0415217b202ae59a930769dffd9d6ba6b87c -# Parent 825fd04dacc6297d3a980ec4184079405950b35d -Bug 1375074 - Save and restore non-volatile x28 on ARM64 for generated unboxed object constructor. - -diff --git a/js/src/jit-test/tests/bug1375074.js b/js/src/jit-test/tests/bug1375074.js -new file mode 100644 ---- /dev/null -+++ b/js/src/jit-test/tests/bug1375074.js -@@ -0,0 +1,18 @@ -+// This forces the VM to start creating unboxed objects and thus stresses a -+// particular path into generated code for a specialized unboxed object -+// constructor. -+ -+var K = 2000; // 2000 should be plenty -+var s = "["; -+var i; -+for ( i=0; i < K-1; i++ ) -+ s = s + `{"i":${i}},`; -+s += `{"i":${i}}]`; -+var v = JSON.parse(s); -+ -+assertEq(v.length == K, true); -+ -+for ( i=0; i < K; i++) { -+ assertEq(v[i] instanceof Object, true); -+ assertEq(v[i].i, i); -+} -diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp ---- a/js/src/vm/UnboxedObject.cpp -+++ b/js/src/vm/UnboxedObject.cpp -@@ -95,7 +95,15 @@ UnboxedLayout::makeConstructorCode(JSCon - #endif - - #ifdef JS_CODEGEN_ARM64 -- // ARM64 communicates stack address via sp, but uses a pseudo-sp for addressing. -+ // ARM64 communicates stack address via sp, but uses a pseudo-sp (PSP) for -+ // addressing. The register we use for PSP may however also be used by -+ // calling code, and it is nonvolatile, so save it. Do this as a special -+ // case first because the generic save/restore code needs the PSP to be -+ // initialized already. -+ MOZ_ASSERT(PseudoStackPointer64.Is(masm.GetStackPointer64())); -+ masm.Str(PseudoStackPointer64, vixl::MemOperand(sp, -16, vixl::PreIndex)); -+ -+ // Initialize the PSP from the SP. - masm.initStackPtr(); - #endif - -@@ -233,7 +241,22 @@ UnboxedLayout::makeConstructorCode(JSCon - masm.pop(ScratchDoubleReg); - masm.PopRegsInMask(savedNonVolatileRegisters); - -+#ifdef JS_CODEGEN_ARM64 -+ // Now restore the value that was in the PSP register on entry, and return. -+ -+ // Obtain the correct SP from the PSP. -+ masm.Mov(sp, PseudoStackPointer64); -+ -+ // Restore the saved value of the PSP register, this value is whatever the -+ // caller had saved in it, not any actual SP value, and it must not be -+ // overwritten subsequently. -+ masm.Ldr(PseudoStackPointer64, vixl::MemOperand(sp, 16, vixl::PostIndex)); -+ -+ // Perform a plain Ret(), as abiret() will move SP <- PSP and that is wrong. -+ masm.Ret(vixl::lr); -+#else - masm.abiret(); -+#endif - - masm.bind(&failureStoreOther); - diff --git a/disable-dbus-remote.patch b/disable-dbus-remote.patch deleted file mode 100644 index 72040f2..0000000 --- a/disable-dbus-remote.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up thunderbird-60.3.0/toolkit/components/remote/nsRemoteService.cpp.old thunderbird-60.3.0/toolkit/components/remote/nsRemoteService.cpp ---- thunderbird-60.3.0/toolkit/components/remote/nsRemoteService.cpp.old 2018-11-06 11:25:46.634929894 +0100 -+++ thunderbird-60.3.0/toolkit/components/remote/nsRemoteService.cpp 2018-11-06 11:21:49.617828440 +0100 -@@ -34,7 +34,7 @@ NS_IMPL_ISUPPORTS(nsRemoteService, - NS_IMETHODIMP - nsRemoteService::Startup(const char* aAppName, const char* aProfileName) - { --#if defined(MOZ_ENABLE_DBUS) -+#if 0 - nsresult rv; - mDBusRemoteService = new nsDBusRemoteService(); - rv = mDBusRemoteService->Startup(aAppName, aProfileName); diff --git a/firefox-gcc-6.0.patch b/firefox-gcc-6.0.patch deleted file mode 100644 index 0a74d36..0000000 --- a/firefox-gcc-6.0.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff -up firefox-44.0/nsprpub/config/make-system-wrappers.pl.back firefox-44.0/nsprpub/config/make-system-wrappers.pl ---- firefox-44.0/nsprpub/config/make-system-wrappers.pl.back 2016-01-24 00:23:49.000000000 +0100 -+++ firefox-44.0/nsprpub/config/make-system-wrappers.pl 2016-02-02 14:58:45.064112655 +0100 -@@ -19,7 +19,9 @@ while () { - open OUT, ">$output_dir/$_"; - print OUT "#pragma GCC system_header\n"; # suppress include_next warning - print OUT "#pragma GCC visibility push(default)\n"; -+ print OUT "#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS\n"; - print OUT "#include_next \<$_\>\n"; -+ print OUT "#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS\n"; - print OUT "#pragma GCC visibility pop\n"; - close OUT; - } -diff -up firefox-44.0/mozglue/build/arm.cpp.old firefox-44.0/mozglue/build/arm.cpp ---- firefox-44.0/mozglue/build/arm.cpp.old 2016-02-03 10:07:29.879526500 +0100 -+++ firefox-44.0/mozglue/build/arm.cpp 2016-02-03 10:08:11.062697517 +0100 -@@ -104,7 +104,9 @@ check_neon(void) - - # elif defined(__linux__) || defined(ANDROID) - # include -+#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS - # include -+#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS - # include - - enum{ diff --git a/firefox-wayland-crash-mozbz1507475.patch b/firefox-wayland-crash-mozbz1507475.patch deleted file mode 100644 index bab96bc..0000000 --- a/firefox-wayland-crash-mozbz1507475.patch +++ /dev/null @@ -1,94 +0,0 @@ -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 00b408c..d08ae4c 100644 --- a/firefox-wayland.patch +++ b/firefox-wayland.patch @@ -1,7 +1,7 @@ -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-21 13:42:00.757025666 +0100 -@@ -40,7 +40,9 @@ GtkCompositorWidget::GtkCompositorWidget +diff -up thunderbird-60.5.0/widget/gtk/GtkCompositorWidget.cpp.wayland thunderbird-60.5.0/widget/gtk/GtkCompositorWidget.cpp +--- thunderbird-60.5.0/widget/gtk/GtkCompositorWidget.cpp.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/GtkCompositorWidget.cpp 2019-02-05 14:26:16.973316654 +0100 +@@ -38,7 +38,9 @@ GtkCompositorWidget::GtkCompositorWidget // Grab the window's visual and depth XWindowAttributes windowAttrs; @@ -10,22 +10,20 @@ diff -up thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp.wayland thunderbi + NS_WARNING("GtkCompositorWidget(): XGetWindowAttributes() failed!"); + } - Visual* visual = windowAttrs.visual; - int depth = windowAttrs.depth; -@@ -50,8 +52,7 @@ GtkCompositorWidget::GtkCompositorWidget - mXDisplay, - mXWindow, - visual, -- depth -- ); -+ depth); - } - mClientSize = aInitData.InitialClientSize(); - } -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 + Visual* visual = windowAttrs.visual; + int depth = windowAttrs.depth; +diff -up thunderbird-60.5.0/widget/gtk/moz.build.wayland thunderbird-60.5.0/widget/gtk/moz.build +--- thunderbird-60.5.0/widget/gtk/moz.build.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/moz.build 2019-02-05 14:26:16.974316651 +0100 +@@ -99,6 +99,7 @@ if CONFIG['MOZ_X11']: + if CONFIG['MOZ_WAYLAND']: + UNIFIED_SOURCES += [ + 'nsClipboardWayland.cpp', ++ 'nsWaylandDisplay.cpp', + 'WindowSurfaceWayland.cpp', + ] + +@@ -123,6 +124,7 @@ include('/ipc/chromium/chromium-config.m FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ @@ -33,172 +31,406 @@ diff -up thunderbird-60.3.0/widget/gtk/moz.build.wayland thunderbird-60.3.0/widg '/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 +diff -up thunderbird-60.5.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.5.0/widget/gtk/mozcontainer.cpp +--- thunderbird-60.5.0/widget/gtk/mozcontainer.cpp.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/mozcontainer.cpp 2019-02-05 15:09:24.116970135 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public +@@ -7,9 +7,10 @@ + + #include "mozcontainer.h" + #include +-#ifdef MOZ_WAYLAND #include - #include +-#include ++#ifdef MOZ_WAYLAND ++#include "nsWaylandDisplay.h" +#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; -+ - 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) -+{ -+ container->parent_surface_committed = true; -+ g_signal_handler_disconnect(clock, -+ container->parent_surface_committed_handler); -+ container->parent_surface_committed_handler = 0; -+} -+ - /* 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; -+ } -+ - 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); -+ -+ 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; - } - +@@ -19,12 +20,20 @@ + #include "maiRedundantObjectFactory.h" #endif -@@ -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); -+ } -+ } - } ++#ifdef MOZ_WAYLAND ++using namespace mozilla; ++using namespace mozilla::widget; ++#endif ++ + /* init methods */ + static void moz_container_class_init(MozContainerClass *klass); + static void moz_container_init(MozContainer *container); - return container->surface; + /* widget class methods */ + static void moz_container_map(GtkWidget *widget); ++#if defined(MOZ_WAYLAND) ++static gboolean moz_container_map_wayland(GtkWidget *widget, GdkEventAny *event); ++#endif + static void moz_container_unmap(GtkWidget *widget); + static void moz_container_realize(GtkWidget *widget); + static void moz_container_size_allocate(GtkWidget *widget, +@@ -114,29 +123,6 @@ void moz_container_put(MozContainer *con + gtk_widget_set_parent(child_widget, GTK_WIDGET(container)); } + +-void moz_container_move(MozContainer *container, GtkWidget *child_widget, +- gint x, gint y, gint width, gint height) { +- MozContainerChild *child; +- GtkAllocation new_allocation; +- +- child = moz_container_get_child(container, child_widget); +- +- child->x = x; +- child->y = y; +- +- new_allocation.x = x; +- new_allocation.y = y; +- new_allocation.width = width; +- new_allocation.height = height; +- +- /* printf("moz_container_move %p %p will allocate to %d %d %d %d\n", +- (void *)container, (void *)child_widget, +- new_allocation.x, new_allocation.y, +- new_allocation.width, new_allocation.height); */ +- +- gtk_widget_size_allocate(child_widget, &new_allocation); +-} +- + /* static methods */ + + void moz_container_class_init(MozContainerClass *klass) { +@@ -146,6 +132,11 @@ void moz_container_class_init(MozContain + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + + widget_class->map = moz_container_map; ++#if defined(MOZ_WAYLAND) ++ if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) { ++ widget_class->map_event = moz_container_map_wayland; ++ } ++#endif + widget_class->unmap = moz_container_unmap; + widget_class->realize = moz_container_realize; + widget_class->size_allocate = moz_container_size_allocate; +@@ -155,109 +146,81 @@ void moz_container_class_init(MozContain + container_class->add = moz_container_add; + } + +-#if defined(MOZ_WAYLAND) +-static void registry_handle_global(void *data, struct wl_registry *registry, +- uint32_t name, const char *interface, +- uint32_t version) { +- MozContainer *container = MOZ_CONTAINER(data); +- if (strcmp(interface, "wl_subcompositor") == 0) { +- container->subcompositor = static_cast( +- wl_registry_bind(registry, name, &wl_subcompositor_interface, 1)); +- } +-} +- +-static void registry_handle_global_remove(void *data, +- struct wl_registry *registry, +- uint32_t name) {} +- +-static const struct wl_registry_listener registry_listener = { +- registry_handle_global, registry_handle_global_remove}; +-#endif +- + void moz_container_init(MozContainer *container) { + gtk_widget_set_can_focus(GTK_WIDGET(container), TRUE); + gtk_container_set_resize_mode(GTK_CONTAINER(container), GTK_RESIZE_IMMEDIATE); + gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container), FALSE); + + #if defined(MOZ_WAYLAND) +- { +- 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); +- } +- } ++ container->surface = nullptr; ++ container->subsurface = nullptr; ++ container->eglwindow = nullptr; ++ container->frame_callback_handler = nullptr; ++ // We can draw to x11 window any time. ++ container->ready_to_draw = GDK_IS_X11_DISPLAY(gdk_display_get_default()); ++ container->surface_needs_clear = true; + #endif + } + + #if defined(MOZ_WAYLAND) +-/* 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. +- */ +-static gboolean moz_container_map_surface(MozContainer *container) { +- // Available as of GTK 3.8+ +- static auto sGdkWaylandDisplayGetWlCompositor = +- (wl_compositor * (*)(GdkDisplay *)) +- dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_compositor"); ++static wl_surface *moz_container_get_gtk_container_surface( ++ MozContainer *container) { + static auto sGdkWaylandWindowGetWlSurface = (wl_surface * (*)(GdkWindow *)) + dlsym(RTLD_DEFAULT, "gdk_wayland_window_get_wl_surface"); + +- GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container)); +- if (GDK_IS_X11_DISPLAY(display)) return false; ++ GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container)); ++ return sGdkWaylandWindowGetWlSurface(window); ++} + +- if (container->subsurface && container->surface) return true; ++static void frame_callback_handler(void *data, struct wl_callback *callback, ++ uint32_t time) { ++ MozContainer *container = MOZ_CONTAINER(data); ++ g_clear_pointer(&container->frame_callback_handler, wl_callback_destroy); ++ container->ready_to_draw = true; ++} + +- if (!container->surface) { +- struct wl_compositor *compositor; +- compositor = sGdkWaylandDisplayGetWlCompositor(display); +- container->surface = wl_compositor_create_surface(compositor); +- } ++static const struct wl_callback_listener frame_listener = { ++ frame_callback_handler}; + +- if (!container->subsurface) { +- GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container)); +- wl_surface *gtk_surface = sGdkWaylandWindowGetWlSurface(window); +- if (!gtk_surface) { +- // We requested the underlying wl_surface too early when container +- // is not realized yet. We'll try again before first rendering +- // to mContainer. +- return false; +- } ++static gboolean moz_container_map_wayland(GtkWidget *widget, GdkEventAny *event) { ++ MozContainer* container = MOZ_CONTAINER(widget); + +- container->subsurface = wl_subcompositor_get_subsurface( +- container->subcompositor, container->surface, gtk_surface); +- gint x, y; +- gdk_window_get_position(window, &x, &y); +- wl_subsurface_set_position(container->subsurface, x, y); +- wl_subsurface_set_desync(container->subsurface); ++ if (container->ready_to_draw || container->frame_callback_handler) { ++ return FALSE; ++ } + +- // Route input to parent wl_surface owned by Gtk+ so we get input +- // events from Gtk+. +- GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container)); +- wl_compositor *compositor = sGdkWaylandDisplayGetWlCompositor(display); +- wl_region *region = wl_compositor_create_region(compositor); +- wl_surface_set_input_region(container->surface, region); +- wl_region_destroy(region); ++ wl_surface *gtk_container_surface = ++ moz_container_get_gtk_container_surface(container); + -+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 (gtk_container_surface) { ++ container->frame_callback_handler = wl_surface_frame(gtk_container_surface); ++ wl_callback_add_listener(container->frame_callback_handler, &frame_listener, ++ container); + } +- return true; + ++ return FALSE; + } + +-static void moz_container_unmap_surface(MozContainer *container) { ++static void moz_container_unmap_wayland(MozContainer *container) { + g_clear_pointer(&container->subsurface, wl_subsurface_destroy); + g_clear_pointer(&container->surface, wl_surface_destroy); ++ g_clear_pointer(&container->frame_callback_handler, wl_callback_destroy); ++ ++ container->surface_needs_clear = true; ++ container->ready_to_draw = false; + } + ++static gint moz_container_get_scale(MozContainer *container) { ++ static auto sGdkWindowGetScaleFactorPtr = (gint(*)(GdkWindow *))dlsym( ++ RTLD_DEFAULT, "gdk_window_get_scale_factor"); ++ ++ if (sGdkWindowGetScaleFactorPtr) { + 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 (*sGdkWindowGetScaleFactorPtr)(window); + } -+ return container->eglwindow;*/ return nullptr; -+} + -+gboolean -+moz_container_has_wl_egl_window(MozContainer *container) -+{ -+ return container->eglwindow ? true : false; ++ return 1; +} #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; + + void moz_container_map(GtkWidget *widget) { +@@ -283,7 +246,9 @@ void moz_container_map(GtkWidget *widget + if (gtk_widget_get_has_window(widget)) { + gdk_window_show(gtk_widget_get_window(widget)); + #if defined(MOZ_WAYLAND) +- moz_container_map_surface(MOZ_CONTAINER(widget)); ++ if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) { ++ moz_container_map_wayland(widget, nullptr); ++ } + #endif + } + } +@@ -296,7 +261,9 @@ void moz_container_unmap(GtkWidget *widg + if (gtk_widget_get_has_window(widget)) { + gdk_window_hide(gtk_widget_get_window(widget)); + #if defined(MOZ_WAYLAND) +- moz_container_unmap_surface(MOZ_CONTAINER(widget)); ++ if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) { ++ moz_container_unmap_wayland(MOZ_CONTAINER(widget)); ++ } + #endif + } + } +@@ -485,13 +452,62 @@ static void moz_container_add(GtkContain + + #ifdef MOZ_WAYLAND + struct wl_surface *moz_container_get_wl_surface(MozContainer *container) { +- if (!container->subsurface || !container->surface) { ++ if (!container->surface) { ++ if (!container->ready_to_draw) { ++ return nullptr; ++ } ++ GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container)); ++ ++ // Available as of GTK 3.8+ ++ static auto sGdkWaylandDisplayGetWlCompositor = ++ (wl_compositor * (*)(GdkDisplay *)) ++ dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_compositor"); ++ struct wl_compositor *compositor = ++ sGdkWaylandDisplayGetWlCompositor(display); ++ container->surface = wl_compositor_create_surface(compositor); ++ ++ nsWaylandDisplay *waylandDisplay = WaylandDisplayGet(display); ++ container->subsurface = wl_subcompositor_get_subsurface( ++ waylandDisplay->GetSubcompositor(), container->surface, ++ moz_container_get_gtk_container_surface(container)); ++ WaylandDisplayRelease(waylandDisplay); ++ + GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container)); +- if (!gdk_window_is_visible(window)) return nullptr; ++ gint x, y; ++ gdk_window_get_position(window, &x, &y); ++ wl_subsurface_set_position(container->subsurface, x, y); ++ wl_subsurface_set_desync(container->subsurface); + +- moz_container_map_surface(container); ++ // Route input to parent wl_surface owned by Gtk+ so we get input ++ // events from Gtk+. ++ wl_region *region = wl_compositor_create_region(compositor); ++ wl_surface_set_input_region(container->surface, region); ++ wl_region_destroy(region); ++ ++ wl_surface_set_buffer_scale(container->surface, ++ moz_container_get_scale(container)); + } + + return container->surface; + } ++ ++struct wl_egl_window *moz_container_get_wl_egl_window(MozContainer *container) { ++ if (!container->eglwindow) { ++ wl_surface *surface = moz_container_get_wl_surface(container); ++ if (!surface) { ++ return nullptr; ++ } ++ } ++ return container->eglwindow; ++} ++ ++gboolean moz_container_has_wl_egl_window(MozContainer *container) { ++ return container->eglwindow ? true : false; ++} ++ ++gboolean moz_container_surface_needs_clear(MozContainer *container) { ++ gboolean state = container->surface_needs_clear; ++ container->surface_needs_clear = false; ++ return state; ++} + #endif +diff -up thunderbird-60.5.0/widget/gtk/mozcontainer.h.wayland thunderbird-60.5.0/widget/gtk/mozcontainer.h +--- thunderbird-60.5.0/widget/gtk/mozcontainer.h.wayland 2019-01-22 20:44:03.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/mozcontainer.h 2019-02-05 14:26:16.974316651 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public +@@ -63,7 +63,6 @@ typedef struct _MozContainerClass MozCon + * present in wayland-devel < 1.12 + */ + #ifdef MOZ_WAYLAND +-struct wl_subcompositor; + struct wl_surface; + struct wl_subsurface; + #endif +@@ -73,9 +72,12 @@ struct _MozContainer { + GList *children; + + #ifdef MOZ_WAYLAND +- struct wl_subcompositor *subcompositor; + struct wl_surface *surface; + struct wl_subsurface *subsurface; ++ struct wl_egl_window *eglwindow; ++ struct wl_callback *frame_callback_handler; ++ gboolean surface_needs_clear; ++ gboolean ready_to_draw; #endif }; -@@ -95,6 +98,8 @@ void moz_container_move ( +@@ -87,11 +89,13 @@ GType moz_container_get_type(void); + GtkWidget *moz_container_new(void); + void moz_container_put(MozContainer *container, GtkWidget *child_widget, gint x, + gint y); +-void moz_container_move(MozContainer *container, GtkWidget *child_widget, +- gint x, gint y, gint width, gint height); #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); + 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); ++gboolean moz_container_surface_needs_clear(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) +diff -up thunderbird-60.5.0/widget/gtk/mozgtk/mozgtk.c.wayland thunderbird-60.5.0/widget/gtk/mozgtk/mozgtk.c +--- thunderbird-60.5.0/widget/gtk/mozgtk/mozgtk.c.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/mozgtk/mozgtk.c 2019-02-05 14:26:16.974316651 +0100 +@@ -26,6 +26,7 @@ STUB(gdk_display_sync) + STUB(gdk_display_warp_pointer) + STUB(gdk_drag_context_get_actions) + STUB(gdk_drag_context_get_dest_window) ++STUB(gdk_drag_context_get_source_window) + STUB(gdk_drag_context_list_targets) + STUB(gdk_drag_status) + STUB(gdk_error_trap_pop) +@@ -55,6 +56,7 @@ STUB(gdk_pointer_grab) + STUB(gdk_pointer_ungrab) + STUB(gdk_property_change) + STUB(gdk_property_get) ++STUB(gdk_property_delete) + STUB(gdk_screen_get_default) + STUB(gdk_screen_get_display) + STUB(gdk_screen_get_font_options) +@@ -136,6 +138,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) @@ -207,7 +439,7 @@ diff -up thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland thunderbird-60.3. 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) +@@ -267,6 +271,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) @@ -215,125 +447,261 @@ diff -up thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland thunderbird-60.3. 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 - { +@@ -411,6 +416,7 @@ STUB(gtk_table_get_type) + STUB(gtk_table_new) + STUB(gtk_target_list_add) + STUB(gtk_target_list_add_image_targets) ++STUB(gtk_target_list_add_text_targets) + STUB(gtk_target_list_new) + STUB(gtk_target_list_unref) + STUB(gtk_targets_include_image) +@@ -491,6 +497,7 @@ STUB(gtk_widget_unrealize) + STUB(gtk_window_deiconify) + STUB(gtk_window_fullscreen) + STUB(gtk_window_get_group) ++STUB(gtk_window_get_modal) + STUB(gtk_window_get_transient_for) + STUB(gtk_window_get_type) + STUB(gtk_window_get_type_hint) +diff -up thunderbird-60.5.0/widget/gtk/mozwayland/mozwayland.c.wayland thunderbird-60.5.0/widget/gtk/mozwayland/mozwayland.c +--- thunderbird-60.5.0/widget/gtk/mozwayland/mozwayland.c.wayland 2019-01-22 20:44:02.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/mozwayland/mozwayland.c 2019-02-05 14:26:16.974316651 +0100 +@@ -1,14 +1,23 @@ +-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + ++#include + #include "mozilla/Types.h" + #include ++#include + #include + ++union wl_argument; ++ ++/* Those strucures are just placeholders and will be replaced by ++ * real symbols from libwayland during run-time linking. We need to make ++ * them explicitly visible. ++ */ ++#pragma GCC visibility push(default) + const struct wl_interface wl_buffer_interface; + const struct wl_interface wl_callback_interface; + const struct wl_interface wl_data_device_interface; +@@ -22,6 +31,7 @@ const struct wl_interface wl_seat_interf + const struct wl_interface wl_surface_interface; + const struct wl_interface wl_subsurface_interface; + const struct wl_interface wl_subcompositor_interface; ++#pragma GCC visibility pop + + MOZ_EXPORT void wl_event_queue_destroy(struct wl_event_queue *queue) {} + +@@ -75,6 +85,10 @@ MOZ_EXPORT const void *wl_proxy_get_list + return NULL; } -+MOZ_EXPORT struct wl_egl_window * -+wl_egl_window_create(struct wl_surface *surface, -+ int width, int height) -+{ -+ return NULL; ++typedef int (*wl_dispatcher_func_t)(const void *, void *, uint32_t, ++ const struct wl_message *, ++ union wl_argument *); ++ + MOZ_EXPORT int wl_proxy_add_dispatcher(struct wl_proxy *proxy, + wl_dispatcher_func_t dispatcher_func, + const void *dispatcher_data, +@@ -160,3 +174,13 @@ MOZ_EXPORT void wl_display_cancel_read(s + MOZ_EXPORT int wl_display_read_events(struct wl_display *display) { return -1; } + + MOZ_EXPORT void wl_log_set_handler_client(wl_log_func_t handler) {} ++ ++MOZ_EXPORT struct wl_egl_window *wl_egl_window_create( ++ struct wl_surface *surface, int width, int height) { ++ return NULL; +} + -+MOZ_EXPORT void -+wl_egl_window_destroy(struct wl_egl_window *egl_window) -+{ ++MOZ_EXPORT void wl_egl_window_destroy(struct wl_egl_window *egl_window) {} ++ ++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.5.0/widget/gtk/mozwayland/mozwayland.h.wayland thunderbird-60.5.0/widget/gtk/mozwayland/mozwayland.h +--- thunderbird-60.5.0/widget/gtk/mozwayland/mozwayland.h.wayland 2019-02-05 14:26:16.975316648 +0100 ++++ thunderbird-60.5.0/widget/gtk/mozwayland/mozwayland.h 2019-02-05 14:26:16.975316648 +0100 +@@ -0,0 +1,115 @@ ++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim:expandtab:shiftwidth=4:tabstop=4: ++ */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * 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/. */ ++ ++/* Wayland compatibility header, it makes Firefox build with ++ wayland-1.2 and Gtk+ 3.10. ++*/ ++ ++#ifndef __MozWayland_h_ ++#define __MozWayland_h_ ++ ++#include "mozilla/Types.h" ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++MOZ_EXPORT int wl_display_roundtrip_queue(struct wl_display *display, ++ struct wl_event_queue *queue); ++MOZ_EXPORT uint32_t wl_proxy_get_version(struct wl_proxy *proxy); ++MOZ_EXPORT struct wl_proxy *wl_proxy_marshal_constructor( ++ struct wl_proxy *proxy, uint32_t opcode, ++ const struct wl_interface *interface, ...); ++ ++/* We need implement some missing functions from wayland-client-protocol.h ++ */ ++#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM ++enum wl_data_device_manager_dnd_action { ++ WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE = 0, ++ WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY = 1, ++ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE = 2, ++ WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4 ++}; ++#endif ++ ++#ifndef WL_DATA_OFFER_SET_ACTIONS ++#define WL_DATA_OFFER_SET_ACTIONS 4 ++ ++struct moz_wl_data_offer_listener { ++ void (*offer)(void *data, struct wl_data_offer *wl_data_offer, ++ const char *mime_type); ++ void (*source_actions)(void *data, struct wl_data_offer *wl_data_offer, ++ uint32_t source_actions); ++ void (*action)(void *data, struct wl_data_offer *wl_data_offer, ++ uint32_t dnd_action); ++}; ++ ++static inline void wl_data_offer_set_actions( ++ struct wl_data_offer *wl_data_offer, uint32_t dnd_actions, ++ uint32_t preferred_action) { ++ wl_proxy_marshal((struct wl_proxy *)wl_data_offer, WL_DATA_OFFER_SET_ACTIONS, ++ dnd_actions, preferred_action); ++} ++#else ++typedef struct wl_data_offer_listener moz_wl_data_offer_listener; ++#endif ++ ++#ifndef WL_SUBCOMPOSITOR_GET_SUBSURFACE ++#define WL_SUBCOMPOSITOR_GET_SUBSURFACE 1 ++struct wl_subcompositor; ++ ++// Emulate what mozilla header wrapper does - make the ++// wl_subcompositor_interface always visible. ++#pragma GCC visibility push(default) ++extern const struct wl_interface wl_subsurface_interface; ++extern const struct wl_interface wl_subcompositor_interface; ++#pragma GCC visibility pop ++ ++#define WL_SUBSURFACE_DESTROY 0 ++#define WL_SUBSURFACE_SET_POSITION 1 ++#define WL_SUBSURFACE_PLACE_ABOVE 2 ++#define WL_SUBSURFACE_PLACE_BELOW 3 ++#define WL_SUBSURFACE_SET_SYNC 4 ++#define WL_SUBSURFACE_SET_DESYNC 5 ++ ++static inline struct wl_subsurface *wl_subcompositor_get_subsurface( ++ struct wl_subcompositor *wl_subcompositor, struct wl_surface *surface, ++ struct wl_surface *parent) { ++ struct wl_proxy *id; ++ ++ id = wl_proxy_marshal_constructor( ++ (struct wl_proxy *)wl_subcompositor, WL_SUBCOMPOSITOR_GET_SUBSURFACE, ++ &wl_subsurface_interface, NULL, surface, parent); ++ ++ return (struct wl_subsurface *)id; +} + -+MOZ_EXPORT void -+wl_egl_window_resize(struct wl_egl_window *egl_window, -+ int width, int height, -+ int dx, int dy) -+{ ++static inline void wl_subsurface_set_position( ++ struct wl_subsurface *wl_subsurface, int32_t x, int32_t y) { ++ wl_proxy_marshal((struct wl_proxy *)wl_subsurface, WL_SUBSURFACE_SET_POSITION, ++ x, y); +} -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 - } ++ ++static inline void wl_subsurface_set_desync( ++ struct wl_subsurface *wl_subsurface) { ++ wl_proxy_marshal((struct wl_proxy *)wl_subsurface, WL_SUBSURFACE_SET_DESYNC); ++} ++ ++static inline void wl_subsurface_destroy(struct wl_subsurface *wl_subsurface) { ++ wl_proxy_marshal((struct wl_proxy *)wl_subsurface, WL_SUBSURFACE_DESTROY); ++ ++ wl_proxy_destroy((struct wl_proxy *)wl_subsurface); ++} ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __MozWayland_h_ */ +diff -up thunderbird-60.5.0/widget/gtk/nsClipboard.cpp.wayland thunderbird-60.5.0/widget/gtk/nsClipboard.cpp +--- thunderbird-60.5.0/widget/gtk/nsClipboard.cpp.wayland 2019-01-22 20:44:03.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsClipboard.cpp 2019-02-05 14:26:16.975316648 +0100 +@@ -72,7 +72,7 @@ nsClipboard::~nsClipboard() { + } } -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" + +-NS_IMPL_ISUPPORTS(nsClipboard, nsIClipboard) ++NS_IMPL_ISUPPORTS(nsClipboard, nsIClipboard, nsIObserver) + + nsresult nsClipboard::Init(void) { + GdkDisplay *display = gdk_display_get_default(); +diff -up thunderbird-60.5.0/widget/gtk/nsClipboardWayland.cpp.wayland thunderbird-60.5.0/widget/gtk/nsClipboardWayland.cpp +--- thunderbird-60.5.0/widget/gtk/nsClipboardWayland.cpp.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsClipboardWayland.cpp 2019-02-05 14:26:16.975316648 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public +@@ -20,9 +20,11 @@ + #include "nsImageToPixbuf.h" + #include "nsStringStream.h" + #include "nsIObserverService.h" +-#include "mozilla/Services.h" #include "mozilla/RefPtr.h" #include "mozilla/TimeStamp.h" +#include "nsDragService.h" ++#include "mozwayland/mozwayland.h" ++#include "nsWaylandDisplay.h" #include "imgIContainer.h" -@@ -46,6 +47,44 @@ nsRetrievalContextWayland::sTextMimeType - "COMPOUND_TEXT" - }; +@@ -31,15 +33,43 @@ + #include + #include + #include +-#include +-#include + #include -+static inline GdkDragAction -+wl_to_gdk_actions(uint32_t dnd_actions) -+{ +-#include "wayland/gtk-primary-selection-client-protocol.h" +- + const char *nsRetrievalContextWayland::sTextMimeTypes[TEXT_MIME_TYPES_NUM] = { + "text/plain;charset=utf-8", "UTF8_STRING", "COMPOUND_TEXT"}; + ++static inline GdkDragAction wl_to_gdk_actions(uint32_t dnd_actions) { + GdkDragAction actions = GdkDragAction(0); + + if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) -+ actions = GdkDragAction(actions|GDK_ACTION_COPY); ++ actions = GdkDragAction(actions | GDK_ACTION_COPY); + if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) -+ actions = GdkDragAction(actions|GDK_ACTION_MOVE); ++ actions = GdkDragAction(actions | GDK_ACTION_MOVE); + + return actions; +} + -+static inline uint32_t -+gdk_to_wl_actions(GdkDragAction action) -+{ ++static inline uint32_t gdk_to_wl_actions(GdkDragAction action) { + uint32_t dnd_actions = 0; + + if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_PRIVATE)) @@ -344,120 +712,102 @@ diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland thunderbir + return dnd_actions; +} + -+static GtkWidget* -+get_gtk_widget_for_wl_surface(struct wl_surface *surface) -+{ -+ GdkWindow *gdkParentWindow = -+ static_cast(wl_surface_get_user_data(surface)); ++static GtkWidget *get_gtk_widget_for_wl_surface(struct wl_surface *surface) { ++ GdkWindow *gdkParentWindow = ++ static_cast(wl_surface_get_user_data(surface)); + -+ gpointer user_data = nullptr; -+ gdk_window_get_user_data(gdkParentWindow, &user_data); ++ gpointer user_data = nullptr; ++ gdk_window_get_user_data(gdkParentWindow, &user_data); + -+ return GTK_WIDGET(user_data); ++ return GTK_WIDGET(user_data); +} + - void - DataOffer::AddMIMEType(const char *aMimeType) - { -@@ -114,7 +153,7 @@ DataOffer::GetData(wl_display* aDisplay, + void DataOffer::AddMIMEType(const char *aMimeType) { + GdkAtom atom = gdk_atom_intern(aMimeType, FALSE); + mTargetMIMETypes.AppendElement(atom); +@@ -98,7 +128,7 @@ char *DataOffer::GetData(wl_display *aDi - GIOChannel *channel = g_io_channel_unix_new(pipe_fd[0]); - GError* error = nullptr; -- char* clipboardData; -+ char* clipboardData = nullptr; + 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; + g_io_channel_set_encoding(channel, nullptr, &error); + if (!error) { +@@ -138,31 +168,92 @@ bool WaylandDataOffer::RequestDataTransf + return false; } -+void -+WaylandDataOffer::DragOfferAccept(const char* aMimeType, uint32_t aTime) -+{ -+ wl_data_offer_accept(mWaylandDataOffer, aTime, aMimeType); ++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; ++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); ++ 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(). ++ /* 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])); -+ } ++ 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; ++void WaylandDataOffer::SetSelectedDragAction(uint32_t aWaylandAction) { ++ mSelectedDragAction = aWaylandAction; +} + -+GdkDragAction -+WaylandDataOffer::GetSelectedDragAction() -+{ -+ return wl_to_gdk_actions(mSelectedDragAction); ++GdkDragAction WaylandDataOffer::GetSelectedDragAction() { ++ return wl_to_gdk_actions(mSelectedDragAction); +} + -+void -+WaylandDataOffer::SetAvailableDragActions(uint32_t aWaylandActions) -+{ -+ mAvailableDragAction = aWaylandActions; ++void WaylandDataOffer::SetAvailableDragActions(uint32_t aWaylandActions) { ++ mAvailableDragAction = aWaylandActions; +} + -+GdkDragAction -+WaylandDataOffer::GetAvailableDragActions() -+{ -+ return wl_to_gdk_actions(mAvailableDragAction); ++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); + static void data_offer_offer(void *data, struct wl_data_offer *wl_data_offer, + const char *type) { + auto *offer = static_cast(data); + 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); - } + static void data_offer_source_actions(void *data, + struct wl_data_offer *wl_data_offer, +- uint32_t source_actions) {} ++ 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); - } + static void data_offer_action(void *data, struct wl_data_offer *wl_data_offer, +- uint32_t dnd_action) {} ++ uint32_t dnd_action) { ++ auto *offer = static_cast(data); ++ offer->SetSelectedDragAction(dnd_action); ++} /* wl_data_offer callback description: * @@ -470,565 +820,678 @@ diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland thunderbir + * 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 - } +-static const struct wl_data_offer_listener data_offer_listener = { ++static const moz_wl_data_offer_listener data_offer_listener = { + data_offer_offer, data_offer_source_actions, data_offer_action}; + + WaylandDataOffer::WaylandDataOffer(wl_data_offer *aWaylandDataOffer) + : mWaylandDataOffer(aWaylandDataOffer) { +- wl_data_offer_add_listener(mWaylandDataOffer, &data_offer_listener, this); ++ wl_data_offer_add_listener( ++ mWaylandDataOffer, (struct wl_data_offer_listener *)&data_offer_listener, ++ this); } + WaylandDataOffer::~WaylandDataOffer(void) { +@@ -207,20 +298,93 @@ PrimaryDataOffer::~PrimaryDataOffer(void + } + } + +-void nsRetrievalContextWayland::RegisterDataOffer( +NS_IMPL_ISUPPORTS(nsWaylandDragContext, nsISupports); + -+nsWaylandDragContext::nsWaylandDragContext(WaylandDataOffer* aDataOffer, ++nsWaylandDragContext::nsWaylandDragContext(WaylandDataOffer *aDataOffer, + wl_display *aDisplay) -+ : mDataOffer(aDataOffer) -+ , mDisplay(aDisplay) -+ , mTime(0) -+ , mGtkWidget(nullptr) -+ , mX(0) -+ , mY(0) -+{ ++ : 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 -+nsWaylandDragContext::DropDataEnter(GtkWidget* aGtkWidget, uint32_t aTime, -+ nscoord aX, nscoord aY) -+{ -+ mTime = aTime; -+ mGtkWidget = aGtkWidget; -+ mX = aX; -+ mY = aY; ++void nsWaylandDragContext::DropMotion(uint32_t aTime, nscoord aX, nscoord aY) { ++ mTime = aTime; ++ 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::GetLastDropInfo(uint32_t *aTime, nscoord *aX, nscoord *aY) -+{ -+ *aTime = mTime; -+ *aX = mX; -+ *aY = mY; ++void nsWaylandDragContext::SetDragStatus(GdkDragAction aAction) { ++ mDataOffer->SetDragStatus(aAction, mTime); +} + -+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; +} + -+GdkDragAction -+nsWaylandDragContext::GetSelectedDragAction() -+{ -+ GdkDragAction gdkAction = mDataOffer->GetSelectedDragAction(); ++GList *nsWaylandDragContext::GetTargets() { ++ int targetNums; ++ GdkAtom *atoms = mDataOffer->GetTargets(&targetNums); + -+ // We emulate gdk_drag_context_get_actions() here. -+ if (!gdkAction) { -+ gdkAction = mDataOffer->GetAvailableDragActions(); -+ } ++ GList *targetList = nullptr; ++ for (int i = 0; i < targetNums; i++) { ++ targetList = g_list_append(targetList, GDK_ATOM_TO_POINTER(atoms[i])); ++ } + -+ return gdkAction; ++ return targetList; +} + -+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); +} + -+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, ++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 = new WaylandDataOffer(aWaylandDataOffer); + g_hash_table_insert(mActiveOffers, aWaylandDataOffer, dataOffer); + } } - void --nsRetrievalContextWayland::RegisterDataOffer( -+nsRetrievalContextWayland::RegisterNewDataOffer( - gtk_primary_selection_offer *aPrimaryDataOffer) - { - DataOffer* dataOffer = - static_cast(g_hash_table_lookup(mActiveOffers, - aPrimaryDataOffer)); -+ MOZ_ASSERT(dataOffer == nullptr, +-void nsRetrievalContextWayland::RegisterDataOffer( ++void nsRetrievalContextWayland::RegisterNewDataOffer( + gtk_primary_selection_offer *aPrimaryDataOffer) { + DataOffer *dataOffer = static_cast( + g_hash_table_lookup(mActiveOffers, aPrimaryDataOffer)); ++ MOZ_ASSERT( ++ dataOffer == nullptr, + "Registered PrimaryDataOffer already exists. Wayland protocol error?"); + if (!dataOffer) { - dataOffer = new PrimaryDataOffer(aPrimaryDataOffer); - g_hash_table_insert(mActiveOffers, aPrimaryDataOffer, dataOffer); -@@ -274,6 +467,9 @@ nsRetrievalContextWayland::RegisterDataO - void - nsRetrievalContextWayland::SetClipboardDataOffer(wl_data_offer *aWaylandDataOffer) - { -+ // Delete existing clipboard data offer -+ mClipboardOffer = nullptr; + dataOffer = new PrimaryDataOffer(aPrimaryDataOffer); + g_hash_table_insert(mActiveOffers, aPrimaryDataOffer, dataOffer); +@@ -229,21 +393,30 @@ void nsRetrievalContextWayland::Register + + void nsRetrievalContextWayland::SetClipboardDataOffer( + wl_data_offer *aWaylandDataOffer) { +- DataOffer *dataOffer = static_cast( +- g_hash_table_lookup(mActiveOffers, aWaylandDataOffer)); +- NS_ASSERTION(dataOffer, "We're missing clipboard data offer!"); +- if (dataOffer) { +- g_hash_table_remove(mActiveOffers, aWaylandDataOffer); +- mClipboardOffer = dataOffer; ++ // Delete existing clipboard data offer ++ mClipboardOffer = nullptr; + - DataOffer* dataOffer = - static_cast(g_hash_table_lookup(mActiveOffers, - aWaylandDataOffer)); -@@ -288,10 +484,12 @@ void - nsRetrievalContextWayland::SetPrimaryDataOffer( - gtk_primary_selection_offer *aPrimaryDataOffer) - { -- if (aPrimaryDataOffer == nullptr) { -- // Release any primary offer we have. -- mPrimaryOffer = nullptr; -- } else { -+ // Release any primary offer we have. -+ mPrimaryOffer = nullptr; -+ -+ // aPrimaryDataOffer can be null which means we lost -+ // the mouse selection. -+ if (aPrimaryDataOffer) { - DataOffer* dataOffer = - static_cast(g_hash_table_lookup(mActiveOffers, - aPrimaryDataOffer)); -@@ -304,12 +502,31 @@ nsRetrievalContextWayland::SetPrimaryDat ++ // null aWaylandDataOffer indicates that our clipboard content ++ // is no longer valid and should be release. ++ if (aWaylandDataOffer != nullptr) { ++ DataOffer *dataOffer = static_cast( ++ g_hash_table_lookup(mActiveOffers, aWaylandDataOffer)); ++ NS_ASSERTION(dataOffer, "We're missing stored clipboard data offer!"); ++ if (dataOffer) { ++ g_hash_table_remove(mActiveOffers, aWaylandDataOffer); ++ mClipboardOffer = dataOffer; ++ } + } } - void --nsRetrievalContextWayland::ClearDataOffers(void) -+nsRetrievalContextWayland::AddDragAndDropDataOffer(wl_data_offer *aDropDataOffer) - { -- if (mClipboardOffer) -- mClipboardOffer = nullptr; -- if (mPrimaryOffer) -- mPrimaryOffer = nullptr; -+ // Remove any existing D&D contexts. -+ mDragContext = nullptr; + void nsRetrievalContextWayland::SetPrimaryDataOffer( + gtk_primary_selection_offer *aPrimaryDataOffer) { +- if (aPrimaryDataOffer == nullptr) { +- // Release any primary offer we have. +- mPrimaryOffer = nullptr; +- } else { ++ // Release any primary offer we have. ++ mPrimaryOffer = nullptr; + -+ WaylandDataOffer* dataOffer = -+ static_cast(g_hash_table_lookup(mActiveOffers, -+ aDropDataOffer)); -+ NS_ASSERTION(dataOffer, "We're missing drag and drop data offer!"); -+ if (dataOffer) { -+ g_hash_table_remove(mActiveOffers, aDropDataOffer); -+ mDragContext = new nsWaylandDragContext(dataOffer, mDisplay); -+ } ++ // aPrimaryDataOffer can be null which means we lost ++ // the mouse selection. ++ if (aPrimaryDataOffer) { + DataOffer *dataOffer = static_cast( + g_hash_table_lookup(mActiveOffers, aPrimaryDataOffer)); + NS_ASSERTION(dataOffer, "We're missing primary data offer!"); +@@ -254,9 +427,26 @@ void nsRetrievalContextWayland::SetPrima + } + } + +-void nsRetrievalContextWayland::ClearDataOffers(void) { +- if (mClipboardOffer) mClipboardOffer = nullptr; +- if (mPrimaryOffer) mPrimaryOffer = nullptr; ++void nsRetrievalContextWayland::AddDragAndDropDataOffer( ++ wl_data_offer *aDropDataOffer) { ++ // Remove any existing D&D contexts. ++ mDragContext = nullptr; ++ ++ WaylandDataOffer *dataOffer = static_cast( ++ g_hash_table_lookup(mActiveOffers, aDropDataOffer)); ++ NS_ASSERTION(dataOffer, "We're missing drag and drop data offer!"); ++ if (dataOffer) { ++ g_hash_table_remove(mActiveOffers, aDropDataOffer); ++ mDragContext = new nsWaylandDragContext(dataOffer, mDisplay->GetDisplay()); ++ } +} + -+nsWaylandDragContext* -+nsRetrievalContextWayland::GetDragContext(void) -+{ -+ return mDragContext; ++nsWaylandDragContext *nsRetrievalContextWayland::GetDragContext(void) { ++ return mDragContext; +} + -+void -+nsRetrievalContextWayland::ClearDragAndDropDataOffer(void) -+{ -+ mDragContext = nullptr; ++void nsRetrievalContextWayland::ClearDragAndDropDataOffer(void) { ++ mDragContext = nullptr; } // We have a new fresh data content. -@@ -321,7 +538,7 @@ data_device_data_offer (void - { - nsRetrievalContextWayland *context = - static_cast(data); -- context->RegisterDataOffer(offer); -+ context->RegisterNewDataOffer(offer); +@@ -266,7 +456,7 @@ static void data_device_data_offer(void + struct wl_data_offer *offer) { + nsRetrievalContextWayland *context = + static_cast(data); +- context->RegisterDataOffer(offer); ++ context->RegisterNewDataOffer(offer); } // The new fresh data content is clipboard. -@@ -341,31 +558,78 @@ data_device_enter (void - struct wl_data_device *data_device, - uint32_t time, - struct wl_surface *surface, -- int32_t x, -- int32_t y, -+ int32_t x_fixed, -+ int32_t y_fixed, - struct wl_data_offer *offer) - { -+ nsRetrievalContextWayland *context = -+ static_cast(data); -+ context->AddDragAndDropDataOffer(offer); +@@ -281,15 +471,65 @@ static void data_device_selection(void * + // The new fresh wayland data content is drag and drop. + static void data_device_enter(void *data, struct wl_data_device *data_device, + uint32_t time, struct wl_surface *surface, +- int32_t x, int32_t y, +- struct wl_data_offer *offer) {} ++ int32_t x_fixed, int32_t y_fixed, ++ struct wl_data_offer *offer) { ++ nsRetrievalContextWayland *context = ++ static_cast(data); ++ context->AddDragAndDropDataOffer(offer); + -+ nsWaylandDragContext* dragContext = context->GetDragContext(); ++ nsWaylandDragContext *dragContext = context->GetDragContext(); + -+ GtkWidget* gtkWidget = get_gtk_widget_for_wl_surface(surface); -+ if (!gtkWidget) { -+ NS_WARNING("DragAndDrop: Unable to get GtkWidget for wl_surface!"); -+ return; -+ } ++ GtkWidget *gtkWidget = get_gtk_widget_for_wl_surface(surface); ++ if (!gtkWidget) { ++ NS_WARNING("DragAndDrop: Unable to get GtkWidget for wl_surface!"); ++ return; ++ } + -+ LOGDRAG(("nsWindow data_device_enter for GtkWidget %p\n", -+ (void*)gtkWidget)); ++ LOGDRAG(("nsWindow data_device_enter for GtkWidget %p\n", (void *)gtkWidget)); + -+ dragContext->DropDataEnter(gtkWidget, time, -+ wl_fixed_to_int(x_fixed), -+ wl_fixed_to_int(y_fixed)); - } ++ dragContext->DropDataEnter(gtkWidget, time, wl_fixed_to_int(x_fixed), ++ wl_fixed_to_int(y_fixed)); ++} ++ ++static void data_device_leave(void *data, struct wl_data_device *data_device) { ++ nsRetrievalContextWayland *context = ++ static_cast(data); - static void - data_device_leave (void *data, - struct wl_data_device *data_device) - { -+ nsRetrievalContextWayland *context = -+ static_cast(data); +-static void data_device_leave(void *data, struct wl_data_device *data_device) {} ++ nsWaylandDragContext *dropContext = context->GetDragContext(); ++ WindowDragLeaveHandler(dropContext->GetWidget()); + -+ nsWaylandDragContext* dropContext = context->GetDragContext(); -+ WindowDragLeaveHandler(dropContext->GetWidget()); -+ -+ context->ClearDragAndDropDataOffer(); - } ++ context->ClearDragAndDropDataOffer(); ++} - static void - data_device_motion (void *data, - struct wl_data_device *data_device, - uint32_t time, -- int32_t x, -- int32_t y) -+ int32_t x_fixed, -+ int32_t y_fixed) - { -+ nsRetrievalContextWayland *context = -+ static_cast(data); + static void data_device_motion(void *data, struct wl_data_device *data_device, +- uint32_t time, int32_t x, int32_t y) {} ++ uint32_t time, int32_t x_fixed, ++ int32_t y_fixed) { ++ nsRetrievalContextWayland *context = ++ static_cast(data); + -+ nsWaylandDragContext* dropContext = context->GetDragContext(); -+ -+ nscoord x = wl_fixed_to_int(x_fixed); -+ nscoord y = wl_fixed_to_int(y_fixed); -+ dropContext->DropMotion(time, x, y); -+ -+ WindowDragMotionHandler(dropContext->GetWidget(), nullptr, -+ dropContext, x, y, time); - } ++ nsWaylandDragContext *dropContext = context->GetDragContext(); - static void - data_device_drop (void *data, - struct wl_data_device *data_device) - { -+ nsRetrievalContextWayland *context = -+ static_cast(data); +-static void data_device_drop(void *data, struct wl_data_device *data_device) {} ++ nscoord x = wl_fixed_to_int(x_fixed); ++ nscoord y = wl_fixed_to_int(y_fixed); ++ dropContext->DropMotion(time, x, y); + -+ nsWaylandDragContext* dropContext = context->GetDragContext(); ++ WindowDragMotionHandler(dropContext->GetWidget(), nullptr, dropContext, x, y, ++ time); ++} + -+ uint32_t time; -+ nscoord x, y; -+ dropContext->GetLastDropInfo(&time, &x, &y); ++static void data_device_drop(void *data, struct wl_data_device *data_device) { ++ nsRetrievalContextWayland *context = ++ static_cast(data); + -+ WindowDragDropHandler(dropContext->GetWidget(), nullptr, dropContext, -+ x, y, time); - } ++ nsWaylandDragContext *dropContext = context->GetDragContext(); ++ ++ uint32_t time; ++ nscoord x, y; ++ dropContext->GetLastDropInfo(&time, &x, &y); ++ ++ WindowDragDropHandler(dropContext->GetWidget(), nullptr, dropContext, x, y, ++ time); ++} /* wl_data_device callback description: -@@ -405,7 +669,7 @@ primary_selection_data_offer (void - // create and add listener - nsRetrievalContextWayland *context = - static_cast(data); -- context->RegisterDataOffer(gtk_primary_offer); -+ context->RegisterNewDataOffer(gtk_primary_offer); + * +@@ -323,7 +563,7 @@ static void primary_selection_data_offer + // create and add listener + nsRetrievalContextWayland *context = + static_cast(data); +- context->RegisterDataOffer(gtk_primary_offer); ++ context->RegisterNewDataOffer(gtk_primary_offer); } - static void -@@ -418,6 +682,18 @@ primary_selection_selection (void - context->SetPrimaryDataOffer(gtk_primary_offer); + static void primary_selection_selection( +@@ -335,6 +575,19 @@ static void primary_selection_selection( + context->SetPrimaryDataOffer(gtk_primary_offer); } +/* gtk_primary_selection_device callback description: + * + * primary_selection_data_offer - It's called when there's a new -+ * gtk_primary_selection_offer available. -+ * We need to attach gtk_primary_selection_offer_listener -+ * to it to get available MIME types. ++ * gtk_primary_selection_offer available. We need to ++ * attach gtk_primary_selection_offer_listener to it ++ * to get available MIME types. + * -+ * primary_selection_selection - It's called when the new gtk_primary_selection_offer -+ * is a primary selection content. It can be also called with -+ * gtk_primary_selection_offer = null which means there's no -+ * primary selection. ++ * primary_selection_selection - It's called when the new ++ * gtk_primary_selection_offer is a primary selection ++ * content. It can be also called with ++ * gtk_primary_selection_offer = null which means ++ * there's no primary selection. + */ - static const struct - gtk_primary_selection_device_listener primary_selection_device_listener = { - primary_selection_data_offer, -@@ -430,81 +706,6 @@ nsRetrievalContextWayland::HasSelectionS - return mPrimarySelectionDataDeviceManager != nullptr; + static const struct gtk_primary_selection_device_listener + primary_selection_device_listener = { + primary_selection_data_offer, +@@ -342,149 +595,29 @@ static const struct gtk_primary_selectio + }; + + bool nsRetrievalContextWayland::HasSelectionSupport(void) { +- return mPrimarySelectionDataDeviceManager != nullptr; +-} +- +-static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, +- uint32_t format, int fd, uint32_t size) {} +- +-static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, +- uint32_t serial, struct wl_surface *surface, +- struct wl_array *keys) {} +- +-static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, +- uint32_t serial, struct wl_surface *surface) { +- // We lost focus so our clipboard data are outdated +- nsRetrievalContextWayland *context = +- static_cast(data); +- +- context->ClearDataOffers(); ++ return mDisplay->GetPrimarySelectionDeviceManager() != nullptr; } --static void --keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, -- uint32_t format, int fd, uint32_t size) --{ --} +-static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, +- uint32_t serial, uint32_t time, uint32_t key, +- uint32_t state) {} - --static void --keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, -- uint32_t serial, struct wl_surface *surface, -- struct wl_array *keys) --{ --} -- --static void --keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, -- uint32_t serial, struct wl_surface *surface) --{ -- // We lost focus so our clipboard data are outdated -- nsRetrievalContextWayland *context = -- static_cast(data); -- -- context->ClearDataOffers(); --} -- --static void --keyboard_handle_key(void *data, struct wl_keyboard *keyboard, -- uint32_t serial, uint32_t time, uint32_t key, -- uint32_t state) --{ --} -- --static void --keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, -- uint32_t serial, uint32_t mods_depressed, -- uint32_t mods_latched, uint32_t mods_locked, -- uint32_t group) --{ --} +-static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, +- uint32_t serial, uint32_t mods_depressed, +- uint32_t mods_latched, +- uint32_t mods_locked, uint32_t group) {} - -static const struct wl_keyboard_listener keyboard_listener = { -- keyboard_handle_keymap, -- keyboard_handle_enter, -- keyboard_handle_leave, -- keyboard_handle_key, -- keyboard_handle_modifiers, +- keyboard_handle_keymap, keyboard_handle_enter, keyboard_handle_leave, +- keyboard_handle_key, keyboard_handle_modifiers, -}; - --void --nsRetrievalContextWayland::ConfigureKeyboard(wl_seat_capability caps) --{ +-void nsRetrievalContextWayland::ConfigureKeyboard(wl_seat_capability caps) { - // ConfigureKeyboard() is called when wl_seat configuration is changed. - // We look for the keyboard only, get it when is't available and release it - // when it's lost (we don't have focus for instance). - if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { -- mKeyboard = wl_seat_get_keyboard(mSeat); -- wl_keyboard_add_listener(mKeyboard, &keyboard_listener, this); +- mKeyboard = wl_seat_get_keyboard(mSeat); +- wl_keyboard_add_listener(mKeyboard, &keyboard_listener, this); - } else if (mKeyboard && !(caps & WL_SEAT_CAPABILITY_KEYBOARD)) { -- wl_keyboard_destroy(mKeyboard); -- mKeyboard = nullptr; +- wl_keyboard_destroy(mKeyboard); +- mKeyboard = nullptr; - } -} - --static void --seat_handle_capabilities(void *data, struct wl_seat *seat, -- unsigned int caps) --{ -- nsRetrievalContextWayland *context = -- static_cast(data); -- context->ConfigureKeyboard((wl_seat_capability)caps); +-static void seat_handle_capabilities(void *data, struct wl_seat *seat, +- unsigned int caps) { +- nsRetrievalContextWayland *context = +- static_cast(data); +- context->ConfigureKeyboard((wl_seat_capability)caps); -} - -static const struct wl_seat_listener seat_listener = { -- seat_handle_capabilities, +- seat_handle_capabilities, -}; - - void - nsRetrievalContextWayland::InitDataDeviceManager(wl_registry *registry, - uint32_t id, -@@ -530,7 +731,6 @@ nsRetrievalContextWayland::InitSeat(wl_r - void *data) - { - mSeat = (wl_seat*)wl_registry_bind(registry, id, &wl_seat_interface, 1); -- wl_seat_add_listener(mSeat, &seat_listener, data); +-void nsRetrievalContextWayland::InitDataDeviceManager(wl_registry *registry, +- uint32_t id, +- uint32_t version) { +- int data_device_manager_version = MIN(version, 3); +- mDataDeviceManager = (wl_data_device_manager *)wl_registry_bind( +- registry, id, &wl_data_device_manager_interface, +- data_device_manager_version); +-} +- +-void nsRetrievalContextWayland::InitPrimarySelectionDataDeviceManager( +- wl_registry *registry, uint32_t id) { +- mPrimarySelectionDataDeviceManager = +- (gtk_primary_selection_device_manager *)wl_registry_bind( +- registry, id, >k_primary_selection_device_manager_interface, 1); +-} +- +-void nsRetrievalContextWayland::InitSeat(wl_registry *registry, uint32_t id, +- uint32_t version, void *data) { +- mSeat = (wl_seat *)wl_registry_bind(registry, id, &wl_seat_interface, 1); +- wl_seat_add_listener(mSeat, &seat_listener, data); +-} +- +-static void gdk_registry_handle_global(void *data, struct wl_registry *registry, +- uint32_t id, const char *interface, +- uint32_t version) { +- nsRetrievalContextWayland *context = +- static_cast(data); +- +- if (strcmp(interface, "wl_data_device_manager") == 0) { +- context->InitDataDeviceManager(registry, id, version); +- } else if (strcmp(interface, "wl_seat") == 0) { +- context->InitSeat(registry, id, version, data); +- } else if (strcmp(interface, "gtk_primary_selection_device_manager") == 0) { +- context->InitPrimarySelectionDataDeviceManager(registry, id); +- } +-} +- +-static void gdk_registry_handle_global_remove(void *data, +- struct wl_registry *registry, +- uint32_t id) {} +- +-static const struct wl_registry_listener clipboard_registry_listener = { +- gdk_registry_handle_global, gdk_registry_handle_global_remove}; +- + nsRetrievalContextWayland::nsRetrievalContextWayland(void) + : mInitialized(false), +- mSeat(nullptr), +- mDataDeviceManager(nullptr), +- mPrimarySelectionDataDeviceManager(nullptr), +- mKeyboard(nullptr), ++ mDisplay(WaylandDisplayGet()), + mActiveOffers(g_hash_table_new(NULL, NULL)), + mClipboardOffer(nullptr), + mPrimaryOffer(nullptr), ++ mDragContext(nullptr), + mClipboardRequestNumber(0), + mClipboardData(nullptr), + mClipboardDataLength(0) { +- // Available as of GTK 3.8+ +- static auto sGdkWaylandDisplayGetWlDisplay = (wl_display * (*)(GdkDisplay *)) +- dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display"); +- +- mDisplay = sGdkWaylandDisplayGetWlDisplay(gdk_display_get_default()); +- wl_registry_add_listener(wl_display_get_registry(mDisplay), +- &clipboard_registry_listener, this); +- // Call wl_display_roundtrip() twice to make sure all +- // callbacks are processed. +- wl_display_roundtrip(mDisplay); +- wl_display_roundtrip(mDisplay); +- +- // mSeat/mDataDeviceManager should be set now by +- // gdk_registry_handle_global() as a response to +- // wl_registry_add_listener() call. +- if (!mDataDeviceManager || !mSeat) return; +- +- wl_data_device *dataDevice = +- wl_data_device_manager_get_data_device(mDataDeviceManager, mSeat); ++ wl_data_device *dataDevice = wl_data_device_manager_get_data_device( ++ mDisplay->GetDataDeviceManager(), mDisplay->GetSeat()); + wl_data_device_add_listener(dataDevice, &data_device_listener, this); +- // We have to call wl_display_roundtrip() twice otherwise data_offer_listener +- // may not be processed because it's called from data_device_data_offer +- // callback. +- wl_display_roundtrip(mDisplay); +- wl_display_roundtrip(mDisplay); + +- if (mPrimarySelectionDataDeviceManager) { ++ gtk_primary_selection_device_manager *manager = ++ mDisplay->GetPrimarySelectionDeviceManager(); ++ if (manager) { + gtk_primary_selection_device *primaryDataDevice = +- gtk_primary_selection_device_manager_get_device( +- mPrimarySelectionDataDeviceManager, mSeat); ++ gtk_primary_selection_device_manager_get_device(manager, ++ mDisplay->GetSeat()); + gtk_primary_selection_device_add_listener( + primaryDataDevice, &primary_selection_device_listener, this); + } +@@ -492,8 +625,21 @@ nsRetrievalContextWayland::nsRetrievalCo + mInitialized = true; } - static void -@@ -573,6 +773,7 @@ nsRetrievalContextWayland::nsRetrievalCo - , mActiveOffers(g_hash_table_new(NULL, NULL)) - , mClipboardOffer(nullptr) - , mPrimaryOffer(nullptr) -+ , mDragContext(nullptr) - , mClipboardRequestNumber(0) - , mClipboardData(nullptr) - , mClipboardDataLength(0) -@@ -616,8 +817,21 @@ nsRetrievalContextWayland::nsRetrievalCo - mInitialized = true; - } - -+static gboolean -+offer_hash_remove(gpointer wl_offer, gpointer aDataOffer, gpointer user_data) -+{ ++static gboolean offer_hash_remove(gpointer wl_offer, gpointer aDataOffer, ++ gpointer user_data) { +#ifdef DEBUG -+ nsPrintfCString msg("nsRetrievalContextWayland(): leaked nsDataOffer %p\n", -+ aDataOffer); -+ NS_WARNING(msg.get()); ++ nsPrintfCString msg("nsRetrievalContextWayland(): leaked nsDataOffer %p\n", ++ aDataOffer); ++ NS_WARNING(msg.get()); +#endif -+ delete static_cast(aDataOffer); -+ return true; ++ delete static_cast(aDataOffer); ++ return true; +} + - nsRetrievalContextWayland::~nsRetrievalContextWayland(void) - { -+ g_hash_table_foreach_remove(mActiveOffers, offer_hash_remove, nullptr); - g_hash_table_destroy(mActiveOffers); + nsRetrievalContextWayland::~nsRetrievalContextWayland(void) { ++ g_hash_table_foreach_remove(mActiveOffers, offer_hash_remove, nullptr); + g_hash_table_destroy(mActiveOffers); ++ WaylandDisplayRelease(mDisplay); } -@@ -667,12 +881,14 @@ nsRetrievalContextWayland::TransferFastT - int aClipboardRequestNumber, GtkSelectionData *aSelectionData) - { - if (mClipboardRequestNumber == aClipboardRequestNumber) { -- mClipboardDataLength = gtk_selection_data_get_length(aSelectionData); -- if (mClipboardDataLength > 0) { -+ int dataLength = gtk_selection_data_get_length(aSelectionData); -+ if (dataLength > 0) { -+ mClipboardDataLength = dataLength; - mClipboardData = reinterpret_cast( -- g_malloc(sizeof(char)*mClipboardDataLength)); -+ g_malloc(sizeof(char)*(mClipboardDataLength+1))); - memcpy(mClipboardData, gtk_selection_data_get_data(aSelectionData), - sizeof(char)*mClipboardDataLength); -+ mClipboardData[mClipboardDataLength] = '\0'; - } + GdkAtom *nsRetrievalContextWayland::GetTargets(int32_t aWhichClipboard, +@@ -533,12 +679,14 @@ static void wayland_clipboard_contents_r + void nsRetrievalContextWayland::TransferFastTrackClipboard( + int aClipboardRequestNumber, GtkSelectionData *aSelectionData) { + if (mClipboardRequestNumber == aClipboardRequestNumber) { +- mClipboardDataLength = gtk_selection_data_get_length(aSelectionData); +- if (mClipboardDataLength > 0) { ++ int dataLength = gtk_selection_data_get_length(aSelectionData); ++ if (dataLength > 0) { ++ mClipboardDataLength = dataLength; + mClipboardData = reinterpret_cast( +- g_malloc(sizeof(char) * mClipboardDataLength)); ++ g_malloc(sizeof(char) * (mClipboardDataLength + 1))); + memcpy(mClipboardData, gtk_selection_data_get_data(aSelectionData), + sizeof(char) * mClipboardDataLength); ++ mClipboardData[mClipboardDataLength] = '\0'; + } + } else { + NS_WARNING("Received obsoleted clipboard data!"); +@@ -572,8 +720,8 @@ const char *nsRetrievalContextWayland::G + mClipboardData = nullptr; + mClipboardDataLength = 0; } else { - NS_WARNING("Received obsoleted clipboard data!"); -@@ -727,7 +943,7 @@ nsRetrievalContextWayland::GetClipboardT - if (!dataOffer) - return nullptr; +- mClipboardData = +- dataOffer->GetData(mDisplay, aMimeType, &mClipboardDataLength); ++ mClipboardData = dataOffer->GetData(mDisplay->GetDisplay(), aMimeType, ++ &mClipboardDataLength); + } + } -- for (unsigned int i = 0; i < sizeof(sTextMimeTypes); i++) { -+ for (unsigned int i = 0; i < TEXT_MIME_TYPES_NUM; i++) { - if (dataOffer->HasTarget(sTextMimeTypes[i])) { - uint32_t unused; - 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-21 13:42:00.759025657 +0100 -@@ -32,6 +32,7 @@ public: - private: - virtual bool RequestDataTransfer(const char* aMimeType, int fd) = 0; +@@ -588,7 +736,7 @@ const char *nsRetrievalContextWayland::G + (selection == GDK_SELECTION_PRIMARY) ? mPrimaryOffer : mClipboardOffer; + if (!dataOffer) return nullptr; -+protected: - nsTArray mTargetMIMETypes; +- for (unsigned int i = 0; i < sizeof(sTextMimeTypes); i++) { ++ for (unsigned int i = 0; i < TEXT_MIME_TYPES_NUM; i++) { + if (dataOffer->HasTarget(sTextMimeTypes[i])) { + uint32_t unused; + return GetClipboardData(sTextMimeTypes[i], aWhichClipboard, &unused); +diff -up thunderbird-60.5.0/widget/gtk/nsClipboardWayland.h.wayland thunderbird-60.5.0/widget/gtk/nsClipboardWayland.h +--- thunderbird-60.5.0/widget/gtk/nsClipboardWayland.h.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsClipboardWayland.h 2019-02-05 14:26:16.975316648 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public +@@ -9,6 +9,7 @@ + #define __nsClipboardWayland_h_ + + #include "nsIClipboard.h" ++#include "mozwayland/mozwayland.h" + #include "wayland/gtk-primary-selection-client-protocol.h" + + #include +@@ -32,31 +33,75 @@ class DataOffer { + private: + virtual bool RequestDataTransfer(const char* aMimeType, int fd) = 0; + ++ protected: + nsTArray mTargetMIMETypes; }; -@@ -40,25 +41,66 @@ class WaylandDataOffer : public DataOffe - public: - WaylandDataOffer(wl_data_offer* aWaylandDataOffer); + class WaylandDataOffer : public DataOffer { + public: +- WaylandDataOffer(wl_data_offer* aWaylandDataOffer); ++ explicit WaylandDataOffer(wl_data_offer* aWaylandDataOffer); ++ ++ void DragOfferAccept(const char* aMimeType, uint32_t aTime); ++ void SetDragStatus(GdkDragAction aAction, uint32_t aTime); ++ ++ GdkDragAction GetSelectedDragAction(); ++ void SetSelectedDragAction(uint32_t aWaylandAction); ++ ++ void SetAvailableDragActions(uint32_t aWaylandActions); ++ GdkDragAction GetAvailableDragActions(); --private: -+ void DragOfferAccept(const char* aMimeType, uint32_t aTime); -+ void SetDragStatus(GdkDragAction aAction, uint32_t aTime); +- private: + virtual ~WaylandDataOffer(); + -+ GdkDragAction GetSelectedDragAction(); -+ void SetSelectedDragAction(uint32_t aWaylandAction); -+ -+ void SetAvailableDragActions(uint32_t aWaylandActions); -+ GdkDragAction GetAvailableDragActions(); -+ - virtual ~WaylandDataOffer(); -+private: - bool RequestDataTransfer(const char* aMimeType, int fd) override; ++ private: + bool RequestDataTransfer(const char* aMimeType, int fd) override; - wl_data_offer* mWaylandDataOffer; -+ uint32_t mSelectedDragAction; -+ uint32_t mAvailableDragAction; + wl_data_offer* mWaylandDataOffer; ++ uint32_t mSelectedDragAction; ++ uint32_t mAvailableDragAction; }; - class PrimaryDataOffer : public DataOffer - { - public: - PrimaryDataOffer(gtk_primary_selection_offer* aPrimaryDataOffer); -+ void SetAvailableDragActions(uint32_t aWaylandActions) {}; + class PrimaryDataOffer : public DataOffer { + public: +- PrimaryDataOffer(gtk_primary_selection_offer* aPrimaryDataOffer); ++ explicit PrimaryDataOffer(gtk_primary_selection_offer* aPrimaryDataOffer); ++ void SetAvailableDragActions(uint32_t aWaylandActions){}; --private: - virtual ~PrimaryDataOffer(); -+private: - bool RequestDataTransfer(const char* aMimeType, int fd) override; +- private: + virtual ~PrimaryDataOffer(); ++ ++ private: + bool RequestDataTransfer(const char* aMimeType, int fd) override; - gtk_primary_selection_offer* mPrimaryDataOffer; + gtk_primary_selection_offer* mPrimaryDataOffer; }; -+class nsWaylandDragContext : public nsISupports -+{ -+ NS_DECL_ISUPPORTS ++class nsWaylandDragContext : public nsISupports { ++ NS_DECL_ISUPPORTS + -+public: -+ nsWaylandDragContext(WaylandDataOffer* aWaylandDataOffer, -+ wl_display *aDisplay); ++ public: ++ nsWaylandDragContext(WaylandDataOffer* aWaylandDataOffer, ++ wl_display* aDisplay); + -+ void DropDataEnter(GtkWidget* aGtkWidget, uint32_t aTime, -+ nscoord aX, nscoord aY); -+ void DropMotion(uint32_t aTime, nscoord aX, nscoord aY); -+ void GetLastDropInfo(uint32_t *aTime, nscoord *aX, nscoord *aY); ++ void DropDataEnter(GtkWidget* aGtkWidget, uint32_t aTime, nscoord aX, ++ nscoord aY); ++ void DropMotion(uint32_t aTime, nscoord aX, nscoord aY); ++ void GetLastDropInfo(uint32_t* aTime, nscoord* aX, nscoord* aY); + -+ void SetDragStatus(GdkDragAction action); -+ GdkDragAction GetSelectedDragAction(); ++ void SetDragStatus(GdkDragAction action); ++ GdkDragAction GetSelectedDragAction(); + -+ GtkWidget* GetWidget() { return mGtkWidget; } -+ GList* GetTargets(); -+ char* GetData(const char* aMimeType, uint32_t* aContentLength); -+private: -+ virtual ~nsWaylandDragContext() {}; ++ GtkWidget* GetWidget() { return mGtkWidget; } ++ GList* GetTargets(); ++ char* GetData(const char* aMimeType, uint32_t* aContentLength); + -+ nsAutoPtr mDataOffer; -+ wl_display* mDisplay; -+ uint32_t mTime; -+ GtkWidget* mGtkWidget; -+ nscoord mX, mY; ++ private: ++ virtual ~nsWaylandDragContext(){}; ++ ++ nsAutoPtr mDataOffer; ++ wl_display* mDisplay; ++ uint32_t mTime; ++ GtkWidget* mGtkWidget; ++ nscoord mX, mY; +}; + - class nsRetrievalContextWayland : public nsRetrievalContext - { - public: -@@ -74,15 +116,16 @@ public: - int* aTargetNum) override; - virtual bool HasSelectionSupport(void) override; + class nsRetrievalContextWayland : public nsRetrievalContext { + public: + nsRetrievalContextWayland(); +@@ -71,38 +116,30 @@ class nsRetrievalContextWayland : public + int* aTargetNum) override; + virtual bool HasSelectionSupport(void) override; -- void RegisterDataOffer(wl_data_offer *aWaylandDataOffer); -- void RegisterDataOffer(gtk_primary_selection_offer *aPrimaryDataOffer); -+ void RegisterNewDataOffer(wl_data_offer *aWaylandDataOffer); -+ void RegisterNewDataOffer(gtk_primary_selection_offer *aPrimaryDataOffer); +- void RegisterDataOffer(wl_data_offer* aWaylandDataOffer); +- void RegisterDataOffer(gtk_primary_selection_offer* aPrimaryDataOffer); ++ void RegisterNewDataOffer(wl_data_offer* aWaylandDataOffer); ++ void RegisterNewDataOffer(gtk_primary_selection_offer* aPrimaryDataOffer); - void SetClipboardDataOffer(wl_data_offer *aWaylandDataOffer); - void SetPrimaryDataOffer(gtk_primary_selection_offer *aPrimaryDataOffer); -+ void AddDragAndDropDataOffer(wl_data_offer *aWaylandDataOffer); -+ nsWaylandDragContext* GetDragContext(); + void SetClipboardDataOffer(wl_data_offer* aWaylandDataOffer); + void SetPrimaryDataOffer(gtk_primary_selection_offer* aPrimaryDataOffer); ++ void AddDragAndDropDataOffer(wl_data_offer* aWaylandDataOffer); ++ nsWaylandDragContext* GetDragContext(); -- void ClearDataOffers(); -+ void ClearDragAndDropDataOffer(); +- void ClearDataOffers(); ++ void ClearDragAndDropDataOffer(); -- void ConfigureKeyboard(wl_seat_capability caps); - void TransferFastTrackClipboard(int aClipboardRequestNumber, - GtkSelectionData *aSelectionData); +- void ConfigureKeyboard(wl_seat_capability caps); + void TransferFastTrackClipboard(int aClipboardRequestNumber, + GtkSelectionData* aSelectionData); -@@ -103,6 +146,7 @@ private: - GHashTable* mActiveOffers; - nsAutoPtr mClipboardOffer; - nsAutoPtr mPrimaryOffer; -+ RefPtr mDragContext; +- void InitDataDeviceManager(wl_registry* registry, uint32_t id, +- uint32_t version); +- void InitPrimarySelectionDataDeviceManager(wl_registry* registry, +- uint32_t id); +- void InitSeat(wl_registry* registry, uint32_t id, uint32_t version, +- void* data); + virtual ~nsRetrievalContextWayland() override; - int mClipboardRequestNumber; - char* mClipboardData; -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-21 13:42:00.759025657 +0100 -@@ -34,7 +34,6 @@ + private: + bool mInitialized; +- wl_display* mDisplay; +- wl_seat* mSeat; +- wl_data_device_manager* mDataDeviceManager; +- gtk_primary_selection_device_manager* mPrimarySelectionDataDeviceManager; +- wl_keyboard* mKeyboard; ++ nsWaylandDisplay* mDisplay; + + // Data offers provided by Wayland data device + GHashTable* mActiveOffers; + nsAutoPtr mClipboardOffer; + nsAutoPtr mPrimaryOffer; ++ RefPtr mDragContext; + + int mClipboardRequestNumber; + char* mClipboardData; +diff -up thunderbird-60.5.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60.5.0/widget/gtk/nsDragService.cpp +--- thunderbird-60.5.0/widget/gtk/nsDragService.cpp.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsDragService.cpp 2019-02-05 14:26:16.976316645 +0100 +@@ -1,5 +1,5 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* vim: set ts=4 et sw=4 tw=80: */ ++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim: set ts=4 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ +@@ -9,6 +9,7 @@ + #include "nsIObserverService.h" + #include "nsWidgetsCID.h" + #include "nsWindow.h" ++#include "nsSystemInfo.h" + #include "nsIServiceManager.h" + #include "nsXPCOM.h" + #include "nsISupportsPrimitives.h" +@@ -34,7 +35,6 @@ #include "nsPresContext.h" #include "nsIContent.h" #include "nsIDocument.h" @@ -1036,7 +1499,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. #include "nsViewManager.h" #include "nsIFrame.h" #include "nsGtkUtils.h" -@@ -43,6 +42,9 @@ +@@ -43,10 +43,15 @@ #include "gfxPlatform.h" #include "ScreenHelperGTK.h" #include "nsArrayUtils.h" @@ -1046,313 +1509,356 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. using namespace mozilla; using namespace mozilla::gfx; -@@ -99,6 +101,10 @@ invisibleSourceDragDataGet(GtkWidget - nsDragService::nsDragService() - : mScheduledTask(eDragTaskNone) - , mTaskSource(0) -+#ifdef MOZ_WAYLAND -+ , mPendingWaylandDragContext(nullptr) -+ , mTargetWaylandDragContext(nullptr) -+#endif - { - // We have to destroy the hidden widget before the event loop stops - // running. -@@ -516,6 +522,9 @@ nsDragService::EndDragSession(bool aDone - // We're done with the drag context. - mTargetDragContextForRemote = nullptr; -+#ifdef MOZ_WAYLAND -+ mTargetWaylandDragContextForRemote = nullptr; -+#endif - - return nsBaseDragService::EndDragSession(aDoneDrag, aKeyModifiers); - } -@@ -636,6 +645,14 @@ nsDragService::GetNumDropItems(uint32_t - return NS_OK; - } - -+#ifdef MOZ_WAYLAND -+ // TODO: Wayland implementation of text/uri-list. -+ if (!mTargetDragContext) { -+ *aNumItems = 1; -+ return NS_OK; -+ } -+#endif ++#define NS_SYSTEMINFO_CONTRACTID "@mozilla.org/system-info;1" + - bool isList = IsTargetContextList(); - if (isList) - mSourceDataItems->GetLength(aNumItems); -@@ -1027,9 +1044,18 @@ nsDragService::IsDataFlavorSupported(con - } + // This sets how opaque the drag image is + #define DRAG_IMAGE_ALPHA_LEVEL 0.5 - // check the target context vs. this flavor, one at a time -- GList *tmp; -- for (tmp = gdk_drag_context_list_targets(mTargetDragContext); -- tmp; tmp = tmp->next) { -+ GList *tmp = nullptr; -+ if (mTargetDragContext) { -+ tmp = gdk_drag_context_list_targets(mTargetDragContext); -+ } +@@ -68,6 +73,7 @@ static const char gMimeListType[] = "app + static const char gMozUrlType[] = "_NETSCAPE_URL"; + static const char gTextUriListType[] = "text/uri-list"; + static const char gTextPlainUTF8Type[] = "text/plain;charset=utf-8"; ++static const char gXdndDirectSaveType[] = "XdndDirectSave0"; + + static void invisibleSourceDragBegin(GtkWidget *aWidget, + GdkDragContext *aContext, gpointer aData); +@@ -85,7 +91,15 @@ static void invisibleSourceDragDataGet(G + guint aInfo, guint32 aTime, + gpointer aData); + +-nsDragService::nsDragService() : mScheduledTask(eDragTaskNone), mTaskSource(0) { ++nsDragService::nsDragService() ++ : mScheduledTask(eDragTaskNone), ++ mTaskSource(0) +#ifdef MOZ_WAYLAND -+ else if (mTargetWaylandDragContext) { -+ tmp = mTargetWaylandDragContext->GetTargets(); -+ } -+ GList *tmp_head = tmp; ++ , ++ mPendingWaylandDragContext(nullptr), ++ mTargetWaylandDragContext(nullptr) +#endif -+ -+ for (; tmp; tmp = tmp->next) { - /* Bug 331198 */ - GdkAtom atom = GDK_POINTER_TO_ATOM(tmp->data); - gchar *name = nullptr; -@@ -1074,6 +1100,15 @@ nsDragService::IsDataFlavorSupported(con - } - g_free(name); - } -+ -+#ifdef MOZ_WAYLAND -+ // mTargetWaylandDragContext->GetTargets allocates the list -+ // so we need to free it here. -+ if (!mTargetDragContext && tmp_head) { -+ g_list_free(tmp_head); -+ } -+#endif -+ - return NS_OK; - } - -@@ -1105,6 +1140,36 @@ nsDragService::ReplyToDragMotion(GdkDrag - gdk_drag_status(aDragContext, action, mTargetTime); - } - -+#ifdef MOZ_WAYLAND -+void -+nsDragService::ReplyToDragMotion(nsWaylandDragContext* aDragContext) +{ -+ MOZ_LOG(sDragLm, LogLevel::Debug, -+ ("nsDragService::ReplyToDragMotion %d", mCanDrop)); + // We have to destroy the hidden widget before the event loop stops + // running. + nsCOMPtr obsServ = +@@ -159,7 +173,7 @@ nsDragService::Observe(nsISupports *aSub + } + TargetResetData(); + } else { +- NS_NOTREACHED("unexpected topic"); ++ MOZ_ASSERT_UNREACHABLE("unexpected topic"); + return NS_ERROR_UNEXPECTED; + } + +@@ -457,6 +471,9 @@ nsDragService::EndDragSession(bool aDone + + // We're done with the drag context. + mTargetDragContextForRemote = nullptr; ++#ifdef MOZ_WAYLAND ++ mTargetWaylandDragContextForRemote = nullptr; ++#endif + + return nsBaseDragService::EndDragSession(aDoneDrag, aKeyModifiers); + } +@@ -550,6 +567,14 @@ nsDragService::GetNumDropItems(uint32_t + return NS_OK; + } + ++#ifdef MOZ_WAYLAND ++ // TODO: Wayland implementation of text/uri-list. ++ if (!mTargetDragContext) { ++ *aNumItems = 1; ++ return NS_OK; ++ } ++#endif + -+ GdkDragAction action = (GdkDragAction)0; -+ if (mCanDrop) { -+ // notify the dragger if we can drop -+ switch (mDragAction) { -+ case DRAGDROP_ACTION_COPY: -+ action = GDK_ACTION_COPY; -+ break; -+ case DRAGDROP_ACTION_LINK: -+ action = GDK_ACTION_LINK; -+ break; -+ case DRAGDROP_ACTION_NONE: -+ action = (GdkDragAction)0; -+ break; -+ default: -+ action = GDK_ACTION_MOVE; -+ break; -+ } + bool isList = IsTargetContextList(); + if (isList) + mSourceDataItems->GetLength(aNumItems); +@@ -907,9 +932,18 @@ nsDragService::IsDataFlavorSupported(con + } + + // check the target context vs. this flavor, one at a time +- GList *tmp; +- for (tmp = gdk_drag_context_list_targets(mTargetDragContext); tmp; +- tmp = tmp->next) { ++ GList *tmp = nullptr; ++ if (mTargetDragContext) { ++ tmp = gdk_drag_context_list_targets(mTargetDragContext); ++ } ++#ifdef MOZ_WAYLAND ++ else if (mTargetWaylandDragContext) { ++ tmp = mTargetWaylandDragContext->GetTargets(); ++ } ++ GList *tmp_head = tmp; ++#endif ++ ++ for (; tmp; tmp = tmp->next) { + /* Bug 331198 */ + GdkAtom atom = GDK_POINTER_TO_ATOM(tmp->data); + gchar *name = nullptr; +@@ -946,6 +980,15 @@ nsDragService::IsDataFlavorSupported(con + } + g_free(name); + } ++ ++#ifdef MOZ_WAYLAND ++ // mTargetWaylandDragContext->GetTargets allocates the list ++ // so we need to free it here. ++ if (!mTargetDragContext && tmp_head) { ++ g_list_free(tmp_head); ++ } ++#endif ++ + return NS_OK; + } + +@@ -975,6 +1018,34 @@ void nsDragService::ReplyToDragMotion(Gd + gdk_drag_status(aDragContext, action, mTargetTime); + } + ++#ifdef MOZ_WAYLAND ++void nsDragService::ReplyToDragMotion(nsWaylandDragContext *aDragContext) { ++ MOZ_LOG(sDragLm, LogLevel::Debug, ++ ("nsDragService::ReplyToDragMotion %d", mCanDrop)); ++ ++ GdkDragAction action = (GdkDragAction)0; ++ if (mCanDrop) { ++ // notify the dragger if we can drop ++ switch (mDragAction) { ++ case DRAGDROP_ACTION_COPY: ++ action = GDK_ACTION_COPY; ++ break; ++ case DRAGDROP_ACTION_LINK: ++ action = GDK_ACTION_LINK; ++ break; ++ case DRAGDROP_ACTION_NONE: ++ action = (GdkDragAction)0; ++ break; ++ default: ++ action = GDK_ACTION_MOVE; ++ break; + } ++ } + -+ aDragContext->SetDragStatus(action); ++ aDragContext->SetDragStatus(action); +} +#endif + - void - nsDragService::TargetDataReceived(GtkWidget *aWidget, - GdkDragContext *aContext, -@@ -1136,6 +1201,12 @@ nsDragService::IsTargetContextList(void) - { - bool retval = false; + void nsDragService::TargetDataReceived(GtkWidget *aWidget, + GdkDragContext *aContext, gint aX, + gint aY, +@@ -999,6 +1070,11 @@ void nsDragService::TargetDataReceived(G + bool nsDragService::IsTargetContextList(void) { + bool retval = false; +#ifdef MOZ_WAYLAND -+ // TODO: We need a wayland implementation here. -+ if (!mTargetDragContext) -+ return retval; ++ // TODO: We need a wayland implementation here. ++ if (!mTargetDragContext) return retval; +#endif + - // 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 +1245,28 @@ nsDragService::GetTargetDragData(GdkAtom - mTargetDragContext.get())); - // reset our target data areas - TargetResetData(); -- gtk_drag_get_data(mTargetWidget, mTargetDragContext, aFlavor, mTargetTime); + // 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 +@@ -1032,17 +1108,27 @@ void nsDragService::GetTargetDragData(Gd + mTargetDragContext.get())); + // reset our target data areas + TargetResetData(); +- gtk_drag_get_data(mTargetWidget, mTargetDragContext, aFlavor, mTargetTime); -- MOZ_LOG(sDragLm, LogLevel::Debug, ("about to start inner iteration.")); -- PRTime entryTime = PR_Now(); -- while (!mTargetDragDataReceived && mDoingDrag) { -- // check the number of iterations -- MOZ_LOG(sDragLm, LogLevel::Debug, ("doing iteration...\n")); -- PR_Sleep(20*PR_TicksPerSecond()/1000); /* sleep for 20 ms/iteration */ -- if (PR_Now()-entryTime > NS_DND_TIMEOUT) break; -- gtk_main_iteration(); -+ if (mTargetDragContext) { -+ gtk_drag_get_data(mTargetWidget, mTargetDragContext, aFlavor, mTargetTime); +- MOZ_LOG(sDragLm, LogLevel::Debug, ("about to start inner iteration.")); +- PRTime entryTime = PR_Now(); +- while (!mTargetDragDataReceived && mDoingDrag) { +- // check the number of iterations +- MOZ_LOG(sDragLm, LogLevel::Debug, ("doing iteration...\n")); +- PR_Sleep(20 * PR_TicksPerSecond() / 1000); /* sleep for 20 ms/iteration */ +- if (PR_Now() - entryTime > NS_DND_TIMEOUT) break; +- gtk_main_iteration(); ++ if (mTargetDragContext) { ++ gtk_drag_get_data(mTargetWidget, mTargetDragContext, aFlavor, mTargetTime); + -+ MOZ_LOG(sDragLm, LogLevel::Debug, ("about to start inner iteration.")); -+ PRTime entryTime = PR_Now(); -+ while (!mTargetDragDataReceived && mDoingDrag) { -+ // check the number of iterations -+ MOZ_LOG(sDragLm, LogLevel::Debug, ("doing iteration...\n")); -+ PR_Sleep(20*PR_TicksPerSecond()/1000); /* sleep for 20 ms/iteration */ -+ if (PR_Now()-entryTime > NS_DND_TIMEOUT) break; -+ gtk_main_iteration(); -+ } ++ MOZ_LOG(sDragLm, LogLevel::Debug, ("about to start inner iteration.")); ++ PRTime entryTime = PR_Now(); ++ while (!mTargetDragDataReceived && mDoingDrag) { ++ // check the number of iterations ++ MOZ_LOG(sDragLm, LogLevel::Debug, ("doing iteration...\n")); ++ PR_Sleep(20 * PR_TicksPerSecond() / 1000); /* sleep for 20 ms/iteration */ ++ if (PR_Now() - entryTime > NS_DND_TIMEOUT) break; ++ gtk_main_iteration(); + } + } +#ifdef MOZ_WAYLAND -+ else { -+ mTargetDragData = -+ mTargetWaylandDragContext->GetData(gdk_atom_name(aFlavor), -+ &mTargetDragDataLen); -+ mTargetDragDataReceived = true; - } ++ else { ++ mTargetDragData = mTargetWaylandDragContext->GetData(gdk_atom_name(aFlavor), ++ &mTargetDragDataLen); ++ mTargetDragDataReceived = true; ++ } +#endif - MOZ_LOG(sDragLm, LogLevel::Debug, ("finished inner iteration\n")); + MOZ_LOG(sDragLm, LogLevel::Debug, ("finished inner iteration\n")); } -@@ -1435,7 +1517,7 @@ nsDragService::SourceEndDragSession(GdkD - } +@@ -1218,6 +1304,10 @@ void nsDragService::SourceEndDragSession + // this just releases the list of data items that we provide + mSourceDataItems = nullptr; - // Schedule the appropriate drag end dom events. -- Schedule(eDragTaskSourceEnd, nullptr, nullptr, LayoutDeviceIntPoint(), 0); -+ Schedule(eDragTaskSourceEnd, nullptr, nullptr, nullptr, LayoutDeviceIntPoint(), 0); ++ // Remove this property, if it exists, to satisfy the Direct Save Protocol. ++ GdkAtom property = gdk_atom_intern(gXdndDirectSaveType, FALSE); ++ gdk_property_delete(gdk_drag_context_get_source_window(aContext), property); ++ + if (!mDoingDrag || mScheduledTask == eDragTaskSourceEnd) + // EndDragSession() was already called on drop + // or SourceEndDragSession on drag-failed +@@ -1276,7 +1366,7 @@ void nsDragService::SourceEndDragSession + } + + // Schedule the appropriate drag end dom events. +- Schedule(eDragTaskSourceEnd, nullptr, nullptr, LayoutDeviceIntPoint(), 0); ++ Schedule(eDragTaskSourceEnd, nullptr, nullptr, nullptr, LayoutDeviceIntPoint(), 0); } - static void -@@ -1785,9 +1867,10 @@ invisibleSourceDragEnd(GtkWidget - gboolean - nsDragService::ScheduleMotionEvent(nsWindow *aWindow, - GdkDragContext *aDragContext, -+ nsWaylandDragContext *aWaylandDragContext, - LayoutDeviceIntPoint aWindowPoint, guint aTime) - { -- if (mScheduledTask == eDragTaskMotion) { -+ if (aDragContext && mScheduledTask == eDragTaskMotion) { - // 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 +1881,7 @@ nsDragService::ScheduleMotionEvent(nsWin + static void CreateUriList(nsIArray *items, gchar **text, gint *length) { +@@ -1585,11 +1675,11 @@ static void invisibleSourceDragEnd(GtkWi + // Gecko drag events are in flight. This helps event handlers that may not + // expect nested events, while accessing an event's dataTransfer for example. - // Returning TRUE means we'll reply with a status message, unless we first - // get a leave. -- return Schedule(eDragTaskMotion, aWindow, aDragContext, -+ return Schedule(eDragTaskMotion, aWindow, aDragContext, aWaylandDragContext, - aWindowPoint, aTime); +-gboolean nsDragService::ScheduleMotionEvent(nsWindow *aWindow, +- GdkDragContext *aDragContext, +- LayoutDeviceIntPoint aWindowPoint, +- guint aTime) { +- if (mScheduledTask == eDragTaskMotion) { ++gboolean nsDragService::ScheduleMotionEvent( ++ nsWindow *aWindow, GdkDragContext *aDragContext, ++ nsWaylandDragContext *aWaylandDragContext, ++ LayoutDeviceIntPoint aWindowPoint, guint aTime) { ++ if (aDragContext && mScheduledTask == eDragTaskMotion) { + // 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 +@@ -1600,23 +1690,26 @@ gboolean nsDragService::ScheduleMotionEv + + // Returning TRUE means we'll reply with a status message, unless we first + // get a leave. +- return Schedule(eDragTaskMotion, aWindow, aDragContext, aWindowPoint, aTime); ++ return Schedule(eDragTaskMotion, aWindow, aDragContext, aWaylandDragContext, ++ aWindowPoint, aTime); } -@@ -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. -- if (!Schedule(eDragTaskLeave, nullptr, nullptr, LayoutDeviceIntPoint(), 0)) { -+ if (!Schedule(eDragTaskLeave, nullptr, nullptr, nullptr, -+ LayoutDeviceIntPoint(), 0)) { - NS_WARNING("Drag leave after drop"); - } + void 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. +- if (!Schedule(eDragTaskLeave, nullptr, nullptr, LayoutDeviceIntPoint(), 0)) { ++ if (!Schedule(eDragTaskLeave, nullptr, nullptr, nullptr, ++ LayoutDeviceIntPoint(), 0)) { + NS_WARNING("Drag leave after drop"); + } } -@@ -1816,10 +1900,11 @@ nsDragService::ScheduleLeaveEvent() - gboolean - nsDragService::ScheduleDropEvent(nsWindow *aWindow, + +-gboolean nsDragService::ScheduleDropEvent(nsWindow *aWindow, +- GdkDragContext *aDragContext, +- LayoutDeviceIntPoint aWindowPoint, +- guint aTime) { +- if (!Schedule(eDragTaskDrop, aWindow, aDragContext, aWindowPoint, aTime)) { ++gboolean nsDragService::ScheduleDropEvent( ++ nsWindow *aWindow, GdkDragContext *aDragContext, ++ nsWaylandDragContext *aWaylandDragContext, ++ LayoutDeviceIntPoint aWindowPoint, guint aTime) { ++ if (!Schedule(eDragTaskDrop, aWindow, aDragContext, aWaylandDragContext, ++ aWindowPoint, aTime)) { + NS_WARNING("Additional drag drop ignored"); + return FALSE; + } +@@ -1629,6 +1722,7 @@ gboolean nsDragService::ScheduleDropEven + + gboolean nsDragService::Schedule(DragTask aTask, nsWindow *aWindow, GdkDragContext *aDragContext, + nsWaylandDragContext *aWaylandDragContext, - LayoutDeviceIntPoint aWindowPoint, guint aTime) - { - if (!Schedule(eDragTaskDrop, aWindow, -- aDragContext, aWindowPoint, aTime)) { -+ aDragContext, aWaylandDragContext, aWindowPoint, aTime)) { - NS_WARNING("Additional drag drop ignored"); - return FALSE; - } -@@ -1833,6 +1918,7 @@ nsDragService::ScheduleDropEvent(nsWindo - gboolean - nsDragService::Schedule(DragTask aTask, nsWindow *aWindow, - GdkDragContext *aDragContext, -+ nsWaylandDragContext *aWaylandDragContext, - LayoutDeviceIntPoint aWindowPoint, guint aTime) - { - // If there is an existing leave or motion task scheduled, then that -@@ -1851,6 +1937,9 @@ nsDragService::Schedule(DragTask aTask, - mScheduledTask = aTask; - mPendingWindow = aWindow; - mPendingDragContext = aDragContext; + LayoutDeviceIntPoint aWindowPoint, + guint aTime) { + // If there is an existing leave or motion task scheduled, then that +@@ -1647,6 +1741,9 @@ gboolean nsDragService::Schedule(DragTas + mScheduledTask = aTask; + mPendingWindow = aWindow; + mPendingDragContext = aDragContext; +#ifdef MOZ_WAYLAND -+ mPendingWaylandDragContext = aWaylandDragContext; ++ mPendingWaylandDragContext = aWaylandDragContext; +#endif - mPendingWindowPoint = aWindowPoint; - mPendingTime = aTime; + mPendingWindowPoint = aWindowPoint; + mPendingTime = aTime; -@@ -1927,6 +2016,9 @@ nsDragService::RunScheduledTask() - // succeeed. - mTargetWidget = mTargetWindow->GetMozContainerWidget(); - mTargetDragContext.steal(mPendingDragContext); +@@ -1717,6 +1814,9 @@ gboolean nsDragService::RunScheduledTask + // succeeed. + mTargetWidget = mTargetWindow->GetMozContainerWidget(); + mTargetDragContext.steal(mPendingDragContext); +#ifdef MOZ_WAYLAND -+ mTargetWaylandDragContext = mPendingWaylandDragContext.forget(); ++ mTargetWaylandDragContext = mPendingWaylandDragContext.forget(); +#endif - mTargetTime = mPendingTime; + mTargetTime = mPendingTime; - // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model -@@ -1958,10 +2050,20 @@ nsDragService::RunScheduledTask() - if (task == eDragTaskMotion) { - if (TakeDragEventDispatchedToChildProcess()) { - mTargetDragContextForRemote = mTargetDragContext; + // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model +@@ -1748,10 +1848,20 @@ gboolean nsDragService::RunScheduledTask + if (task == eDragTaskMotion) { + if (TakeDragEventDispatchedToChildProcess()) { + mTargetDragContextForRemote = mTargetDragContext; +#ifdef MOZ_WAYLAND -+ mTargetWaylandDragContextForRemote = mTargetWaylandDragContext; ++ mTargetWaylandDragContextForRemote = mTargetWaylandDragContext; +#endif - } else { - // Reply to tell the source whether we can drop and what - // action would be taken. -- ReplyToDragMotion(mTargetDragContext); -+ if (mTargetDragContext) { -+ ReplyToDragMotion(mTargetDragContext); -+ } -+#ifdef MOZ_WAYLAND -+ else if (mTargetWaylandDragContext) { -+ ReplyToDragMotion(mTargetWaylandDragContext); -+ } -+#endif - } - } - } -@@ -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. -- gtk_drag_finish(mTargetDragContext, success, -- /* del = */ FALSE, mTargetTime); + } else { + // Reply to tell the source whether we can drop and what + // action would be taken. +- ReplyToDragMotion(mTargetDragContext); + if (mTargetDragContext) { -+ gtk_drag_finish(mTargetDragContext, success, -+ /* del = */ FALSE, mTargetTime); ++ ReplyToDragMotion(mTargetDragContext); + } - - // This drag is over, so clear out our reference to the previous - // window. -@@ -1986,6 +2090,9 @@ nsDragService::RunScheduledTask() - // We're done with the drag context. - mTargetWidget = nullptr; - mTargetDragContext = nullptr; +#ifdef MOZ_WAYLAND -+ mTargetWaylandDragContext = nullptr; ++ else if (mTargetWaylandDragContext) { ++ ReplyToDragMotion(mTargetWaylandDragContext); ++ } +#endif - - // 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 +2122,16 @@ nsDragService::UpdateDragAction() - - // default is to do nothing - int action = nsIDragService::DRAGDROP_ACTION_NONE; -- GdkDragAction gdkAction = gdk_drag_context_get_actions(mTargetDragContext); -+ GdkDragAction gdkAction = GDK_ACTION_DEFAULT; + } + } + } +@@ -1762,8 +1872,10 @@ gboolean 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. +- gtk_drag_finish(mTargetDragContext, success, +- /* del = */ FALSE, mTargetTime); + if (mTargetDragContext) { -+ gdkAction = gdk_drag_context_get_actions(mTargetDragContext); ++ gtk_drag_finish(mTargetDragContext, success, ++ /* del = */ FALSE, mTargetTime); + } + + // This drag is over, so clear out our reference to the previous + // window. +@@ -1776,6 +1888,9 @@ gboolean nsDragService::RunScheduledTask + // We're done with the drag context. + mTargetWidget = nullptr; + mTargetDragContext = nullptr; +#ifdef MOZ_WAYLAND -+ else if (mTargetWaylandDragContext) { -+ // We got the selected D&D action from compositor on Wayland. -+ gdkAction = mTargetWaylandDragContext->GetSelectedDragAction(); -+ } ++ mTargetWaylandDragContext = nullptr; +#endif - // set the default just in case nothing matches below - if (gdkAction & GDK_ACTION_DEFAULT) -@@ -2044,6 +2160,12 @@ nsDragService::UpdateDragEffect() + // If we got another drag signal while running the sheduled task, that + // must have happened while running a nested event loop. Leave the task +@@ -1802,7 +1917,16 @@ void nsDragService::UpdateDragAction() { + + // default is to do nothing + int action = nsIDragService::DRAGDROP_ACTION_NONE; +- GdkDragAction gdkAction = gdk_drag_context_get_actions(mTargetDragContext); ++ GdkDragAction gdkAction = GDK_ACTION_DEFAULT; ++ if (mTargetDragContext) { ++ gdkAction = gdk_drag_context_get_actions(mTargetDragContext); ++ } ++#ifdef MOZ_WAYLAND ++ else if (mTargetWaylandDragContext) { ++ // We got the selected D&D action from compositor on Wayland. ++ gdkAction = mTargetWaylandDragContext->GetSelectedDragAction(); ++ } ++#endif + + // set the default just in case nothing matches below + if (gdkAction & GDK_ACTION_DEFAULT) +@@ -1830,6 +1954,12 @@ nsDragService::UpdateDragEffect() { ReplyToDragMotion(mTargetDragContextForRemote); mTargetDragContextForRemote = nullptr; } @@ -1365,9 +1871,17 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. return NS_OK; } -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-21 13:42:00.759025657 +0100 +diff -up thunderbird-60.5.0/widget/gtk/nsDragService.h.wayland thunderbird-60.5.0/widget/gtk/nsDragService.h +--- thunderbird-60.5.0/widget/gtk/nsDragService.h.wayland 2019-01-22 20:44:03.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsDragService.h 2019-02-05 14:26:16.976316645 +0100 +@@ -1,5 +1,5 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* vim: set ts=4 et sw=4 tw=80: */ ++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim: set ts=4 et sw=2 tw=80: */ + /* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ @@ -14,6 +14,7 @@ #include @@ -1376,70 +1890,81 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. namespace mozilla { namespace gfx { -@@ -98,11 +99,13 @@ public: +@@ -91,10 +92,12 @@ class nsDragService final : public nsBas + guint aInfo, guint32 aTime); - gboolean ScheduleMotionEvent(nsWindow *aWindow, - GdkDragContext *aDragContext, -+ nsWaylandDragContext* aPendingWaylandDragContext, - mozilla::LayoutDeviceIntPoint aWindowPoint, - guint aTime); - void ScheduleLeaveEvent(); - gboolean ScheduleDropEvent(nsWindow *aWindow, - GdkDragContext *aDragContext, -+ nsWaylandDragContext* aPendingWaylandDragContext, + gboolean ScheduleMotionEvent(nsWindow *aWindow, GdkDragContext *aDragContext, ++ nsWaylandDragContext *aPendingWaylandDragContext, mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime); + void ScheduleLeaveEvent(); + gboolean ScheduleDropEvent(nsWindow *aWindow, GdkDragContext *aDragContext, ++ nsWaylandDragContext *aPendingWaylandDragContext, + mozilla::LayoutDeviceIntPoint aWindowPoint, + guint aTime); -@@ -158,6 +161,9 @@ private: - RefPtr mPendingWindow; - mozilla::LayoutDeviceIntPoint mPendingWindowPoint; - nsCountedRef mPendingDragContext; +@@ -111,6 +114,8 @@ class nsDragService final : public nsBas + void SourceDataGet(GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, guint32 aTime); + ++ void SourceBeginDrag(GdkDragContext *aContext); ++ + // set the drag icon during drag-begin + void SetDragIcon(GdkDragContext *aContext); + +@@ -144,6 +149,9 @@ class nsDragService final : public nsBas + RefPtr mPendingWindow; + mozilla::LayoutDeviceIntPoint mPendingWindowPoint; + nsCountedRef mPendingDragContext; +#ifdef MOZ_WAYLAND -+ RefPtr mPendingWaylandDragContext; ++ RefPtr mPendingWaylandDragContext; +#endif - guint mPendingTime; + guint mPendingTime; - // mTargetWindow and mTargetWindowPoint record the position of the last -@@ -169,9 +175,15 @@ private: - // motion or drop events. mTime records the corresponding timestamp. - nsCountedRef mTargetWidget; - nsCountedRef mTargetDragContext; + // mTargetWindow and mTargetWindowPoint record the position of the last +@@ -155,9 +163,15 @@ class nsDragService final : public nsBas + // motion or drop events. mTime records the corresponding timestamp. + nsCountedRef mTargetWidget; + nsCountedRef mTargetDragContext; +#ifdef MOZ_WAYLAND -+ RefPtr mTargetWaylandDragContext; ++ RefPtr mTargetWaylandDragContext; +#endif - // mTargetDragContextForRemote is set while waiting for a reply from - // a child process. - nsCountedRef mTargetDragContextForRemote; + // mTargetDragContextForRemote is set while waiting for a reply from + // a child process. + nsCountedRef mTargetDragContextForRemote; +#ifdef MOZ_WAYLAND -+ RefPtr mTargetWaylandDragContextForRemote; ++ RefPtr mTargetWaylandDragContextForRemote; +#endif - guint mTargetTime; + guint mTargetTime; - // is it OK to drop on us? -@@ -212,6 +224,7 @@ private: + // is it OK to drop on us? +@@ -196,6 +210,7 @@ class nsDragService final : public nsBas - gboolean Schedule(DragTask aTask, nsWindow *aWindow, - GdkDragContext *aDragContext, -+ nsWaylandDragContext* aPendingWaylandDragContext, - mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime); + gboolean Schedule(DragTask aTask, nsWindow *aWindow, + GdkDragContext *aDragContext, ++ nsWaylandDragContext *aPendingWaylandDragContext, + mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime); - // Callback for g_idle_add_full() to run mScheduledTask. -@@ -220,9 +233,11 @@ private: - void UpdateDragAction(); - void DispatchMotionEvents(); - void ReplyToDragMotion(GdkDragContext* aDragContext); + // Callback for g_idle_add_full() to run mScheduledTask. +@@ -204,6 +219,9 @@ class nsDragService final : public nsBas + void UpdateDragAction(); + void DispatchMotionEvents(); + void ReplyToDragMotion(GdkDragContext *aDragContext); +#ifdef MOZ_WAYLAND -+ void ReplyToDragMotion(nsWaylandDragContext* aDragContext); ++ void ReplyToDragMotion(nsWaylandDragContext *aDragContext); +#endif - gboolean DispatchDropEvent(); - static uint32_t GetCurrentModifiers(); + gboolean DispatchDropEvent(); + static uint32_t GetCurrentModifiers(); }; - - #endif // nsDragService_h__ -- -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-21 13:42:00.760025653 +0100 +diff -up thunderbird-60.5.0/widget/gtk/nsGtkKeyUtils.cpp.wayland thunderbird-60.5.0/widget/gtk/nsGtkKeyUtils.cpp +--- thunderbird-60.5.0/widget/gtk/nsGtkKeyUtils.cpp.wayland 2019-01-22 20:44:03.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsGtkKeyUtils.cpp 2019-02-05 14:26:16.976316645 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public @@ -28,6 +28,10 @@ #include "mozilla/MouseEvents.h" #include "mozilla/TextEvents.h" @@ -1451,259 +1976,219 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland thunderbird-60. namespace mozilla { namespace widget { -@@ -195,7 +199,11 @@ KeymapWrapper::Init() - memset(mModifierMasks, 0, sizeof(mModifierMasks)); +@@ -200,7 +204,11 @@ void KeymapWrapper::Init() { + mModifierKeys.Clear(); + memset(mModifierMasks, 0, sizeof(mModifierMasks)); - if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) -- InitBySystemSettings(); -+ InitBySystemSettingsX11(); +- if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) InitBySystemSettings(); ++ if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) InitBySystemSettingsX11(); +#ifdef MOZ_WAYLAND -+ else -+ InitBySystemSettingsWayland(); ++ else ++ InitBySystemSettingsWayland(); +#endif - gdk_window_add_filter(nullptr, FilterEvents, this); + gdk_window_add_filter(nullptr, FilterEvents, this); -@@ -275,10 +283,10 @@ KeymapWrapper::InitXKBExtension() +@@ -276,9 +284,9 @@ void KeymapWrapper::InitXKBExtension() { + ("%p InitXKBExtension, Succeeded", this)); } - void --KeymapWrapper::InitBySystemSettings() -+KeymapWrapper::InitBySystemSettingsX11() - { - MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, -- ("%p InitBySystemSettings, mGdkKeymap=%p", -+ ("%p InitBySystemSettingsX11, mGdkKeymap=%p", - this, mGdkKeymap)); +-void KeymapWrapper::InitBySystemSettings() { ++void KeymapWrapper::InitBySystemSettingsX11() { + MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, +- ("%p InitBySystemSettings, mGdkKeymap=%p", this, mGdkKeymap)); ++ ("%p InitBySystemSettingsX11, mGdkKeymap=%p", this, mGdkKeymap)); - Display* display = -@@ -439,6 +447,208 @@ KeymapWrapper::InitBySystemSettings() - XFree(xkeymap); + Display* display = gdk_x11_display_get_xdisplay(gdk_display_get_default()); + +@@ -439,6 +447,163 @@ void KeymapWrapper::InitBySystemSettings + XFree(xkeymap); } +#ifdef MOZ_WAYLAND -+void -+KeymapWrapper::SetModifierMask(xkb_keymap *aKeymap, ModifierIndex aModifierIndex, -+ const char* aModifierName) -+{ -+ static auto sXkbKeymapModGetIndex = -+ (xkb_mod_index_t (*)(struct xkb_keymap *, const char *)) -+ dlsym(RTLD_DEFAULT, "xkb_keymap_mod_get_index"); ++void KeymapWrapper::SetModifierMask(xkb_keymap* aKeymap, ++ ModifierIndex aModifierIndex, ++ const char* aModifierName) { ++ static auto sXkbKeymapModGetIndex = ++ (xkb_mod_index_t(*)(struct xkb_keymap*, const char*))dlsym( ++ RTLD_DEFAULT, "xkb_keymap_mod_get_index"); + -+ xkb_mod_index_t index = sXkbKeymapModGetIndex(aKeymap, aModifierName); -+ if (index != XKB_MOD_INVALID) { -+ mModifierMasks[aModifierIndex] = (1 << index); -+ } ++ xkb_mod_index_t index = sXkbKeymapModGetIndex(aKeymap, aModifierName); ++ if (index != XKB_MOD_INVALID) { ++ mModifierMasks[aModifierIndex] = (1 << index); ++ } +} + -+void -+KeymapWrapper::SetModifierMasks(xkb_keymap *aKeymap) -+{ -+ KeymapWrapper* keymapWrapper = GetInstance(); ++void KeymapWrapper::SetModifierMasks(xkb_keymap* aKeymap) { ++ KeymapWrapper* keymapWrapper = GetInstance(); + -+ // This mapping is derived from get_xkb_modifiers() at gdkkeys-wayland.c -+ keymapWrapper->SetModifierMask(aKeymap, INDEX_NUM_LOCK, XKB_MOD_NAME_NUM); -+ keymapWrapper->SetModifierMask(aKeymap, INDEX_ALT, XKB_MOD_NAME_ALT); -+ keymapWrapper->SetModifierMask(aKeymap, INDEX_META, "Meta"); -+ keymapWrapper->SetModifierMask(aKeymap, INDEX_SUPER, "Super"); -+ keymapWrapper->SetModifierMask(aKeymap, INDEX_HYPER, "Hyper"); ++ // This mapping is derived from get_xkb_modifiers() at gdkkeys-wayland.c ++ keymapWrapper->SetModifierMask(aKeymap, INDEX_NUM_LOCK, XKB_MOD_NAME_NUM); ++ keymapWrapper->SetModifierMask(aKeymap, INDEX_ALT, XKB_MOD_NAME_ALT); ++ keymapWrapper->SetModifierMask(aKeymap, INDEX_META, "Meta"); ++ keymapWrapper->SetModifierMask(aKeymap, INDEX_SUPER, "Super"); ++ keymapWrapper->SetModifierMask(aKeymap, INDEX_HYPER, "Hyper"); + -+ keymapWrapper->SetModifierMask(aKeymap, INDEX_SCROLL_LOCK, "ScrollLock"); -+ keymapWrapper->SetModifierMask(aKeymap, INDEX_LEVEL3, "Level3"); -+ keymapWrapper->SetModifierMask(aKeymap, INDEX_LEVEL5, "Level5"); ++ keymapWrapper->SetModifierMask(aKeymap, INDEX_SCROLL_LOCK, "ScrollLock"); ++ keymapWrapper->SetModifierMask(aKeymap, INDEX_LEVEL3, "Level3"); ++ keymapWrapper->SetModifierMask(aKeymap, INDEX_LEVEL5, "Level5"); + -+ MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, -+ ("%p KeymapWrapper::SetModifierMasks, CapsLock=0x%X, NumLock=0x%X, " -+ "ScrollLock=0x%X, Level3=0x%X, Level5=0x%X, " -+ "Shift=0x%X, Ctrl=0x%X, Alt=0x%X, Meta=0x%X, Super=0x%X, Hyper=0x%X", -+ keymapWrapper, -+ keymapWrapper->GetModifierMask(CAPS_LOCK), -+ keymapWrapper->GetModifierMask(NUM_LOCK), -+ keymapWrapper->GetModifierMask(SCROLL_LOCK), -+ keymapWrapper->GetModifierMask(LEVEL3), -+ keymapWrapper->GetModifierMask(LEVEL5), -+ keymapWrapper->GetModifierMask(SHIFT), -+ keymapWrapper->GetModifierMask(CTRL), -+ keymapWrapper->GetModifierMask(ALT), -+ keymapWrapper->GetModifierMask(META), -+ keymapWrapper->GetModifierMask(SUPER), -+ keymapWrapper->GetModifierMask(HYPER))); ++ MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, ++ ("%p KeymapWrapper::SetModifierMasks, CapsLock=0x%X, NumLock=0x%X, " ++ "ScrollLock=0x%X, Level3=0x%X, Level5=0x%X, " ++ "Shift=0x%X, Ctrl=0x%X, Alt=0x%X, Meta=0x%X, Super=0x%X, Hyper=0x%X", ++ keymapWrapper, keymapWrapper->GetModifierMask(CAPS_LOCK), ++ keymapWrapper->GetModifierMask(NUM_LOCK), ++ keymapWrapper->GetModifierMask(SCROLL_LOCK), ++ keymapWrapper->GetModifierMask(LEVEL3), ++ keymapWrapper->GetModifierMask(LEVEL5), ++ keymapWrapper->GetModifierMask(SHIFT), ++ keymapWrapper->GetModifierMask(CTRL), ++ keymapWrapper->GetModifierMask(ALT), ++ keymapWrapper->GetModifierMask(META), ++ keymapWrapper->GetModifierMask(SUPER), ++ keymapWrapper->GetModifierMask(HYPER))); +} + +/* This keymap routine is derived from weston-2.0.0/clients/simple-im.c -+*/ -+static void -+keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, -+ uint32_t format, int fd, uint32_t size) -+{ -+ if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { -+ close(fd); -+ return; -+ } -+ -+ char *mapString = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); -+ if (mapString == MAP_FAILED) { -+ close(fd); -+ return; -+ } -+ -+ static auto sXkbContextNew = -+ (struct xkb_context *(*)(enum xkb_context_flags)) -+ dlsym(RTLD_DEFAULT, "xkb_context_new"); -+ static auto sXkbKeymapNewFromString = -+ (struct xkb_keymap *(*)(struct xkb_context *, const char *, -+ enum xkb_keymap_format, enum xkb_keymap_compile_flags)) -+ dlsym(RTLD_DEFAULT, "xkb_keymap_new_from_string"); -+ -+ struct xkb_context *xkb_context = sXkbContextNew(XKB_CONTEXT_NO_FLAGS); -+ struct xkb_keymap *keymap = -+ sXkbKeymapNewFromString(xkb_context, mapString, -+ XKB_KEYMAP_FORMAT_TEXT_V1, -+ XKB_KEYMAP_COMPILE_NO_FLAGS); -+ -+ munmap(mapString, size); ++ */ ++static void keyboard_handle_keymap(void* data, struct wl_keyboard* wl_keyboard, ++ uint32_t format, int fd, uint32_t size) { ++ if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + close(fd); ++ return; ++ } + -+ if (!keymap) { -+ NS_WARNING("keyboard_handle_keymap(): Failed to compile keymap!\n"); -+ return; -+ } ++ char* mapString = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); ++ if (mapString == MAP_FAILED) { ++ close(fd); ++ return; ++ } + -+ KeymapWrapper::SetModifierMasks(keymap); ++ static auto sXkbContextNew = ++ (struct xkb_context * (*)(enum xkb_context_flags)) ++ dlsym(RTLD_DEFAULT, "xkb_context_new"); ++ static auto sXkbKeymapNewFromString = ++ (struct xkb_keymap * (*)(struct xkb_context*, const char*, ++ enum xkb_keymap_format, ++ enum xkb_keymap_compile_flags)) ++ dlsym(RTLD_DEFAULT, "xkb_keymap_new_from_string"); + -+ static auto sXkbKeymapUnRef = -+ (void(*)(struct xkb_keymap *)) -+ dlsym(RTLD_DEFAULT, "xkb_keymap_unref"); -+ sXkbKeymapUnRef(keymap); ++ struct xkb_context* xkb_context = sXkbContextNew(XKB_CONTEXT_NO_FLAGS); ++ struct xkb_keymap* keymap = ++ sXkbKeymapNewFromString(xkb_context, mapString, XKB_KEYMAP_FORMAT_TEXT_V1, ++ XKB_KEYMAP_COMPILE_NO_FLAGS); + -+ static auto sXkbContextUnref = -+ (void(*)(struct xkb_context *)) -+ dlsym(RTLD_DEFAULT, "xkb_context_unref"); -+ sXkbContextUnref(xkb_context); ++ munmap(mapString, size); ++ close(fd); ++ ++ if (!keymap) { ++ NS_WARNING("keyboard_handle_keymap(): Failed to compile keymap!\n"); ++ return; ++ } ++ ++ KeymapWrapper::SetModifierMasks(keymap); ++ ++ static auto sXkbKeymapUnRef = ++ (void (*)(struct xkb_keymap*))dlsym(RTLD_DEFAULT, "xkb_keymap_unref"); ++ sXkbKeymapUnRef(keymap); ++ ++ static auto sXkbContextUnref = ++ (void (*)(struct xkb_context*))dlsym(RTLD_DEFAULT, "xkb_context_unref"); ++ sXkbContextUnref(xkb_context); +} + -+static void -+keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, -+ uint32_t serial, struct wl_surface *surface, -+ struct wl_array *keys) -+{ -+} -+ -+static void -+keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, -+ uint32_t serial, struct wl_surface *surface) -+{ -+} -+ -+static void -+keyboard_handle_key(void *data, struct wl_keyboard *keyboard, -+ uint32_t serial, uint32_t time, uint32_t key, -+ uint32_t state) -+{ -+} -+ -+static void -+keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, -+ uint32_t serial, uint32_t mods_depressed, -+ uint32_t mods_latched, uint32_t mods_locked, -+ uint32_t group) -+{ ++static void keyboard_handle_enter(void* data, struct wl_keyboard* keyboard, ++ uint32_t serial, struct wl_surface* surface, ++ struct wl_array* keys) {} ++static void keyboard_handle_leave(void* data, struct wl_keyboard* keyboard, ++ uint32_t serial, struct wl_surface* surface) { +} ++static void keyboard_handle_key(void* data, struct wl_keyboard* keyboard, ++ uint32_t serial, uint32_t time, uint32_t key, ++ uint32_t state) {} ++static void keyboard_handle_modifiers(void* data, struct wl_keyboard* keyboard, ++ uint32_t serial, uint32_t mods_depressed, ++ uint32_t mods_latched, ++ uint32_t mods_locked, uint32_t group) {} + +static const struct wl_keyboard_listener keyboard_listener = { -+ keyboard_handle_keymap, -+ keyboard_handle_enter, -+ keyboard_handle_leave, -+ keyboard_handle_key, -+ keyboard_handle_modifiers, ++ keyboard_handle_keymap, keyboard_handle_enter, keyboard_handle_leave, ++ keyboard_handle_key, keyboard_handle_modifiers, +}; + -+static void -+seat_handle_capabilities(void *data, struct wl_seat *seat, -+ unsigned int caps) -+{ -+ static wl_keyboard *keyboard = nullptr; ++static void seat_handle_capabilities(void* data, struct wl_seat* seat, ++ unsigned int caps) { ++ static wl_keyboard* keyboard = nullptr; + -+ if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { -+ keyboard = wl_seat_get_keyboard(seat); -+ wl_keyboard_add_listener(keyboard, &keyboard_listener, nullptr); -+ } else if (keyboard && !(caps & WL_SEAT_CAPABILITY_KEYBOARD)) { -+ wl_keyboard_destroy(keyboard); -+ keyboard = nullptr; -+ } ++ if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !keyboard) { ++ keyboard = wl_seat_get_keyboard(seat); ++ wl_keyboard_add_listener(keyboard, &keyboard_listener, nullptr); ++ } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && keyboard) { ++ wl_keyboard_destroy(keyboard); ++ keyboard = nullptr; ++ } +} + +static const struct wl_seat_listener seat_listener = { -+ seat_handle_capabilities, ++ seat_handle_capabilities, +}; + -+static void -+gdk_registry_handle_global(void *data, -+ struct wl_registry *registry, -+ uint32_t id, -+ const char *interface, -+ uint32_t version) -+{ -+ if (strcmp(interface, "wl_seat") == 0) { -+ wl_seat *seat = -+ (wl_seat*)wl_registry_bind(registry, id, &wl_seat_interface, 1); -+ wl_seat_add_listener(seat, &seat_listener, data); -+ } ++static void gdk_registry_handle_global(void* data, struct wl_registry* registry, ++ uint32_t id, const char* interface, ++ uint32_t version) { ++ if (strcmp(interface, "wl_seat") == 0) { ++ wl_seat* seat = ++ (wl_seat*)wl_registry_bind(registry, id, &wl_seat_interface, 1); ++ wl_seat_add_listener(seat, &seat_listener, data); ++ } +} + -+static void -+gdk_registry_handle_global_remove(void *data, -+ struct wl_registry *registry, -+ uint32_t id) -+{ -+} ++static void gdk_registry_handle_global_remove(void* data, ++ struct wl_registry* registry, ++ uint32_t id) {} + +static const struct wl_registry_listener keyboard_registry_listener = { -+ gdk_registry_handle_global, -+ gdk_registry_handle_global_remove -+}; ++ gdk_registry_handle_global, gdk_registry_handle_global_remove}; + -+void -+KeymapWrapper::InitBySystemSettingsWayland() -+{ -+ // 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_get_default()); -+ wl_registry_add_listener(wl_display_get_registry(display), -+ &keyboard_registry_listener, this); -+ -+ // Call wl_display_roundtrip() twice to make sure all -+ // callbacks are processed. -+ wl_display_roundtrip(display); -+ wl_display_roundtrip(display); ++void KeymapWrapper::InitBySystemSettingsWayland() { ++ // 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_get_default()); ++ wl_registry_add_listener(wl_display_get_registry(display), ++ &keyboard_registry_listener, this); +} +#endif + - KeymapWrapper::~KeymapWrapper() - { - gdk_window_remove_filter(nullptr, FilterEvents, this); -@@ -1405,6 +1615,14 @@ void - KeymapWrapper::WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent, - GdkEventKey* aGdkKeyEvent) - { -+ if (!aGdkKeyEvent) { -+ // If aGdkKeyEvent is nullptr, we're trying to dispatch a fake keyboard -+ // event in such case, we don't need to set alternative char codes. -+ // So, we don't need to do nothing here. This case is typically we're -+ // dispatching eKeyDown or eKeyUp event during composition. -+ return; -+ } + KeymapWrapper::~KeymapWrapper() { + gdk_window_remove_filter(nullptr, FilterEvents, this); + g_signal_handlers_disconnect_by_func(mGdkKeymap, +@@ -1473,6 +1638,14 @@ void KeymapWrapper::WillDispatchKeyboard + + void KeymapWrapper::WillDispatchKeyboardEventInternal( + WidgetKeyboardEvent& aKeyEvent, GdkEventKey* aGdkKeyEvent) { ++ if (!aGdkKeyEvent) { ++ // If aGdkKeyEvent is nullptr, we're trying to dispatch a fake keyboard ++ // event in such case, we don't need to set alternative char codes. ++ // So, we don't need to do nothing here. This case is typically we're ++ // dispatching eKeyDown or eKeyUp event during composition. ++ return; ++ } + - uint32_t charCode = GetCharCodeFor(aGdkKeyEvent); - if (!charCode) { - 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-21 13:42:00.760025653 +0100 + uint32_t charCode = GetCharCodeFor(aGdkKeyEvent); + if (!charCode) { + MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, +diff -up thunderbird-60.5.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.5.0/widget/gtk/nsGtkKeyUtils.h +--- thunderbird-60.5.0/widget/gtk/nsGtkKeyUtils.h.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsGtkKeyUtils.h 2019-02-05 14:26:16.976316645 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public @@ -13,6 +13,10 @@ #include @@ -1715,61 +2200,66 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.3. namespace mozilla { namespace widget { -@@ -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); -@@ -148,6 +153,14 @@ public: - static void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyEvent, - GdkEventKey* aGdkKeyEvent); +@@ -145,6 +149,14 @@ class KeymapWrapper { + static void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyEvent, + GdkEventKey* aGdkKeyEvent); +#ifdef MOZ_WAYLAND -+ /** -+ * Utility function to set all supported modifier masks -+ * from xkb_keymap. We call that from Wayland backend routines. -+ */ -+ static void SetModifierMasks(xkb_keymap *aKeymap); ++ /** ++ * Utility function to set all supported modifier masks ++ * from xkb_keymap. We call that from Wayland backend routines. ++ */ ++ static void SetModifierMasks(xkb_keymap* aKeymap); +#endif + - /** - * Destroys the singleton KeymapWrapper instance, if it exists. - */ -@@ -172,7 +185,10 @@ protected: - */ - void Init(); - void InitXKBExtension(); -- void InitBySystemSettings(); -+ void InitBySystemSettingsX11(); + /** + * Destroys the singleton KeymapWrapper instance, if it exists. + */ +@@ -168,7 +180,10 @@ class KeymapWrapper { + */ + void Init(); + void InitXKBExtension(); +- void InitBySystemSettings(); ++ void InitBySystemSettingsX11(); +#ifdef MOZ_WAYLAND -+ void InitBySystemSettingsWayland(); ++ void InitBySystemSettingsWayland(); +#endif - /** - * mModifierKeys stores each hardware key information. -@@ -374,6 +390,15 @@ protected: - */ - void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent, - GdkEventKey* aGdkKeyEvent); + /** + * mModifierKeys stores each hardware key information. +@@ -360,6 +375,14 @@ class KeymapWrapper { + */ + 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); ++ /** ++ * 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-21 13:42:00.760025653 +0100 -@@ -31,7 +31,9 @@ + } // namespace widget +diff -up thunderbird-60.5.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60.5.0/widget/gtk/nsLookAndFeel.cpp +--- thunderbird-60.5.0/widget/gtk/nsLookAndFeel.cpp.wayland 2019-01-22 20:44:03.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsLookAndFeel.cpp 2019-02-05 14:26:16.977316642 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public +@@ -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" @@ -1779,711 +2269,455 @@ diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60. using mozilla::LookAndFeel; #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; - } -@@ -213,6 +215,58 @@ GetBorderColors(GtkStyleContext* aContex - return ret; +@@ -170,7 +173,7 @@ static bool GetBorderColors(GtkStyleCont + // 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; + } +@@ -199,6 +202,57 @@ static bool GetBorderColors(GtkStyleCont + 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); ++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 +323,6 @@ nsLookAndFeel::NativeGetColor(ColorID aI + void nsLookAndFeel::NativeInit() { EnsureInit(); } + + void nsLookAndFeel::RefreshImpl() { +@@ -248,7 +302,6 @@ nsresult nsLookAndFeel::NativeGetColor(C 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_highlight: // preference selected item, + aColor = mTextSelectedBackground; +@@ -258,10 +311,15 @@ nsresult nsLookAndFeel::NativeGetColor(C case eColorID_IMESelectedRawTextForeground: case eColorID_IMESelectedConvertedTextForeground: case eColorID_highlighttext: - case eColorID__moz_cellhighlighttext: case eColorID__moz_html_cellhighlighttext: - aColor = mTextSelectedText; - break; + aColor = mTextSelectedText; + break; + case eColorID__moz_cellhighlight: -+ aColor = mMozCellHighlightBackground; -+ break; ++ aColor = mMozCellHighlightBackground; ++ break; + case eColorID__moz_cellhighlighttext: -+ aColor = mMozCellHighlightText; -+ break; ++ 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); + aColor = NS_RGB(0xa0, 0xa0, 0xa0); + break; +@@ -961,6 +1019,9 @@ void nsLookAndFeel::EnsureInit() { + mOddCellBackground = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); -+ // Compute cell highlight colors -+ InitCellHighlightColors(); ++ // 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; + // 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.5.0/widget/gtk/nsLookAndFeel.h.wayland thunderbird-60.5.0/widget/gtk/nsLookAndFeel.h +--- thunderbird-60.5.0/widget/gtk/nsLookAndFeel.h.wayland 2019-01-22 20:44:03.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsLookAndFeel.h 2019-02-05 14:26:16.977316642 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public +@@ -8,6 +8,7 @@ + #ifndef __nsLookAndFeel + #define __nsLookAndFeel - void EnsureInit(); ++#include "X11UndefineNone.h" + #include "nsXPLookAndFeel.h" + #include "nsCOMPtr.h" + #include "gfxFont.h" +@@ -75,6 +76,8 @@ class nsLookAndFeel final : public nsXPL + nscolor mMozWindowActiveBorder; + nscolor mMozWindowInactiveBorder; + nscolor mMozWindowInactiveCaption; ++ nscolor mMozCellHighlightBackground; ++ nscolor mMozCellHighlightText; + nscolor mTextSelectedText; + nscolor mTextSelectedBackground; + nscolor mMozScrollbar; +@@ -89,6 +92,9 @@ class nsLookAndFeel final : public nsXPL + bool mInitialized; + + void EnsureInit(); + -+private: -+ nsresult InitCellHighlightColors(); ++ 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-21 13:45:42.405091067 +0100 -@@ -24,7 +24,20 @@ - #include "nsIBaseWindow.h" - #include "nsIDocShellTreeItem.h" - #include "nsIDocShell.h" -+#include "nsIGIOService.h" - #include "WidgetUtils.h" -+#include "nsIObserverService.h" +diff -up thunderbird-60.5.0/widget/gtk/nsWaylandDisplay.cpp.wayland thunderbird-60.5.0/widget/gtk/nsWaylandDisplay.cpp +--- thunderbird-60.5.0/widget/gtk/nsWaylandDisplay.cpp.wayland 2019-02-05 14:26:16.977316642 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsWaylandDisplay.cpp 2019-02-05 14:26:16.977316642 +0100 +@@ -0,0 +1,222 @@ ++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim:expandtab:shiftwidth=4:tabstop=4: ++ */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * 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/. */ + -+// for gdk_x11_window_get_xid -+#include -+#include -+#include -+#include -+#include ++#include "nsWaylandDisplay.h" + -+// for dlsym -+#include -+#include "MainThreadUtils.h" - - using namespace mozilla; - using namespace mozilla::widget; -@@ -387,7 +400,7 @@ nsPrintDialogWidgetGTK::ExportHeaderFoot - nsresult - nsPrintDialogWidgetGTK::ImportSettings(nsIPrintSettings *aNSSettings) - { -- NS_PRECONDITION(aNSSettings, "aSettings must not be null"); -+ MOZ_ASSERT(aNSSettings, "aSettings must not be null"); - NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); - - nsCOMPtr aNSSettingsGTK(do_QueryInterface(aNSSettings)); -@@ -416,7 +429,7 @@ nsPrintDialogWidgetGTK::ImportSettings(n - nsresult - nsPrintDialogWidgetGTK::ExportSettings(nsIPrintSettings *aNSSettings) - { -- NS_PRECONDITION(aNSSettings, "aSettings must not be null"); -+ MOZ_ASSERT(aNSSettings, "aSettings must not be null"); - NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); - - GtkPrintSettings* settings = gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog)); -@@ -513,13 +526,521 @@ nsPrintDialogServiceGTK::Init() - return NS_OK; - } - -+// Used to obtain window handle. The portal use this handle -+// to ensure that print dialog is modal. -+typedef void (*WindowHandleExported) (GtkWindow *window, -+ const char *handle, -+ gpointer user_data); ++#include "base/message_loop.h" // for MessageLoop ++#include "base/task.h" // for NewRunnableMethod, etc ++#include "mozilla/StaticMutex.h" + -+typedef void (*GtkWindowHandleExported) (GtkWindow *window, -+ const char *handle, -+ gpointer user_data); -+#ifdef MOZ_WAYLAND -+typedef struct { -+ GtkWindow *window; -+ WindowHandleExported callback; -+ gpointer user_data; -+} WaylandWindowHandleExportedData; ++namespace mozilla { ++namespace widget { + -+static void -+wayland_window_handle_exported (GdkWindow *window, -+ const char *wayland_handle_str, -+ gpointer user_data) -+{ -+ WaylandWindowHandleExportedData *data = -+ static_cast(user_data); -+ char *handle_str; ++#define MAX_DISPLAY_CONNECTIONS 2 + -+ handle_str = g_strdup_printf ("wayland:%s", wayland_handle_str); -+ data->callback (data->window, handle_str, data->user_data); -+ g_free (handle_str); ++static nsWaylandDisplay *gWaylandDisplays[MAX_DISPLAY_CONNECTIONS]; ++static StaticMutex gWaylandDisplaysMutex; ++ ++// Each thread which is using wayland connection (wl_display) has to operate ++// its own wl_event_queue. Main Firefox thread wl_event_queue is handled ++// by Gtk main loop, other threads/wl_event_queue has to be handled by us. ++// ++// nsWaylandDisplay is our interface to wayland compositor. It provides wayland ++// global objects as we need (wl_display, wl_shm) and operates wl_event_queue on ++// compositor (not the main) thread. ++static void WaylandDisplayLoop(wl_display *aDisplay); ++ ++// Get WaylandDisplay for given wl_display and actual calling thread. ++static nsWaylandDisplay *WaylandDisplayGetLocked(wl_display *aDisplay, ++ const StaticMutexAutoLock &) { ++ for (auto &display : gWaylandDisplays) { ++ if (display && display->Matches(aDisplay)) { ++ NS_ADDREF(display); ++ return display; ++ } ++ } ++ ++ for (auto &display : gWaylandDisplays) { ++ if (display == nullptr) { ++ display = new nsWaylandDisplay(aDisplay); ++ NS_ADDREF(display); ++ return display; ++ } ++ } ++ ++ MOZ_CRASH("There's too many wayland display conections!"); ++ return nullptr; +} -+#endif + -+// Get window handle for the portal, taken from gtk/gtkwindow.c -+// (currently not exported) -+static gboolean -+window_export_handle(GtkWindow *window, -+ GtkWindowHandleExported callback, -+ gpointer user_data) -+{ -+ if (GDK_IS_X11_DISPLAY(gtk_widget_get_display(GTK_WIDGET(window)))) -+ { -+ GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(window)); -+ char *handle_str; -+ guint32 xid = (guint32) gdk_x11_window_get_xid(gdk_window); ++nsWaylandDisplay *WaylandDisplayGet(GdkDisplay *aGdkDisplay) { ++ if (!aGdkDisplay) { ++ aGdkDisplay = gdk_display_get_default(); ++ } + -+ handle_str = g_strdup_printf("x11:%x", xid); -+ callback(window, handle_str, user_data); -+ g_free(handle_str); ++ // 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(aGdkDisplay); ++ ++ StaticMutexAutoLock lock(gWaylandDisplaysMutex); ++ return WaylandDisplayGetLocked(display, lock); ++} ++ ++static bool WaylandDisplayReleaseLocked(nsWaylandDisplay *aDisplay, ++ const StaticMutexAutoLock &) { ++ for (auto &display : gWaylandDisplays) { ++ if (display == aDisplay) { ++ int rc = display->Release(); ++ if (rc == 0) { ++ display = nullptr; ++ } + return true; + } -+#ifdef MOZ_WAYLAND -+ else -+ { -+ GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(window)); -+ WaylandWindowHandleExportedData *data; -+ -+ data = g_new0(WaylandWindowHandleExportedData, 1); -+ data->window = window; -+ data->callback = callback; -+ data->user_data = user_data; -+ -+ static auto s_gdk_wayland_window_export_handle = -+ reinterpret_cast -+ (dlsym(RTLD_DEFAULT, "gdk_wayland_window_export_handle")); -+ if (!s_gdk_wayland_window_export_handle || -+ !s_gdk_wayland_window_export_handle(gdk_window, -+ wayland_window_handle_exported, -+ data, g_free)) { -+ g_free (data); -+ return false; -+ } else { -+ return true; -+ } -+ } -+#endif -+ -+ g_warning("Couldn't export handle, unsupported windowing system"); -+ ++ } ++ MOZ_ASSERT(false, "Missing nsWaylandDisplay for this thread!"); + return false; +} -+/** -+ * Communication class with the GTK print portal handler -+ * -+ * To print document from flatpak we need to use print portal because -+ * printers are not directly accessible in the sandboxed environment. -+ * -+ * At first we request portal to show the print dialog to let user choose -+ * printer settings. We use DBUS interface for that (PreparePrint method). -+ * -+ * Next we force application to print to temporary file and after the writing -+ * to the file is finished we pass its file descriptor to the portal. -+ * Portal will pass duplicate of the file descriptor to the printer which -+ * user selected before (by DBUS Print method). -+ * -+ * Since DBUS communication is done async while nsPrintDialogServiceGTK::Show -+ * is expecting sync execution, we need to create a new GMainLoop during the -+ * print portal dialog is running. The loop is stopped after the dialog -+ * is closed. ++ ++void WaylandDisplayRelease(nsWaylandDisplay *aDisplay) { ++ StaticMutexAutoLock lock(gWaylandDisplaysMutex); ++ WaylandDisplayReleaseLocked(aDisplay, lock); ++} ++ ++static void WaylandDisplayLoopLocked(wl_display *aDisplay, ++ const StaticMutexAutoLock &) { ++ for (auto &display : gWaylandDisplays) { ++ if (display && display->Matches(aDisplay)) { ++ if (display->DisplayLoop()) { ++ MessageLoop::current()->PostDelayedTask( ++ NewRunnableFunction("WaylandDisplayLoop", &WaylandDisplayLoop, ++ aDisplay), ++ EVENT_LOOP_DELAY); ++ } ++ break; ++ } ++ } ++} ++ ++static void WaylandDisplayLoop(wl_display *aDisplay) { ++ MOZ_ASSERT(!NS_IsMainThread()); ++ StaticMutexAutoLock lock(gWaylandDisplaysMutex); ++ WaylandDisplayLoopLocked(aDisplay, lock); ++} ++ ++void nsWaylandDisplay::SetShm(wl_shm *aShm) { mShm = aShm; } ++ ++void nsWaylandDisplay::SetSubcompositor(wl_subcompositor *aSubcompositor) { ++ mSubcompositor = aSubcompositor; ++} ++ ++void nsWaylandDisplay::SetDataDeviceManager( ++ wl_data_device_manager *aDataDeviceManager) { ++ mDataDeviceManager = aDataDeviceManager; ++} ++ ++void nsWaylandDisplay::SetSeat(wl_seat *aSeat) { mSeat = aSeat; } ++ ++void nsWaylandDisplay::SetPrimarySelectionDeviceManager( ++ gtk_primary_selection_device_manager *aPrimarySelectionDeviceManager) { ++ mPrimarySelectionDeviceManager = aPrimarySelectionDeviceManager; ++} ++ ++static void global_registry_handler(void *data, wl_registry *registry, ++ uint32_t id, const char *interface, ++ uint32_t version) { ++ auto display = reinterpret_cast(data); ++ ++ if (strcmp(interface, "wl_shm") == 0) { ++ auto shm = static_cast( ++ wl_registry_bind(registry, id, &wl_shm_interface, 1)); ++ wl_proxy_set_queue((struct wl_proxy *)shm, display->GetEventQueue()); ++ display->SetShm(shm); ++ } else if (strcmp(interface, "wl_data_device_manager") == 0) { ++ int data_device_manager_version = MIN(version, 3); ++ auto data_device_manager = static_cast( ++ wl_registry_bind(registry, id, &wl_data_device_manager_interface, ++ data_device_manager_version)); ++ wl_proxy_set_queue((struct wl_proxy *)data_device_manager, ++ display->GetEventQueue()); ++ display->SetDataDeviceManager(data_device_manager); ++ } else if (strcmp(interface, "wl_seat") == 0) { ++ auto seat = static_cast( ++ wl_registry_bind(registry, id, &wl_seat_interface, 1)); ++ wl_proxy_set_queue((struct wl_proxy *)seat, display->GetEventQueue()); ++ display->SetSeat(seat); ++ } else if (strcmp(interface, "gtk_primary_selection_device_manager") == 0) { ++ auto primary_selection_device_manager = ++ static_cast(wl_registry_bind( ++ registry, id, >k_primary_selection_device_manager_interface, 1)); ++ wl_proxy_set_queue((struct wl_proxy *)primary_selection_device_manager, ++ display->GetEventQueue()); ++ display->SetPrimarySelectionDeviceManager(primary_selection_device_manager); ++ } else if (strcmp(interface, "wl_subcompositor") == 0) { ++ auto subcompositor = static_cast( ++ wl_registry_bind(registry, id, &wl_subcompositor_interface, 1)); ++ wl_proxy_set_queue((struct wl_proxy *)subcompositor, ++ display->GetEventQueue()); ++ display->SetSubcompositor(subcompositor); ++ } ++} ++ ++static void global_registry_remover(void *data, wl_registry *registry, ++ uint32_t id) {} ++ ++static const struct wl_registry_listener registry_listener = { ++ global_registry_handler, global_registry_remover}; ++ ++bool nsWaylandDisplay::DisplayLoop() { ++ wl_display_dispatch_queue_pending(mDisplay, mEventQueue); ++ return true; ++} ++ ++bool nsWaylandDisplay::Matches(wl_display *aDisplay) { ++ return mThreadId == PR_GetCurrentThread() && aDisplay == mDisplay; ++} ++ ++NS_IMPL_ISUPPORTS(nsWaylandDisplay, nsISupports); ++ ++nsWaylandDisplay::nsWaylandDisplay(wl_display *aDisplay) ++ : mThreadId(PR_GetCurrentThread()), ++ mDisplay(aDisplay), ++ mEventQueue(nullptr), ++ mDataDeviceManager(nullptr), ++ mSubcompositor(nullptr), ++ mSeat(nullptr), ++ mShm(nullptr), ++ mPrimarySelectionDeviceManager(nullptr) { ++ wl_registry *registry = wl_display_get_registry(mDisplay); ++ wl_registry_add_listener(registry, ®istry_listener, this); ++ ++ if (NS_IsMainThread()) { ++ // Use default event queue in main thread operated by Gtk+. ++ mEventQueue = nullptr; ++ wl_display_roundtrip(mDisplay); ++ wl_display_roundtrip(mDisplay); ++ } else { ++ mEventQueue = wl_display_create_queue(mDisplay); ++ MessageLoop::current()->PostTask(NewRunnableFunction( ++ "WaylandDisplayLoop", &WaylandDisplayLoop, mDisplay)); ++ wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue); ++ wl_display_roundtrip_queue(mDisplay, mEventQueue); ++ wl_display_roundtrip_queue(mDisplay, mEventQueue); ++ } ++} ++ ++nsWaylandDisplay::~nsWaylandDisplay() { ++ MOZ_ASSERT(mThreadId == PR_GetCurrentThread()); ++ // Owned by Gtk+, we don't need to release ++ mDisplay = nullptr; ++ ++ if (mEventQueue) { ++ wl_event_queue_destroy(mEventQueue); ++ mEventQueue = nullptr; ++ } ++} ++ ++} // namespace widget ++} // namespace mozilla +diff -up thunderbird-60.5.0/widget/gtk/nsWaylandDisplay.h.wayland thunderbird-60.5.0/widget/gtk/nsWaylandDisplay.h +--- thunderbird-60.5.0/widget/gtk/nsWaylandDisplay.h.wayland 2019-02-05 14:26:16.977316642 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsWaylandDisplay.h 2019-02-05 14:26:16.977316642 +0100 +@@ -0,0 +1,72 @@ ++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim:expandtab:shiftwidth=4:tabstop=4: + */ -+class nsFlatpakPrintPortal: public nsIObserver -+{ -+ NS_DECL_ISUPPORTS -+ NS_DECL_NSIOBSERVER -+ public: -+ explicit nsFlatpakPrintPortal(nsPrintSettingsGTK* aPrintSettings); -+ nsresult PreparePrintRequest(GtkWindow* aWindow); -+ static void OnWindowExportHandleDone(GtkWindow *aWindow, -+ const char* aWindowHandleStr, -+ gpointer aUserData); -+ void PreparePrint(GtkWindow* aWindow, const char* aWindowHandleStr); -+ static void OnPreparePrintResponse(GDBusConnection *connection, -+ const char *sender_name, -+ const char *object_path, -+ const char *interface_name, -+ const char *signal_name, -+ GVariant *parameters, -+ gpointer data); -+ GtkPrintOperationResult GetResult(); -+ private: -+ virtual ~nsFlatpakPrintPortal(); -+ void FinishPrintDialog(GVariant* parameters); -+ nsCOMPtr mPrintAndPageSettings; -+ GDBusProxy* mProxy; -+ guint32 mToken; -+ GMainLoop* mLoop; -+ GtkPrintOperationResult mResult; -+ guint mResponseSignalId; -+ GtkWindow* mParentWindow; ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * 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 __MOZ_WAYLAND_REGISTRY_H__ ++#define __MOZ_WAYLAND_REGISTRY_H__ ++ ++#include "nsISupports.h" ++#include "mozwayland/mozwayland.h" ++#include "wayland/gtk-primary-selection-client-protocol.h" ++ ++namespace mozilla { ++namespace widget { ++ ++// TODO: Bug 1467125 - We need to integrate wl_display_dispatch_queue_pending() ++// with compositor event loop. ++#define EVENT_LOOP_DELAY (1000 / 240) ++ ++// Our general connection to Wayland display server, ++// holds our display connection and runs event loop. ++class nsWaylandDisplay : public nsISupports { ++ NS_DECL_THREADSAFE_ISUPPORTS ++ ++ public: ++ explicit nsWaylandDisplay(wl_display* aDisplay); ++ ++ bool DisplayLoop(); ++ bool Matches(wl_display* aDisplay); ++ ++ wl_display* GetDisplay() { return mDisplay; }; ++ wl_event_queue* GetEventQueue() { return mEventQueue; }; ++ wl_subcompositor* GetSubcompositor(void) { return mSubcompositor; }; ++ wl_data_device_manager* GetDataDeviceManager(void) { ++ return mDataDeviceManager; ++ }; ++ wl_seat* GetSeat(void) { return mSeat; }; ++ wl_shm* GetShm(void) { return mShm; }; ++ gtk_primary_selection_device_manager* GetPrimarySelectionDeviceManager(void) { ++ return mPrimarySelectionDeviceManager; ++ }; ++ ++ public: ++ void SetShm(wl_shm* aShm); ++ void SetSubcompositor(wl_subcompositor* aSubcompositor); ++ void SetDataDeviceManager(wl_data_device_manager* aDataDeviceManager); ++ void SetSeat(wl_seat* aSeat); ++ void SetPrimarySelectionDeviceManager( ++ gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager); ++ ++ private: ++ virtual ~nsWaylandDisplay(); ++ ++ PRThread* mThreadId; ++ wl_display* mDisplay; ++ wl_event_queue* mEventQueue; ++ wl_data_device_manager* mDataDeviceManager; ++ wl_subcompositor* mSubcompositor; ++ wl_seat* mSeat; ++ wl_shm* mShm; ++ gtk_primary_selection_device_manager* mPrimarySelectionDeviceManager; +}; + -+NS_IMPL_ISUPPORTS(nsFlatpakPrintPortal, nsIObserver) ++nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay = nullptr); ++void WaylandDisplayRelease(nsWaylandDisplay* aDisplay); + -+nsFlatpakPrintPortal::nsFlatpakPrintPortal(nsPrintSettingsGTK* aPrintSettings): -+ mPrintAndPageSettings(aPrintSettings), -+ mProxy(nullptr), -+ mLoop(nullptr), -+ mResponseSignalId(0), -+ mParentWindow(nullptr) -+{ -+} ++} // namespace widget ++} // namespace mozilla + -+/** -+ * Creates GDBusProxy, query for window handle and create a new GMainLoop. -+ * -+ * The GMainLoop is to be run from GetResult() and be quitted during -+ * FinishPrintDialog. -+ * -+ * @param aWindow toplevel application window which is used as parent of print -+ * dialog -+ */ -+nsresult -+nsFlatpakPrintPortal::PreparePrintRequest(GtkWindow* aWindow) -+{ -+ MOZ_ASSERT(aWindow, "aWindow must not be null"); -+ MOZ_ASSERT(mPrintAndPageSettings, "mPrintAndPageSettings must not be null"); -+ -+ GError* error = nullptr; -+ mProxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, -+ G_DBUS_PROXY_FLAGS_NONE, -+ nullptr, -+ "org.freedesktop.portal.Desktop", -+ "/org/freedesktop/portal/desktop", -+ "org.freedesktop.portal.Print", -+ nullptr, -+ &error); -+ if (mProxy == nullptr) { -+ NS_WARNING(nsPrintfCString("Unable to create dbus proxy: %s", error->message).get()); -+ g_error_free(error); -+ return NS_ERROR_FAILURE; -+ } -+ -+ // The window handler is returned async, we will continue by PreparePrint method -+ // when it is returned. -+ if (!window_export_handle(aWindow, -+ &nsFlatpakPrintPortal::OnWindowExportHandleDone, this)) { -+ NS_WARNING("Unable to get window handle for creating modal print dialog."); -+ return NS_ERROR_FAILURE; -+ } -+ -+ mLoop = g_main_loop_new (NULL, FALSE); -+ return NS_OK; -+} -+ -+void -+nsFlatpakPrintPortal::OnWindowExportHandleDone(GtkWindow* aWindow, -+ const char* aWindowHandleStr, -+ gpointer aUserData) -+{ -+ nsFlatpakPrintPortal* printPortal = static_cast(aUserData); -+ printPortal->PreparePrint(aWindow, aWindowHandleStr); -+} -+ -+/** -+ * Ask print portal to show the print dialog. -+ * -+ * Print and page settings and window handle are passed to the portal to prefill -+ * last used settings. -+ */ -+void -+nsFlatpakPrintPortal::PreparePrint(GtkWindow* aWindow, const char* aWindowHandleStr) -+{ -+ GtkPrintSettings* gtkSettings = mPrintAndPageSettings->GetGtkPrintSettings(); -+ GtkPageSetup* pageSetup = mPrintAndPageSettings->GetGtkPageSetup(); -+ -+ // We need to remember GtkWindow to unexport window handle after it is -+ // no longer needed by the portal dialog (apply only on non-X11 sessions). -+ if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) { -+ mParentWindow = aWindow; -+ } -+ -+ GVariantBuilder opt_builder; -+ g_variant_builder_init(&opt_builder, G_VARIANT_TYPE_VARDICT); -+ char* token = g_strdup_printf("mozilla%d", g_random_int_range (0, G_MAXINT)); -+ g_variant_builder_add(&opt_builder, "{sv}", "handle_token", -+ g_variant_new_string(token)); -+ g_free(token); -+ GVariant* options = g_variant_builder_end(&opt_builder); -+ static auto s_gtk_print_settings_to_gvariant = -+ reinterpret_cast -+ (dlsym(RTLD_DEFAULT, "gtk_print_settings_to_gvariant")); -+ static auto s_gtk_page_setup_to_gvariant = -+ reinterpret_cast -+ (dlsym(RTLD_DEFAULT, "gtk_page_setup_to_gvariant")); -+ if (!s_gtk_print_settings_to_gvariant || !s_gtk_page_setup_to_gvariant) { -+ mResult = GTK_PRINT_OPERATION_RESULT_ERROR; -+ FinishPrintDialog(nullptr); -+ return; -+ } -+ -+ // Get translated window title -+ nsCOMPtr bundleSvc = -+ do_GetService(NS_STRINGBUNDLE_CONTRACTID); -+ nsCOMPtr printBundle; -+ bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", -+ getter_AddRefs(printBundle)); -+ nsAutoString intlPrintTitle; -+ printBundle->GetStringFromName("printTitleGTK", intlPrintTitle); -+ -+ GError* error = nullptr; -+ GVariant *ret = g_dbus_proxy_call_sync(mProxy, -+ "PreparePrint", -+ g_variant_new ("(ss@a{sv}@a{sv}@a{sv})", -+ aWindowHandleStr, -+ NS_ConvertUTF16toUTF8(intlPrintTitle).get(), // Title of the window -+ s_gtk_print_settings_to_gvariant(gtkSettings), -+ s_gtk_page_setup_to_gvariant(pageSetup), -+ options), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, -+ nullptr, -+ &error); -+ if (ret == nullptr) { -+ NS_WARNING(nsPrintfCString("Unable to call dbus proxy: %s", error->message).get()); -+ g_error_free (error); -+ mResult = GTK_PRINT_OPERATION_RESULT_ERROR; -+ FinishPrintDialog(nullptr); -+ return; -+ } -+ -+ const char* handle = nullptr; -+ g_variant_get (ret, "(&o)", &handle); -+ if (strcmp (aWindowHandleStr, handle) != 0) -+ { -+ aWindowHandleStr = g_strdup (handle); -+ if (mResponseSignalId) { -+ g_dbus_connection_signal_unsubscribe( -+ g_dbus_proxy_get_connection(G_DBUS_PROXY(mProxy)), mResponseSignalId); -+ } -+ } -+ mResponseSignalId = -+ g_dbus_connection_signal_subscribe( -+ g_dbus_proxy_get_connection(G_DBUS_PROXY(mProxy)), -+ "org.freedesktop.portal.Desktop", -+ "org.freedesktop.portal.Request", -+ "Response", -+ aWindowHandleStr, -+ NULL, -+ G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, -+ &nsFlatpakPrintPortal::OnPreparePrintResponse, -+ this, NULL); -+ -+} -+ -+void -+nsFlatpakPrintPortal::OnPreparePrintResponse(GDBusConnection *connection, -+ const char *sender_name, -+ const char *object_path, -+ const char *interface_name, -+ const char *signal_name, -+ GVariant *parameters, -+ gpointer data) -+{ -+ nsFlatpakPrintPortal* printPortal = static_cast(data); -+ printPortal->FinishPrintDialog(parameters); -+} -+ -+/** -+ * When the dialog is accepted, read print and page settings and token. -+ * -+ * Token is later used for printing portal as print operation identifier. -+ * Print and page settings are modified in-place and stored to -+ * mPrintAndPageSettings. -+ */ -+void -+nsFlatpakPrintPortal::FinishPrintDialog(GVariant* parameters) -+{ -+ // This ends GetResult() method -+ if (mLoop) { -+ g_main_loop_quit (mLoop); -+ mLoop = nullptr; -+ } -+ -+ if (!parameters) { -+ // mResult should be already defined -+ return; -+ } -+ -+ guint32 response; -+ GVariant *options; -+ -+ g_variant_get (parameters, "(u@a{sv})", &response, &options); -+ mResult = GTK_PRINT_OPERATION_RESULT_CANCEL; -+ if (response == 0) { -+ GVariant *v; -+ -+ char *filename; -+ char *uri; -+ v = g_variant_lookup_value (options, "settings", G_VARIANT_TYPE_VARDICT); -+ static auto s_gtk_print_settings_new_from_gvariant = -+ reinterpret_cast -+ (dlsym(RTLD_DEFAULT, "gtk_print_settings_new_from_gvariant")); -+ -+ GtkPrintSettings* printSettings = s_gtk_print_settings_new_from_gvariant(v); -+ g_variant_unref (v); -+ -+ v = g_variant_lookup_value (options, "page-setup", G_VARIANT_TYPE_VARDICT); -+ static auto s_gtk_page_setup_new_from_gvariant = -+ reinterpret_cast -+ (dlsym(RTLD_DEFAULT, "gtk_page_setup_new_from_gvariant")); -+ GtkPageSetup* pageSetup = s_gtk_page_setup_new_from_gvariant(v); -+ g_variant_unref (v); -+ -+ g_variant_lookup (options, "token", "u", &mToken); -+ -+ // Force printing to file because only filedescriptor of the file -+ // can be passed to portal -+ int fd = g_file_open_tmp("gtkprintXXXXXX", &filename, NULL); -+ uri = g_filename_to_uri(filename, NULL, NULL); -+ gtk_print_settings_set(printSettings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri); -+ g_free (uri); -+ close (fd); -+ -+ // Save native settings in the session object -+ mPrintAndPageSettings->SetGtkPrintSettings(printSettings); -+ mPrintAndPageSettings->SetGtkPageSetup(pageSetup); -+ -+ // Portal consumes PDF file -+ mPrintAndPageSettings->SetOutputFormat(nsIPrintSettings::kOutputFormatPDF); -+ -+ // We need to set to print to file -+ mPrintAndPageSettings->SetPrintToFile(true); -+ -+ mResult = GTK_PRINT_OPERATION_RESULT_APPLY; -+ } -+} -+ -+/** -+ * Get result of the print dialog. -+ * -+ * This call blocks until FinishPrintDialog is called. -+ * -+ */ -+GtkPrintOperationResult -+nsFlatpakPrintPortal::GetResult() { -+ // If the mLoop has not been initialized we haven't go thru PreparePrint method -+ if (!NS_IsMainThread() || !mLoop) { -+ return GTK_PRINT_OPERATION_RESULT_ERROR; -+ } -+ // Calling g_main_loop_run stops current code until g_main_loop_quit is called -+ g_main_loop_run(mLoop); -+ -+ // Free resources we've allocated in order to show print dialog. -+#ifdef MOZ_WAYLAND -+ if (mParentWindow) { -+ GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(mParentWindow)); -+ static auto s_gdk_wayland_window_unexport_handle = -+ reinterpret_cast -+ (dlsym(RTLD_DEFAULT, "gdk_wayland_window_unexport_handle")); -+ if (s_gdk_wayland_window_unexport_handle) { -+ s_gdk_wayland_window_unexport_handle(gdk_window); -+ } -+ } -+#endif -+ return mResult; -+} -+ -+/** -+ * Send file descriptor of the file which contains document to the portal to -+ * finish the print operation. -+ */ -+NS_IMETHODIMP -+nsFlatpakPrintPortal::Observe(nsISupports *aObject, const char * aTopic, -+ const char16_t * aData) -+{ -+ // Check that written file match to the stored filename in case multiple -+ // print operations are in progress. -+ nsAutoString filenameStr; -+ mPrintAndPageSettings->GetToFileName(filenameStr); -+ if (!nsDependentString(aData).Equals(filenameStr)) { -+ // Different file is finished, not for this instance -+ return NS_OK; -+ } -+ int fd, idx; -+ fd = open(NS_ConvertUTF16toUTF8(filenameStr).get(), O_RDONLY|O_CLOEXEC); -+ static auto s_g_unix_fd_list_new = -+ reinterpret_cast -+ (dlsym(RTLD_DEFAULT, "g_unix_fd_list_new")); -+ NS_ASSERTION(s_g_unix_fd_list_new, "Cannot find g_unix_fd_list_new function."); -+ -+ GUnixFDList *fd_list = s_g_unix_fd_list_new(); -+ static auto s_g_unix_fd_list_append = -+ reinterpret_cast -+ (dlsym(RTLD_DEFAULT, "g_unix_fd_list_append")); -+ idx = s_g_unix_fd_list_append(fd_list, fd, NULL); -+ close(fd); -+ -+ GVariantBuilder opt_builder; -+ g_variant_builder_init(&opt_builder, G_VARIANT_TYPE_VARDICT); -+ g_variant_builder_add(&opt_builder, "{sv}", "token", -+ g_variant_new_uint32(mToken)); -+ g_dbus_proxy_call_with_unix_fd_list( -+ mProxy, -+ "Print", -+ g_variant_new("(ssh@a{sv})", -+ "", /* window */ -+ "Print", /* title */ -+ idx, -+ g_variant_builder_end(&opt_builder)), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, -+ fd_list, -+ NULL, -+ NULL, // TODO portal result cb function -+ nullptr); // data -+ g_object_unref(fd_list); -+ -+ nsCOMPtr os = mozilla::services::GetObserverService(); -+ // Let the nsFlatpakPrintPortal instance die -+ os->RemoveObserver(this, "print-to-file-finished"); -+ return NS_OK; -+} -+ -+nsFlatpakPrintPortal::~nsFlatpakPrintPortal() { -+ if (mProxy) { -+ if (mResponseSignalId) { -+ g_dbus_connection_signal_unsubscribe( -+ g_dbus_proxy_get_connection(G_DBUS_PROXY(mProxy)), mResponseSignalId); -+ } -+ g_object_unref(mProxy); -+ } -+ if (mLoop) -+ g_main_loop_quit(mLoop); -+} -+ - NS_IMETHODIMP - nsPrintDialogServiceGTK::Show(nsPIDOMWindowOuter *aParent, - nsIPrintSettings *aSettings, - nsIWebBrowserPrint *aWebBrowserPrint) - { -- NS_PRECONDITION(aParent, "aParent must not be null"); -- NS_PRECONDITION(aSettings, "aSettings must not be null"); -+ MOZ_ASSERT(aParent, "aParent must not be null"); -+ MOZ_ASSERT(aSettings, "aSettings must not be null"); -+ -+ // Check for the flatpak portal first -+ nsCOMPtr giovfs = -+ do_GetService(NS_GIOSERVICE_CONTRACTID); -+ 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."); -+ GtkWindow* gtkParent = get_gtk_window_for_nsiwidget(widget); -+ NS_ASSERTION(gtkParent, "Need a GTK window for dialog to be modal."); -+ -+ -+ nsCOMPtr printSettingsGTK(do_QueryInterface(aSettings)); -+ RefPtr fpPrintPortal = -+ new nsFlatpakPrintPortal(printSettingsGTK); -+ -+ nsresult rv = fpPrintPortal->PreparePrintRequest(gtkParent); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ // This blocks until nsFlatpakPrintPortal::FinishPrintDialog is called -+ GtkPrintOperationResult printDialogResult = fpPrintPortal->GetResult(); -+ -+ rv = NS_OK; -+ switch (printDialogResult) { -+ case GTK_PRINT_OPERATION_RESULT_APPLY: -+ { -+ nsCOMPtr observer = do_QueryInterface(fpPrintPortal); -+ nsCOMPtr os = mozilla::services::GetObserverService(); -+ NS_ENSURE_STATE(os); -+ // Observer waits until notified that the file with the content -+ // to print has been written. -+ rv = os->AddObserver(observer, "print-to-file-finished", false); -+ 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 +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); - - 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-21 13:42:00.762025644 +0100 ++#endif // __MOZ_WAYLAND_REGISTRY_H__ +diff -up thunderbird-60.5.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.5.0/widget/gtk/nsWindow.cpp +--- thunderbird-60.5.0/widget/gtk/nsWindow.cpp.wayland 2019-01-22 20:44:03.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsWindow.cpp 2019-02-05 14:26:16.978316639 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public @@ -18,6 +18,7 @@ #include "mozilla/TouchEvents.h" #include "mozilla/UniquePtrExtensions.h" @@ -2492,7 +2726,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w #include #include "GeckoProfiler.h" -@@ -25,7 +26,7 @@ +@@ -25,13 +26,15 @@ #include "prlink.h" #include "nsGTKToolkit.h" #include "nsIRollupListener.h" @@ -2501,7 +2735,15 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w #include "nsWidgetsCID.h" #include "nsDragService.h" -@@ -56,6 +57,7 @@ + #include "nsIWidgetListener.h" + #include "nsIScreenManager.h" + #include "SystemTimeConverter.h" ++#include "nsIPresShell.h" ++#include "nsViewManager.h" + + #include "nsGtkKeyUtils.h" + #include "nsGtkCursors.h" +@@ -56,6 +59,7 @@ #if defined(MOZ_WAYLAND) #include @@ -2509,15 +2751,15 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w #endif #include "nsGkAtoms.h" -@@ -116,6 +118,7 @@ using namespace mozilla::widget; +@@ -116,6 +120,7 @@ using namespace mozilla::widget; #include "mozilla/layers/CompositorThread.h" #ifdef MOZ_X11 -+#include "GLContextGLX.h" // for GLContextGLX::FindVisual() ++#include "GLContextGLX.h" // for GLContextGLX::FindVisual() #include "GtkCompositorWidget.h" #include "gfxXlibSurface.h" #include "WindowSurfaceX11Image.h" -@@ -129,8 +132,6 @@ using namespace mozilla::widget; +@@ -129,8 +134,6 @@ using namespace mozilla::widget; #include "nsShmImage.h" #include "gtkdrawing.h" @@ -2526,7 +2768,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w #include "NativeKeyBindings.h" #include -@@ -140,6 +141,7 @@ using namespace mozilla::gfx; +@@ -140,6 +143,7 @@ using namespace mozilla::gfx; using namespace mozilla::widget; using namespace mozilla::layers; using mozilla::gl::GLContext; @@ -2534,135 +2776,148 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w // Don't put more than this many rects in the dirty region, just fluff // out to the bounding-box if there are more -@@ -155,7 +157,8 @@ const gint kEvents = GDK_EXPOSURE_MASK | +@@ -152,9 +156,12 @@ const gint kEvents = + #if GTK_CHECK_VERSION(3, 4, 0) + GDK_SMOOTH_SCROLL_MASK | GDK_TOUCH_MASK | #endif - GDK_SCROLL_MASK | - GDK_POINTER_MOTION_MASK | -- GDK_PROPERTY_CHANGE_MASK; -+ GDK_PROPERTY_CHANGE_MASK | -+ GDK_FOCUS_CHANGE_MASK; +- GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK; ++ GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK | ++ GDK_FOCUS_CHANGE_MASK; /* utility functions */ - static bool is_mouse_in_window(GdkWindow* aWindow, -@@ -210,7 +213,7 @@ static void hierarchy_changed_cb - GtkWidget *previous_toplevel); - static gboolean window_state_event_cb (GtkWidget *widget, - GdkEventWindowState *event); --static void theme_changed_cb (GtkSettings *settings, -+static void settings_changed_cb (GtkSettings *settings, - GParamSpec *pspec, - nsWindow *data); - static void check_resize_cb (GtkContainer* container, -@@ -481,6 +484,8 @@ nsWindow::nsWindow() - mPendingConfigures = 0; - mCSDSupportLevel = CSD_SUPPORT_NONE; - mDrawInTitlebar = false; -+ -+ mHasAlphaVisual = false; ++static void theme_changed_cb(GtkSettings *settings, GParamSpec *pspec, ++ nsWindow *data); + static bool is_mouse_in_window(GdkWindow *aWindow, gdouble aMouseX, + gdouble aMouseY); + static nsWindow *get_window_for_gtk_widget(GtkWidget *widget); +@@ -196,8 +203,6 @@ static void hierarchy_changed_cb(GtkWidg + GtkWidget *previous_toplevel); + static gboolean window_state_event_cb(GtkWidget *widget, + GdkEventWindowState *event); +-static void theme_changed_cb(GtkSettings *settings, GParamSpec *pspec, +- nsWindow *data); + static void check_resize_cb(GtkContainer *container, gpointer user_data); + static void screen_composited_changed_cb(GdkScreen *screen, gpointer user_data); + static void widget_composited_changed_cb(GtkWidget *widget, gpointer user_data); +@@ -550,7 +555,7 @@ static GtkWidget *EnsureInvisibleContain } - nsWindow::~nsWindow() -@@ -630,7 +635,7 @@ EnsureInvisibleContainer() - static void - CheckDestroyInvisibleContainer() - { -- NS_PRECONDITION(gInvisibleContainer, "oh, no"); -+ MOZ_ASSERT(gInvisibleContainer, "oh, no"); + static void CheckDestroyInvisibleContainer() { +- NS_PRECONDITION(gInvisibleContainer, "oh, no"); ++ MOZ_ASSERT(gInvisibleContainer, "oh, no"); - if (!gdk_window_peek_children(gtk_widget_get_window(gInvisibleContainer))) { - // No children, so not in use. -@@ -731,7 +736,7 @@ nsWindow::Destroy() - ClearCachedResources(); + if (!gdk_window_peek_children(gtk_widget_get_window(gInvisibleContainer))) { + // No children, so not in use. +@@ -639,9 +644,6 @@ void nsWindow::Destroy() { - g_signal_handlers_disconnect_by_func(gtk_settings_get_default(), -- FuncToGpointer(theme_changed_cb), -+ FuncToGpointer(settings_changed_cb), - this); + ClearCachedResources(); - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); -@@ -841,8 +846,14 @@ nsWindow::GetDesktopToDeviceScale() - void - nsWindow::SetParent(nsIWidget *aNewParent) - { -- if (mContainer || !mGdkWindow) { -- NS_NOTREACHED("nsWindow::SetParent called illegally"); -+ if (!mGdkWindow) { -+ MOZ_ASSERT_UNREACHABLE("The native window has already been destroyed"); -+ return; -+ } +- g_signal_handlers_disconnect_by_func(gtk_settings_get_default(), +- FuncToGpointer(theme_changed_cb), this); +- + nsIRollupListener *rollupListener = nsBaseWidget::GetActiveRollupListener(); + if (rollupListener) { + nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); +@@ -725,7 +727,7 @@ double nsWindow::GetDefaultScaleInternal + DesktopToLayoutDeviceScale nsWindow::GetDesktopToDeviceScale() { + #ifdef MOZ_WAYLAND + GdkDisplay *gdkDisplay = gdk_display_get_default(); +- if (GDK_IS_WAYLAND_DISPLAY(gdkDisplay)) { ++ if (!GDK_IS_X11_DISPLAY(gdkDisplay)) { + return DesktopToLayoutDeviceScale(GdkScaleFactor()); + } + #endif +@@ -735,8 +737,14 @@ DesktopToLayoutDeviceScale nsWindow::Get + } + + void nsWindow::SetParent(nsIWidget *aNewParent) { +- if (mContainer || !mGdkWindow) { +- NS_NOTREACHED("nsWindow::SetParent called illegally"); ++ if (!mGdkWindow) { ++ MOZ_ASSERT_UNREACHABLE("The native window has already been destroyed"); ++ return; ++ } + -+ if (mContainer) { -+ // FIXME bug 1469183 -+ NS_ERROR("nsWindow should not have a container here"); - return; - } ++ if (mContainer) { ++ // FIXME bug 1469183 ++ NS_ERROR("nsWindow should not have a container here"); + return; + } -@@ -886,7 +897,7 @@ nsWindow::WidgetTypeSupportsAcceleration - void - nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) - { -- NS_PRECONDITION(aNewParent, ""); -+ MOZ_ASSERT(aNewParent, "null widget"); - NS_ASSERTION(!mIsDestroyed, ""); - NS_ASSERTION(!static_cast(aNewParent)->mIsDestroyed, ""); +@@ -774,7 +782,7 @@ void nsWindow::SetParent(nsIWidget *aNew + bool nsWindow::WidgetTypeSupportsAcceleration() { return !IsSmallPopup(); } -@@ -1517,7 +1528,7 @@ nsWindow::GetClientBounds() - void - nsWindow::UpdateClientOffset() - { -- AUTO_PROFILER_LABEL("nsWindow::UpdateClientOffset", GRAPHICS); -+ AUTO_PROFILER_LABEL("nsWindow::UpdateClientOffset", OTHER); + void nsWindow::ReparentNativeWidget(nsIWidget *aNewParent) { +- NS_PRECONDITION(aNewParent, ""); ++ MOZ_ASSERT(aNewParent, "null widget"); + NS_ASSERTION(!mIsDestroyed, ""); + NS_ASSERTION(!static_cast(aNewParent)->mIsDestroyed, ""); - if (!mIsTopLevel || !mShell || !mIsX11Display || - gtk_window_get_window_type(GTK_WINDOW(mShell)) == GTK_WINDOW_POPUP) { -@@ -2057,6 +2068,12 @@ nsWindow::OnExposeEvent(cairo_t *cr) - if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel) - return FALSE; +@@ -1331,7 +1339,7 @@ LayoutDeviceIntRect nsWindow::GetClientB + } + void nsWindow::UpdateClientOffset() { +- AUTO_PROFILER_LABEL("nsWindow::UpdateClientOffset", GRAPHICS); ++ AUTO_PROFILER_LABEL("nsWindow::UpdateClientOffset", OTHER); + + if (!mIsTopLevel || !mShell || !mIsX11Display || + gtk_window_get_window_type(GTK_WINDOW(mShell)) == GTK_WINDOW_POPUP) { +@@ -1373,9 +1381,7 @@ LayoutDeviceIntPoint nsWindow::GetClient + } + + gboolean nsWindow::OnPropertyNotifyEvent(GtkWidget *aWidget, +- GdkEventProperty *aEvent) +- +-{ ++ GdkEventProperty *aEvent) { + if (aEvent->atom == gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE)) { + UpdateClientOffset(); + +@@ -1820,6 +1826,9 @@ gboolean nsWindow::OnExposeEvent(cairo_t + + // Windows that are not visible will be painted after they become visible. + if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel) return FALSE; +#ifdef MOZ_WAYLAND -+ // Window does not have visible wl_surface yet. -+ if (!mIsX11Display && !GetWaylandSurface()) -+ return FALSE; ++ if (mContainer && !mContainer->ready_to_draw) return FALSE; +#endif -+ - nsIWidgetListener *listener = GetListener(); - if (!listener) - return FALSE; -@@ -3318,6 +3335,33 @@ nsWindow::OnWindowStateEvent(GtkWidget * - } - // else the widget is a shell widget. -+ // The block below is a bit evil. -+ // -+ // When a window is resized before it is shown, gtk_window_resize() delays -+ // resizes until the window is shown. If gtk_window_state_event() sees a -+ // GDK_WINDOW_STATE_MAXIMIZED change [1] before the window is shown, then -+ // gtk_window_compute_configure_request_size() ignores the values from the -+ // resize [2]. See bug 1449166 for an example of how this could happen. -+ // -+ // [1] https://gitlab.gnome.org/GNOME/gtk/blob/3.22.30/gtk/gtkwindow.c#L7967 -+ // [2] https://gitlab.gnome.org/GNOME/gtk/blob/3.22.30/gtk/gtkwindow.c#L9377 -+ // -+ // In order to provide a sensible size for the window when the user exits -+ // maximized state, we hide the GDK_WINDOW_STATE_MAXIMIZED change from -+ // gtk_window_state_event() so as to trick GTK into using the values from -+ // gtk_window_resize() in its configure request. -+ // -+ // We instead notify gtk_window_state_event() of the maximized state change -+ // once the window is shown. -+ if (!mIsShown) { -+ aEvent->changed_mask = static_cast -+ (aEvent->changed_mask & ~GDK_WINDOW_STATE_MAXIMIZED); -+ } else if (aEvent->changed_mask & GDK_WINDOW_STATE_WITHDRAWN && -+ aEvent->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) { -+ aEvent->changed_mask = static_cast -+ (aEvent->changed_mask | GDK_WINDOW_STATE_MAXIMIZED); -+ } + nsIWidgetListener *listener = GetListener(); + if (!listener) return FALSE; +@@ -3000,6 +3009,33 @@ void nsWindow::OnWindowStateEvent(GtkWid + } + // else the widget is a shell widget. + ++ // The block below is a bit evil. ++ // ++ // When a window is resized before it is shown, gtk_window_resize() delays ++ // resizes until the window is shown. If gtk_window_state_event() sees a ++ // GDK_WINDOW_STATE_MAXIMIZED change [1] before the window is shown, then ++ // gtk_window_compute_configure_request_size() ignores the values from the ++ // resize [2]. See bug 1449166 for an example of how this could happen. ++ // ++ // [1] https://gitlab.gnome.org/GNOME/gtk/blob/3.22.30/gtk/gtkwindow.c#L7967 ++ // [2] https://gitlab.gnome.org/GNOME/gtk/blob/3.22.30/gtk/gtkwindow.c#L9377 ++ // ++ // In order to provide a sensible size for the window when the user exits ++ // maximized state, we hide the GDK_WINDOW_STATE_MAXIMIZED change from ++ // gtk_window_state_event() so as to trick GTK into using the values from ++ // gtk_window_resize() in its configure request. ++ // ++ // We instead notify gtk_window_state_event() of the maximized state change ++ // once the window is shown. ++ if (!mIsShown) { ++ aEvent->changed_mask = static_cast( ++ aEvent->changed_mask & ~GDK_WINDOW_STATE_MAXIMIZED); ++ } else if (aEvent->changed_mask & GDK_WINDOW_STATE_WITHDRAWN && ++ aEvent->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) { ++ aEvent->changed_mask = static_cast( ++ aEvent->changed_mask | GDK_WINDOW_STATE_MAXIMIZED); ++ } + - // We don't care about anything but changes in the maximized/icon/fullscreen - // states - if ((aEvent->changed_mask -@@ -3404,6 +3448,7 @@ nsWindow::OnDPIChanged() + // We don't care about anything but changes in the maximized/icon/fullscreen + // states + if ((aEvent->changed_mask & +@@ -3075,6 +3111,7 @@ void nsWindow::OnDPIChanged() { // Update menu's font size etc presShell->ThemeChanged(); } @@ -2670,416 +2925,303 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } } -@@ -3611,6 +3656,7 @@ nsWindow::Create(nsIWidget* aParent, - nsWindow *parentnsWindow = nullptr; - GtkWidget *eventWidget = nullptr; - bool drawToContainer = false; -+ bool useAlphaVisual = false; +@@ -3443,13 +3480,15 @@ nsresult nsWindow::Create(nsIWidget *aPa + gtk_style_context_has_class(style, "csd"); + eventWidget = (drawToContainer) ? container : mShell; - if (aParent) { - parentnsWindow = static_cast(aParent); -@@ -3661,8 +3707,8 @@ nsWindow::Create(nsIWidget* aParent, - } - mShell = gtk_window_new(type); +- gtk_widget_add_events(eventWidget, kEvents); +- if (drawToContainer) +- gtk_widget_add_events(mShell, GDK_PROPERTY_CHANGE_MASK); +- + // Prevent GtkWindow from painting a background to avoid flickering. + gtk_widget_set_app_paintable(eventWidget, TRUE); -- bool useAlphaVisual = (mWindowType == eWindowType_popup && -- aInitData->mSupportTranslucency); -+ useAlphaVisual = (mWindowType == eWindowType_popup && -+ aInitData->mSupportTranslucency); ++ gtk_widget_add_events(eventWidget, kEvents); ++ if (drawToContainer) { ++ gtk_widget_add_events(mShell, GDK_PROPERTY_CHANGE_MASK); ++ gtk_widget_set_app_paintable(mShell, TRUE); ++ } ++ + // If we draw to mContainer window then configure it now because + // gtk_container_add() realizes the child widget. + gtk_widget_set_has_window(container, drawToContainer); +@@ -3698,6 +3737,15 @@ nsresult nsWindow::Create(nsIWidget *aPa + mXDepth = gdk_visual_get_depth(gdkVisual); - // 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); - -- /* There are two cases here: -+ /* There are several cases here: - * - * 1) We're running on Gtk+ without client side decorations. - * Content is rendered to mShell window and we listen -@@ -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. -- if (mIsX11Display) { -- gulong value = 2; // Opt out of unredirection -- GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL); -- gdk_property_change(gtk_widget_get_window(mShell), -- gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE), -- cardinal_atom, -- 32, // format -- GDK_PROP_MODE_REPLACE, -- (guchar*)&value, -- 1); -- } -+ SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED); - #endif - } - break; -@@ -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", -- G_CALLBACK(theme_changed_cb), this); -+ G_CALLBACK(settings_changed_cb), this); - g_signal_connect_after(default_settings, - "notify::gtk-font-name", -- G_CALLBACK(theme_changed_cb), this); -+ G_CALLBACK(settings_changed_cb), this); -+ g_signal_connect_after(default_settings, -+ "notify::gtk-enable-animations", -+ G_CALLBACK(settings_changed_cb), this); - } - - if (mContainer) { -@@ -4083,60 +4122,70 @@ nsWindow::Create(nsIWidget* aParent, + mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth); ++ ++ if (mIsTopLevel) { ++ // Set window manager hint to keep fullscreen windows composited. ++ // ++ // If the window were to get unredirected, there could be visible ++ // tearing because Gecko does not align its framebuffer updates with ++ // vblank. ++ SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED); ++ } + } + #ifdef MOZ_WAYLAND + else if (!mIsX11Display) { +@@ -3708,12 +3756,37 @@ nsresult nsWindow::Create(nsIWidget *aPa + return NS_OK; } - void --nsWindow::SetWindowClass(const nsAString &xulWinType) -+nsWindow::RefreshWindowClass(void) - { -- if (!mShell) -- return; -+ if (mGtkWindowTypeName.IsEmpty() || mGtkWindowRoleName.IsEmpty()) -+ return; - -- const char *res_class = gdk_get_program_class(); -- if (!res_class) -- return; -+ GdkWindow* gdkWindow = gtk_widget_get_window(mShell); -+ gdk_window_set_role(gdkWindow, mGtkWindowRoleName.get()); - -- char *res_name = ToNewCString(xulWinType); -- if (!res_name) -- return; ++void nsWindow::RefreshWindowClass(void) { ++ if (mGtkWindowTypeName.IsEmpty() || mGtkWindowRoleName.IsEmpty()) return; ++ ++ GdkWindow *gdkWindow = gtk_widget_get_window(mShell); ++ gdk_window_set_role(gdkWindow, mGtkWindowRoleName.get()); ++ +#ifdef MOZ_X11 -+ if (mIsX11Display) { -+ XClassHint *class_hint = XAllocClassHint(); -+ if (!class_hint) { -+ return; -+ } -+ const char *res_class = gdk_get_program_class(); -+ if (!res_class) -+ return; -+ -+ class_hint->res_name = const_cast(mGtkWindowTypeName.get()); -+ class_hint->res_class = const_cast(res_class); -+ -+ // Can't use gtk_window_set_wmclass() for this; it prints -+ // a warning & refuses to make the change. -+ GdkDisplay *display = gdk_display_get_default(); -+ XSetClassHint(GDK_DISPLAY_XDISPLAY(display), -+ gdk_x11_window_get_xid(gdkWindow), -+ class_hint); -+ XFree(class_hint); ++ if (mIsX11Display) { ++ XClassHint *class_hint = XAllocClassHint(); ++ if (!class_hint) { ++ return; + } ++ const char *res_class = gdk_get_program_class(); ++ if (!res_class) return; ++ ++ class_hint->res_name = const_cast(mGtkWindowTypeName.get()); ++ class_hint->res_class = const_cast(res_class); ++ ++ // Can't use gtk_window_set_wmclass() for this; it prints ++ // a warning & refuses to make the change. ++ GdkDisplay *display = gdk_display_get_default(); ++ XSetClassHint(GDK_DISPLAY_XDISPLAY(display), ++ gdk_x11_window_get_xid(gdkWindow), class_hint); ++ XFree(class_hint); ++ } +#endif /* MOZ_X11 */ +} ++ + void nsWindow::SetWindowClass(const nsAString &xulWinType) { + if (!mShell) return; -- const char *role = nullptr; -+void -+nsWindow::SetWindowClass(const nsAString &xulWinType) -+{ -+ if (!mShell) -+ return; +- const char *res_class = gdk_get_program_class(); +- if (!res_class) return; +- + char *res_name = ToNewCString(xulWinType); + if (!res_name) return; -- // Parse res_name into a name and role. Characters other than -- // [A-Za-z0-9_-] are converted to '_'. Anything after the first -- // colon is assigned to role; if there's no colon, assign the -- // whole thing to both role and res_name. -- for (char *c = res_name; *c; c++) { -- if (':' == *c) { -- *c = 0; -- role = c + 1; -- } -- else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c))) -- *c = '_'; -- } -- res_name[0] = toupper(res_name[0]); -- if (!role) role = res_name; -+ char *res_name = ToNewCString(xulWinType); -+ if (!res_name) -+ return; +@@ -3733,29 +3806,11 @@ void nsWindow::SetWindowClass(const nsAS + res_name[0] = toupper(res_name[0]); + if (!role) role = res_name; -- GdkWindow* gdkWindow = gtk_widget_get_window(mShell); +- GdkWindow *gdkWindow = gtk_widget_get_window(mShell); - gdk_window_set_role(gdkWindow, role); -+ const char *role = nullptr; - +- -#ifdef MOZ_X11 - if (mIsX11Display) { -- XClassHint *class_hint = XAllocClassHint(); -- if (!class_hint) { -- free(res_name); -- return; -+ // Parse res_name into a name and role. Characters other than -+ // [A-Za-z0-9_-] are converted to '_'. Anything after the first -+ // colon is assigned to role; if there's no colon, assign the -+ // whole thing to both role and res_name. -+ for (char *c = res_name; *c; c++) { -+ if (':' == *c) { -+ *c = 0; -+ role = c + 1; - } -- class_hint->res_name = res_name; -- class_hint->res_class = const_cast(res_class); -+ else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c))) -+ *c = '_'; -+ } -+ res_name[0] = toupper(res_name[0]); -+ if (!role) role = res_name; - -- // Can't use gtk_window_set_wmclass() for this; it prints -- // a warning & refuses to make the change. -- GdkDisplay *display = gdk_display_get_default(); -- XSetClassHint(GDK_DISPLAY_XDISPLAY(display), -- gdk_x11_window_get_xid(gdkWindow), -- class_hint); -- XFree(class_hint); +- XClassHint *class_hint = XAllocClassHint(); +- if (!class_hint) { +- free(res_name); +- return; +- } +- class_hint->res_name = res_name; +- class_hint->res_class = const_cast(res_class); +- +- // Can't use gtk_window_set_wmclass() for this; it prints +- // a warning & refuses to make the change. +- GdkDisplay *display = gdk_display_get_default(); +- XSetClassHint(GDK_DISPLAY_XDISPLAY(display), +- gdk_x11_window_get_xid(gdkWindow), class_hint); +- XFree(class_hint); - } -#endif /* MOZ_X11 */ -+ mGtkWindowTypeName = res_name; -+ mGtkWindowRoleName = role; -+ free(res_name); - -- free(res_name); -+ RefreshWindowClass(); - } - - void -@@ -4162,6 +4211,8 @@ nsWindow::NativeResize() - size.width, size.height)); - - if (mIsTopLevel) { -+ MOZ_ASSERT(size.width > 0 && size.height > 0, -+ "Can't resize window smaller than 1x1."); - gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height); - } - else if (mContainer) { -@@ -4207,6 +4258,8 @@ nsWindow::NativeMoveResize() - NativeShow(false); - } - NativeMove(); -+ -+ return; - } - - GdkRectangle size = DevicePixelsToGdkSizeRoundUp(mBounds.Size()); -@@ -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. -+ MOZ_ASSERT(size.width > 0 && size.height > 0, -+ "Can't resize window smaller than 1x1."); - gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height); - } - else if (mContainer) { -@@ -4271,6 +4326,16 @@ nsWindow::NativeShow(bool aAction) - } - } - else { -+#ifdef MOZ_WAYLAND -+ if (mContainer && moz_container_has_wl_egl_window(mContainer)) { -+ // Because wl_egl_window is destroyed on moz_container_unmap(), -+ // the current compositor cannot use it anymore. To avoid crash, -+ // destroy the compositor & recreate a new compositor on next -+ // expose event. -+ DestroyLayerManager(); -+ } -+#endif -+ - if (mIsTopLevel) { - // Workaround window freezes on GTK versions before 3.21.2 by - // ensuring that configure events get dispatched to windows before -@@ -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); -+ MOZ_ASSERT(monitorRect.width > 0 && monitorRect.height > 0, -+ "Can't resize window smaller than 1x1."); - gtk_window_resize(gtkWin, monitorRect.width, monitorRect.height); - - GdkColor bgColor; -@@ -5951,7 +6018,7 @@ window_state_event_cb (GtkWidget *widget - } - - static void --theme_changed_cb (GtkSettings *settings, GParamSpec *pspec, nsWindow *data) -+settings_changed_cb (GtkSettings *settings, GParamSpec *pspec, nsWindow *data) - { - RefPtr window = data; - window->ThemeChanged(); -@@ -6032,13 +6099,13 @@ nsWindow::InitDragEvent(WidgetDragEvent - KeymapWrapper::InitInputEvent(aEvent, modifierState); - } - --static gboolean --drag_motion_event_cb(GtkWidget *aWidget, -- GdkDragContext *aDragContext, -- gint aX, -- gint aY, -- guint aTime, -- gpointer aData) -+gboolean -+WindowDragMotionHandler(GtkWidget *aWidget, -+ GdkDragContext *aDragContext, -+ nsWaylandDragContext *aWaylandDragContext, -+ gint aX, -+ gint aY, -+ guint aTime) - { - RefPtr window = get_window_for_gtk_widget(aWidget); - if (!window) -@@ -6063,15 +6130,24 @@ drag_motion_event_cb(GtkWidget *aWidget, - - RefPtr dragService = nsDragService::GetInstance(); - return dragService-> -- ScheduleMotionEvent(innerMostWindow, aDragContext, -+ ScheduleMotionEvent(innerMostWindow, aDragContext, aWaylandDragContext, - point, aTime); - } - --static void --drag_leave_event_cb(GtkWidget *aWidget, -- GdkDragContext *aDragContext, -- guint aTime, -- gpointer aData) -+static gboolean -+drag_motion_event_cb(GtkWidget *aWidget, -+ GdkDragContext *aDragContext, -+ gint aX, -+ gint aY, -+ guint aTime, -+ gpointer aData) -+{ -+ return WindowDragMotionHandler(aWidget, aDragContext, nullptr, -+ aX, aY, aTime); -+} -+ -+void -+WindowDragLeaveHandler(GtkWidget *aWidget) - { - RefPtr window = get_window_for_gtk_widget(aWidget); - if (!window) -@@ -6104,14 +6180,22 @@ drag_leave_event_cb(GtkWidget *aWidget, - dragService->ScheduleLeaveEvent(); - } - -+static void -+drag_leave_event_cb(GtkWidget *aWidget, -+ GdkDragContext *aDragContext, -+ guint aTime, -+ gpointer aData) -+{ -+ WindowDragLeaveHandler(aWidget); -+} - --static gboolean --drag_drop_event_cb(GtkWidget *aWidget, -- GdkDragContext *aDragContext, -- gint aX, -- gint aY, -- guint aTime, -- gpointer aData) -+gboolean -+WindowDragDropHandler(GtkWidget *aWidget, -+ GdkDragContext *aDragContext, -+ nsWaylandDragContext *aWaylandDragContext, -+ gint aX, -+ gint aY, -+ guint aTime) - { - RefPtr window = get_window_for_gtk_widget(aWidget); - if (!window) -@@ -6136,10 +6220,21 @@ drag_drop_event_cb(GtkWidget *aWidget, - - RefPtr dragService = nsDragService::GetInstance(); - return dragService-> -- ScheduleDropEvent(innerMostWindow, aDragContext, -+ ScheduleDropEvent(innerMostWindow, aDragContext, aWaylandDragContext, - point, aTime); - } - -+static gboolean -+drag_drop_event_cb(GtkWidget *aWidget, -+ GdkDragContext *aDragContext, -+ gint aX, -+ gint aY, -+ guint aTime, -+ gpointer aData) -+{ -+ return WindowDragDropHandler(aWidget, aDragContext, nullptr, aX, aY, aTime); -+} -+ - static void - drag_data_received_event_cb(GtkWidget *aWidget, - GdkDragContext *aDragContext, -@@ -6554,12 +6649,6 @@ nsWindow::GetLayerManager(PLayerTransact - return mLayerManager; - } - -- if (!mLayerManager && !IsComposited() && -- eTransparencyTransparent == GetTransparencyMode()) -- { -- mLayerManager = CreateBasicLayerManager(); -- } - - return nsBaseWidget::GetLayerManager(aShadowManager, aBackendHint, aPersistence); ++ mGtkWindowTypeName = res_name; ++ mGtkWindowRoleName = role; + free(res_name); ++ ++ RefreshWindowClass(); } -@@ -6601,6 +6690,13 @@ nsWindow::ClearCachedResources() - void - nsWindow::UpdateClientOffsetForCSDWindow() - { -+ // We update window offset on X11 as the window position is calculated -+ // relatively to mShell. We don't do that on Wayland as our wl_subsurface -+ // is attached to mContainer and mShell is ignored. -+ if (!mIsX11Display) { -+ return; -+ } + void nsWindow::NativeResize() { +@@ -3820,6 +3875,8 @@ void nsWindow::NativeMoveResize() { + NativeShow(false); + } + NativeMove(); + - // _NET_FRAME_EXTENTS is not set on client decorated windows, - // so we need to read offset between mContainer and toplevel mShell - // window. -@@ -6692,6 +6788,15 @@ nsWindow::SetDrawsInTitlebar(bool aState - mNeedsShow = true; - NativeResize(); ++ return; + } -+ // Label mShell toplevel window so property_notify_event_cb callback -+ // can find its way home. -+ g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)), -+ "nsWindow", this); -+#ifdef MOZ_X11 -+ SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED); + GdkRectangle size = DevicePixelsToGdkSizeRoundUp(mBounds.Size()); +@@ -3832,6 +3889,8 @@ void 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. ++ MOZ_ASSERT(size.width > 0 && size.height > 0, ++ "Can't resize window smaller than 1x1."); + gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height); + } else if (mContainer) { + GtkAllocation allocation; +@@ -3877,6 +3936,16 @@ void nsWindow::NativeShow(bool aAction) + gdk_window_show_unraised(mGdkWindow); + } + } else { ++#ifdef MOZ_WAYLAND ++ if (mContainer && moz_container_has_wl_egl_window(mContainer)) { ++ // Because wl_egl_window is destroyed on moz_container_unmap(), ++ // the current compositor cannot use it anymore. To avoid crash, ++ // destroy the compositor & recreate a new compositor on next ++ // expose event. ++ DestroyLayerManager(); ++ } +#endif -+ RefreshWindowClass(); + - // 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 +7103,8 @@ nsWindow::GetSystemCSDSupportLevel() { - // KDE Plasma - } else if (strstr(currentDesktop, "KDE") != nullptr) { - sCSDSupportLevel = CSD_SUPPORT_CLIENT; -+ } else if (strstr(currentDesktop, "Enlightenment") != nullptr) { -+ sCSDSupportLevel = CSD_SUPPORT_CLIENT; - } else if (strstr(currentDesktop, "LXDE") != nullptr) { - sCSDSupportLevel = CSD_SUPPORT_CLIENT; - } else if (strstr(currentDesktop, "openbox") != nullptr) { -@@ -7014,6 +7121,8 @@ nsWindow::GetSystemCSDSupportLevel() { - sCSDSupportLevel = CSD_SUPPORT_SYSTEM; - } else if (strstr(currentDesktop, "LXQt") != nullptr) { - sCSDSupportLevel = CSD_SUPPORT_SYSTEM; -+ } else if (strstr(currentDesktop, "Deepin") != nullptr) { -+ sCSDSupportLevel = CSD_SUPPORT_SYSTEM; - } else { + if (mIsTopLevel) { + // Workaround window freezes on GTK versions before 3.21.2 by + // ensuring that configure events get dispatched to windows before +@@ -5436,9 +5505,10 @@ void nsWindow::InitDragEvent(WidgetDragE + KeymapWrapper::InitInputEvent(aEvent, modifierState); + } + +-static gboolean drag_motion_event_cb(GtkWidget *aWidget, +- GdkDragContext *aDragContext, gint aX, +- gint aY, guint aTime, gpointer aData) { ++gboolean WindowDragMotionHandler(GtkWidget *aWidget, ++ GdkDragContext *aDragContext, ++ nsWaylandDragContext *aWaylandDragContext, ++ gint aX, gint aY, guint aTime) { + RefPtr window = get_window_for_gtk_widget(aWidget); + if (!window) return FALSE; + +@@ -5459,13 +5529,17 @@ static gboolean drag_motion_event_cb(Gtk + LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({retx, rety}); + + RefPtr dragService = nsDragService::GetInstance(); +- return dragService->ScheduleMotionEvent(innerMostWindow, aDragContext, point, +- aTime); ++ return dragService->ScheduleMotionEvent(innerMostWindow, aDragContext, ++ aWaylandDragContext, point, aTime); + } + +-static void drag_leave_event_cb(GtkWidget *aWidget, +- GdkDragContext *aDragContext, guint aTime, +- gpointer aData) { ++static gboolean drag_motion_event_cb(GtkWidget *aWidget, ++ GdkDragContext *aDragContext, gint aX, ++ gint aY, guint aTime, gpointer aData) { ++ return WindowDragMotionHandler(aWidget, aDragContext, nullptr, aX, aY, aTime); ++} ++ ++void WindowDragLeaveHandler(GtkWidget *aWidget) { + RefPtr window = get_window_for_gtk_widget(aWidget); + if (!window) return; + +@@ -5495,9 +5569,15 @@ static void drag_leave_event_cb(GtkWidge + dragService->ScheduleLeaveEvent(); + } + +-static gboolean drag_drop_event_cb(GtkWidget *aWidget, +- GdkDragContext *aDragContext, gint aX, +- gint aY, guint aTime, gpointer aData) { ++static void drag_leave_event_cb(GtkWidget *aWidget, ++ GdkDragContext *aDragContext, guint aTime, ++ gpointer aData) { ++ WindowDragLeaveHandler(aWidget); ++} ++ ++gboolean WindowDragDropHandler(GtkWidget *aWidget, GdkDragContext *aDragContext, ++ nsWaylandDragContext *aWaylandDragContext, ++ gint aX, gint aY, guint aTime) { + RefPtr window = get_window_for_gtk_widget(aWidget); + if (!window) return FALSE; + +@@ -5518,8 +5598,14 @@ static gboolean drag_drop_event_cb(GtkWi + LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({retx, rety}); + + RefPtr dragService = nsDragService::GetInstance(); +- return dragService->ScheduleDropEvent(innerMostWindow, aDragContext, point, +- aTime); ++ return dragService->ScheduleDropEvent(innerMostWindow, aDragContext, ++ aWaylandDragContext, point, aTime); ++} ++ ++static gboolean drag_drop_event_cb(GtkWidget *aWidget, ++ GdkDragContext *aDragContext, gint aX, ++ gint aY, guint aTime, gpointer aData) { ++ return WindowDragDropHandler(aWidget, aDragContext, nullptr, aX, aY, aTime); + } + + static void drag_data_received_event_cb(GtkWidget *aWidget, +@@ -5877,11 +5963,6 @@ nsIWidget::LayerManager *nsWindow::GetLa + return mLayerManager; + } + +- if (!mLayerManager && !IsComposited() && +- eTransparencyTransparent == GetTransparencyMode()) { +- mLayerManager = CreateBasicLayerManager(); +- } +- + return nsBaseWidget::GetLayerManager(aShadowManager, aBackendHint, + aPersistence); + } +@@ -5919,6 +6000,13 @@ void nsWindow::ClearCachedResources() { + * It works only for CSD decorated GtkWindow. + */ + void nsWindow::UpdateClientOffsetForCSDWindow() { ++ // We update window offset on X11 as the window position is calculated ++ // relatively to mShell. We don't do that on Wayland as our wl_subsurface ++ // is attached to mContainer and mShell is ignored. ++ if (!mIsX11Display) { ++ return; ++ } ++ + // _NET_FRAME_EXTENTS is not set on client decorated windows, + // so we need to read offset between mContainer and toplevel mShell + // window. +@@ -6005,6 +6093,15 @@ void nsWindow::SetDrawsInTitlebar(bool a + mNeedsShow = true; + NativeResize(); + ++ // Label mShell toplevel window so property_notify_event_cb callback ++ // can find its way home. ++ g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)), "nsWindow", ++ this); ++#ifdef MOZ_X11 ++ SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED); ++#endif ++ RefreshWindowClass(); ++ + // 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. +@@ -6019,13 +6116,11 @@ void nsWindow::SetDrawsInTitlebar(bool a + } + + gint nsWindow::GdkScaleFactor() { +-#if (MOZ_WIDGET_GTK >= 3) + // Available as of GTK 3.10+ + static auto sGdkWindowGetScaleFactorPtr = + (gint(*)(GdkWindow *))dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor"); + if (sGdkWindowGetScaleFactorPtr && mGdkWindow) + return (*sGdkWindowGetScaleFactorPtr)(mGdkWindow); +-#endif + return ScreenHelperGTK::GetGTKMonitorScaleFactor(); + } + +@@ -6287,6 +6382,8 @@ nsWindow::CSDSupportLevel nsWindow::GetS + // KDE Plasma + } else if (strstr(currentDesktop, "KDE") != nullptr) { + sCSDSupportLevel = CSD_SUPPORT_CLIENT; ++ } else if (strstr(currentDesktop, "Enlightenment") != nullptr) { ++ sCSDSupportLevel = CSD_SUPPORT_CLIENT; + } else if (strstr(currentDesktop, "LXDE") != nullptr) { + sCSDSupportLevel = CSD_SUPPORT_CLIENT; + } else if (strstr(currentDesktop, "openbox") != nullptr) { +@@ -6303,6 +6400,8 @@ nsWindow::CSDSupportLevel nsWindow::GetS + sCSDSupportLevel = CSD_SUPPORT_SYSTEM; + } else if (strstr(currentDesktop, "LXQt") != nullptr) { + sCSDSupportLevel = CSD_SUPPORT_SYSTEM; ++ } else if (strstr(currentDesktop, "Deepin") != nullptr) { ++ sCSDSupportLevel = CSD_SUPPORT_SYSTEM; + } else { // Release or beta builds are not supposed to be broken // so disable titlebar rendering on untested/unknown systems. -@@ -7066,26 +7175,18 @@ nsWindow::RoundsWidgetCoordinatesTo() +@@ -6351,34 +6450,19 @@ int32_t nsWindow::RoundsWidgetCoordinate - void nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) - { + void nsWindow::GetCompositorWidgetInitData( + mozilla::widget::CompositorWidgetInitData *aInitData) { + // Make sure the window XID is propagated to X server, we can fail otherwise + // in GPU process (Bug 1401634). + if (mXDisplay && mXWindow != X11None) { @@ -3087,31 +3229,50 @@ 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(), - GetClientSize()); + (mXWindow != X11None) ? mXWindow : (uintptr_t) nullptr, + mXDisplay ? nsCString(XDisplayString(mXDisplay)) : nsCString(), + GetClientSize()); } --bool --nsWindow::IsComposited() const --{ +-bool nsWindow::IsComposited() const { - if (!mGdkWindow) { - NS_WARNING("nsWindow::HasARGBVisual called before realization!"); - return false; - } - -- GdkScreen* gdkScreen = gdk_screen_get_default(); +- GdkScreen *gdkScreen = gdk_screen_get_default(); - return gdk_screen_is_composited(gdkScreen) && -- (gdk_window_get_visual(mGdkWindow) -- == gdk_screen_get_rgba_visual(gdkScreen)); +- (gdk_window_get_visual(mGdkWindow) == +- gdk_screen_get_rgba_visual(gdkScreen)); -} - #ifdef MOZ_WAYLAND - wl_display* - nsWindow::GetWaylandDisplay() -@@ -7110,3 +7211,85 @@ nsWindow::GetWaylandSurface() +-wl_display *nsWindow::GetWaylandDisplay() { +- // Available as of GTK 3.8+ +- static auto sGdkWaylandDisplayGetWlDisplay = (wl_display * (*)(GdkDisplay *)) +- dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display"); +- +- GdkDisplay *gdkDisplay = gdk_display_get_default(); +- return mIsX11Display ? nullptr : sGdkWaylandDisplayGetWlDisplay(gdkDisplay); +-} +- + wl_surface *nsWindow::GetWaylandSurface() { + if (mContainer) + return moz_container_get_wl_surface(MOZ_CONTAINER(mContainer)); +@@ -6388,4 +6472,80 @@ wl_surface *nsWindow::GetWaylandSurface( + "drawing!"); return nullptr; } ++ ++bool nsWindow::WaylandSurfaceNeedsClear() { ++ if (mContainer) { ++ return moz_container_surface_needs_clear(MOZ_CONTAINER(mContainer)); ++ } ++ ++ NS_WARNING( ++ "nsWindow::WaylandSurfaceNeedsClear(): We don't have any mContainer!"); ++ return false; ++} #endif + +#ifdef MOZ_X11 @@ -3126,38 +3287,26 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w + * for further details. + */ + -+#define PROGRESS_HINT "_NET_WM_XAPP_PROGRESS" ++#define PROGRESS_HINT "_NET_WM_XAPP_PROGRESS" + -+static void -+set_window_hint_cardinal (Window xid, -+ const gchar *atom_name, -+ gulong cardinal) -+{ ++static void set_window_hint_cardinal(Window xid, const gchar *atom_name, ++ gulong cardinal) { + GdkDisplay *display; + -+ display = gdk_display_get_default (); ++ display = gdk_display_get_default(); + -+ if (cardinal > 0) -+ { -+ XChangeProperty (GDK_DISPLAY_XDISPLAY (display), -+ xid, -+ gdk_x11_get_xatom_by_name_for_display (display, atom_name), -+ XA_CARDINAL, 32, -+ PropModeReplace, -+ (guchar *) &cardinal, 1); -+ } -+ else -+ { -+ XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), -+ xid, -+ gdk_x11_get_xatom_by_name_for_display (display, atom_name)); ++ if (cardinal > 0) { ++ XChangeProperty(GDK_DISPLAY_XDISPLAY(display), xid, ++ gdk_x11_get_xatom_by_name_for_display(display, atom_name), ++ XA_CARDINAL, 32, PropModeReplace, (guchar *)&cardinal, 1); ++ } else { ++ XDeleteProperty(GDK_DISPLAY_XDISPLAY(display), xid, ++ gdk_x11_get_xatom_by_name_for_display(display, atom_name)); + } +} -+#endif // MOZ_X11 ++#endif // MOZ_X11 + -+void -+nsWindow::SetProgress(unsigned long progressPercent) -+{ ++void nsWindow::SetProgress(unsigned long progressPercent) { +#ifdef MOZ_X11 + + if (!mIsX11Display) { @@ -3171,200 +3320,533 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w + progressPercent = MIN(progressPercent, 100); + + set_window_hint_cardinal(GDK_WINDOW_XID(gtk_widget_get_window(mShell)), -+ PROGRESS_HINT, -+ progressPercent); -+#endif // MOZ_X11 ++ PROGRESS_HINT, progressPercent); ++#endif // MOZ_X11 +} + +#ifdef MOZ_X11 -+void -+nsWindow::SetCompositorHint(WindowComposeRequest aState) -+{ -+ if (mIsX11Display) { -+ gulong value = aState; -+ GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL); -+ gdk_property_change(gtk_widget_get_window(mShell), -+ gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE), -+ cardinal_atom, -+ 32, // format -+ GDK_PROP_MODE_REPLACE, -+ (guchar*)&value, -+ 1); -+ } ++void nsWindow::SetCompositorHint(WindowComposeRequest aState) { ++ if (mIsX11Display && ++ (!GetLayerManager() || ++ GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC)) { ++ gulong value = aState; ++ GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL); ++ gdk_property_change(gtk_widget_get_window(mShell), ++ gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE), ++ cardinal_atom, ++ 32, // format ++ GDK_PROP_MODE_REPLACE, (guchar *)&value, 1); ++ } +} +#endif + -+ -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-21 13:42:00.762025644 +0100 -@@ -66,6 +66,21 @@ extern mozilla::LazyLogModule gWidgetDra +diff -up thunderbird-60.5.0/widget/gtk/nsWindow.h.wayland thunderbird-60.5.0/widget/gtk/nsWindow.h +--- thunderbird-60.5.0/widget/gtk/nsWindow.h.wayland 2019-01-22 20:44:03.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/nsWindow.h 2019-02-05 14:26:16.978316639 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* This Source Code Form is subject to the terms of the Mozilla Public +@@ -8,19 +8,8 @@ + #ifndef __nsWindow_h__ + #define __nsWindow_h__ + +-#include "mozcontainer.h" +-#include "mozilla/RefPtr.h" +-#include "mozilla/UniquePtr.h" +-#include "nsIDragService.h" +-#include "nsITimer.h" +-#include "nsGkAtoms.h" +-#include "nsRefPtrHashtable.h" +- +-#include "nsBaseWidget.h" +-#include "CompositorWidget.h" + #include + #include +- + #ifdef MOZ_X11 + #include + #include "X11UndefineNone.h" +@@ -28,7 +17,16 @@ + #ifdef MOZ_WAYLAND + #include + #endif +- ++#include "mozcontainer.h" ++#include "mozilla/RefPtr.h" ++#include "mozilla/UniquePtr.h" ++#include "nsIDragService.h" ++#include "nsITimer.h" ++#include "nsGkAtoms.h" ++#include "nsRefPtrHashtable.h" ++#include "nsIFrame.h" ++#include "nsBaseWidget.h" ++#include "CompositorWidget.h" + #include "mozilla/widget/WindowSurface.h" + #include "mozilla/widget/WindowSurfaceProvider.h" + +@@ -66,6 +64,19 @@ extern mozilla::LazyLogModule gWidgetDra #endif /* MOZ_LOGGING */ +#ifdef MOZ_WAYLAND +class nsWaylandDragContext; + -+gboolean -+WindowDragMotionHandler(GtkWidget *aWidget, GdkDragContext *aDragContext, -+ nsWaylandDragContext *aWaylandDragContext, -+ gint aX, gint aY, guint aTime); -+gboolean -+WindowDragDropHandler(GtkWidget *aWidget, GdkDragContext *aDragContext, -+ nsWaylandDragContext *aWaylandDragContext, gint aX, gint aY, -+ guint aTime); -+void -+WindowDragLeaveHandler(GtkWidget *aWidget); ++gboolean WindowDragMotionHandler(GtkWidget* aWidget, ++ GdkDragContext* aDragContext, ++ nsWaylandDragContext* aWaylandDragContext, ++ gint aX, gint aY, guint aTime); ++gboolean WindowDragDropHandler(GtkWidget* aWidget, GdkDragContext* aDragContext, ++ nsWaylandDragContext* aWaylandDragContext, ++ gint aX, gint aY, guint aTime); ++void WindowDragLeaveHandler(GtkWidget* aWidget); +#endif + class gfxPattern; namespace mozilla { -@@ -78,6 +93,7 @@ class nsWindow final : public nsBaseWidg - public: - typedef mozilla::gfx::DrawTarget DrawTarget; - typedef mozilla::WidgetEventTime WidgetEventTime; -+ typedef mozilla::WidgetKeyboardEvent WidgetKeyboardEvent; - typedef mozilla::widget::PlatformCompositorWidgetDelegate PlatformCompositorWidgetDelegate; +@@ -77,6 +88,7 @@ class nsWindow final : public nsBaseWidg + public: + typedef mozilla::gfx::DrawTarget DrawTarget; + typedef mozilla::WidgetEventTime WidgetEventTime; ++ typedef mozilla::WidgetKeyboardEvent WidgetKeyboardEvent; + typedef mozilla::widget::PlatformCompositorWidgetDelegate + PlatformCompositorWidgetDelegate; - nsWindow(); -@@ -115,8 +131,7 @@ public: - int32_t *aX, - int32_t *aY) override; - virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override; -- virtual void Move(double aX, -- double aY) override; -+ virtual void Move(double aX, double aY) override; - virtual void Show (bool aState) override; - virtual void Resize (double aWidth, - double aHeight, -@@ -228,6 +243,8 @@ public: - virtual void EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget, - LayoutDeviceIntRegion& aInvalidRegion) override; +@@ -216,6 +228,8 @@ class nsWindow final : public nsBaseWidg + mozilla::gfx::DrawTarget* aDrawTarget, + LayoutDeviceIntRegion& aInvalidRegion) override; -+ void SetProgress(unsigned long progressPercent); ++ void SetProgress(unsigned long progressPercent); + - private: - void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface, nsIntRect aBoundsRect); + private: + void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface, + nsIntRect aBoundsRect); +@@ -335,6 +349,7 @@ class nsWindow final : public nsBaseWidg + #ifdef MOZ_WAYLAND + wl_display* GetWaylandDisplay(); + wl_surface* GetWaylandSurface(); ++ bool WaylandSurfaceNeedsClear(); + #endif + virtual void GetCompositorWidgetInitData( + mozilla::widget::CompositorWidgetInitData* aInitData) override; +@@ -436,13 +451,23 @@ class nsWindow final : public nsBaseWidg + gint* aButton, gint* aRootX, gint* aRootY); + void ClearCachedResources(); + nsIWidgetListener* GetListener(); +- bool IsComposited() const; -@@ -452,13 +469,24 @@ private: - gint* aRootX, gint* aRootY); - void ClearCachedResources(); - nsIWidgetListener* GetListener(); -- bool IsComposited() const; + void UpdateClientOffsetForCSDWindow(); - void UpdateClientOffsetForCSDWindow(); - - nsWindow* GetTransientForWindowIfPopup(); - bool IsHandlingTouchSequence(GdkEventSequence* aSequence); + nsWindow* GetTransientForWindowIfPopup(); + bool IsHandlingTouchSequence(GdkEventSequence* aSequence); +#ifdef MOZ_X11 -+ typedef enum { GTK_WIDGET_COMPOSIDED_DEFAULT = 0, -+ GTK_WIDGET_COMPOSIDED_DISABLED = 1, -+ GTK_WIDGET_COMPOSIDED_ENABLED = 2 -+ } WindowComposeRequest; ++ typedef enum {GTK_WIDGET_COMPOSIDED_DEFAULT = 0, ++ GTK_WIDGET_COMPOSIDED_DISABLED = 1, ++ GTK_WIDGET_COMPOSIDED_ENABLED = 2} WindowComposeRequest; + -+ void SetCompositorHint(WindowComposeRequest aState); ++ void SetCompositorHint(WindowComposeRequest aState); +#endif -+ nsCString mGtkWindowTypeName; -+ nsCString mGtkWindowRoleName; -+ void RefreshWindowClass(); ++ nsCString mGtkWindowTypeName; ++ nsCString mGtkWindowRoleName; ++ void RefreshWindowClass(); + - GtkWidget *mShell; - MozContainer *mContainer; - GdkWindow *mGdkWindow; -@@ -558,6 +586,9 @@ private: - // full translucency at this time; each pixel is either fully opaque - // or fully transparent. - gchar* mTransparencyBitmap; -+ // True when we're on compositing window manager and this -+ // window is using visual with alpha channel. -+ bool mHasAlphaVisual; - - // all of our DND stuff - void InitDragEvent(mozilla::WidgetDragEvent& aEvent); -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-21 13:42:00.762025644 +0100 + GtkWidget* mShell; + MozContainer* mContainer; + GdkWindow* mGdkWindow; +diff -up thunderbird-60.5.0/widget/gtk/WindowSurfaceProvider.h.wayland thunderbird-60.5.0/widget/gtk/WindowSurfaceProvider.h +--- thunderbird-60.5.0/widget/gtk/WindowSurfaceProvider.h.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/WindowSurfaceProvider.h 2019-02-05 14:26:16.978316639 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -17,6 +17,7 @@ #include #endif - #include // for Window, Display, Visual, etc. + #include // for Window, Display, Visual, etc. +#include "X11UndefineNone.h" class nsWindow; -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-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); +@@ -70,6 +71,7 @@ class WindowSurfaceProvider final { + #ifdef MOZ_WAYLAND + nsWindow* mWidget; + #endif ++ bool mIsShaped; + }; + } // namespace widget +diff -up thunderbird-60.5.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderbird-60.5.0/widget/gtk/WindowSurfaceWayland.cpp +--- thunderbird-60.5.0/widget/gtk/WindowSurfaceWayland.cpp.wayland 2019-01-22 20:44:04.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/WindowSurfaceWayland.cpp 2019-02-05 14:26:16.979316635 +0100 +@@ -1,27 +1,28 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + ++#include "nsWaylandDisplay.h" + #include "WindowSurfaceWayland.h" + +-#include "base/message_loop.h" // for MessageLoop +-#include "base/task.h" // for NewRunnableMethod, etc + #include "nsPrintfCString.h" + #include "mozilla/gfx/2D.h" + #include "mozilla/gfx/Tools.h" + #include "gfxPlatform.h" + #include "mozcontainer.h" +-#include "nsCOMArray.h" +-#include "mozilla/StaticMutex.h" ++#include "nsTArray.h" ++#include "base/message_loop.h" // for MessageLoop ++#include "base/task.h" // for NewRunnableMethod, etc + +-#include + #include +-#include + #include + #include + ++namespace mozilla { ++namespace widget { ++ + /* + Wayland multi-thread rendering scheme + +@@ -131,188 +132,16 @@ handle to wayland compositor by WindowBa + (wl_buffer/wl_surface). + */ + +-namespace mozilla { +-namespace widget { +- + #define BUFFER_BPP 4 +- +-// TODO: How many rendering threads do we actualy handle? +-static nsCOMArray gWaylandDisplays; +-static StaticMutex gWaylandDisplaysMutex; +- +-// Each thread which is using wayland connection (wl_display) has to operate +-// its own wl_event_queue. Main Firefox thread wl_event_queue is handled +-// by Gtk main loop, other threads/wl_event_queue has to be handled by us. +-// +-// nsWaylandDisplay is our interface to wayland compositor. It provides wayland +-// global objects as we need (wl_display, wl_shm) and operates wl_event_queue on +-// compositor (not the main) thread. +-static nsWaylandDisplay *WaylandDisplayGet(wl_display *aDisplay); +-static void WaylandDisplayRelease(wl_display *aDisplay); +-static void WaylandDisplayLoop(wl_display *aDisplay); +- -// TODO: is the 60pfs loop correct? --#define EVENT_LOOP_DELAY (1000/60) -+// TODO: Bug 1467125 - We need to integrate wl_display_dispatch_queue_pending() with -+// compositor event loop. -+#define EVENT_LOOP_DELAY (1000/240) +-#define EVENT_LOOP_DELAY (1000 / 60) +- +-// Get WaylandDisplay for given wl_display and actual calling thread. +-static nsWaylandDisplay *WaylandDisplayGetLocked(wl_display *aDisplay, +- const StaticMutexAutoLock &) { +- nsWaylandDisplay *waylandDisplay = nullptr; +- +- int len = gWaylandDisplays.Count(); +- for (int i = 0; i < len; i++) { +- if (gWaylandDisplays[i]->Matches(aDisplay)) { +- waylandDisplay = gWaylandDisplays[i]; +- break; +- } +- } +- +- if (!waylandDisplay) { +- waylandDisplay = new nsWaylandDisplay(aDisplay); +- gWaylandDisplays.AppendObject(waylandDisplay); +- } +- +- NS_ADDREF(waylandDisplay); +- return waylandDisplay; +-} +- +-static nsWaylandDisplay *WaylandDisplayGet(wl_display *aDisplay) { +- StaticMutexAutoLock lock(gWaylandDisplaysMutex); +- return WaylandDisplayGetLocked(aDisplay, lock); +-} +- +-static bool WaylandDisplayReleaseLocked(wl_display *aDisplay, +- const StaticMutexAutoLock &) { +- int len = gWaylandDisplays.Count(); +- for (int i = 0; i < len; i++) { +- if (gWaylandDisplays[i]->Matches(aDisplay)) { +- int rc = gWaylandDisplays[i]->Release(); +- // nsCOMArray::AppendObject()/RemoveObjectAt() also call +- // AddRef()/Release() so remove WaylandDisplay when ref count is 1. +- if (rc == 1) { +- gWaylandDisplays.RemoveObjectAt(i); +- } +- return true; +- } +- } +- MOZ_ASSERT(false, "Missing nsWaylandDisplay for this thread!"); +- return false; +-} +- +-static void WaylandDisplayRelease(wl_display *aDisplay) { +- StaticMutexAutoLock lock(gWaylandDisplaysMutex); +- WaylandDisplayReleaseLocked(aDisplay, lock); +-} +- +-static void WaylandDisplayLoopLocked(wl_display *aDisplay, +- const StaticMutexAutoLock &) { +- int len = gWaylandDisplays.Count(); +- for (int i = 0; i < len; i++) { +- if (gWaylandDisplays[i]->Matches(aDisplay)) { +- if (gWaylandDisplays[i]->DisplayLoop()) { +- MessageLoop::current()->PostDelayedTask( +- NewRunnableFunction("WaylandDisplayLoop", &WaylandDisplayLoop, +- aDisplay), +- EVENT_LOOP_DELAY); +- } +- break; +- } +- } +-} +- +-static void WaylandDisplayLoop(wl_display *aDisplay) { +- MOZ_ASSERT(!NS_IsMainThread()); +- StaticMutexAutoLock lock(gWaylandDisplaysMutex); +- WaylandDisplayLoopLocked(aDisplay, lock); +-} +- +-static void global_registry_handler(void *data, wl_registry *registry, +- uint32_t id, const char *interface, +- uint32_t version) { +- if (strcmp(interface, "wl_shm") == 0) { +- auto interface = reinterpret_cast(data); +- auto shm = static_cast( +- wl_registry_bind(registry, id, &wl_shm_interface, 1)); +- wl_proxy_set_queue((struct wl_proxy *)shm, interface->GetEventQueue()); +- interface->SetShm(shm); +- } +-} +- +-static void global_registry_remover(void *data, wl_registry *registry, +- uint32_t id) {} +- +-static const struct wl_registry_listener registry_listener = { +- global_registry_handler, global_registry_remover}; +- +-wl_shm *nsWaylandDisplay::GetShm() { +- MOZ_ASSERT(mThreadId == PR_GetCurrentThread()); +- +- if (!mShm) { +- // wl_shm is not provided by Gtk so we need to query wayland directly +- // See weston/simple-shm.c and create_display() for reference. +- wl_registry *registry = wl_display_get_registry(mDisplay); +- wl_registry_add_listener(registry, ®istry_listener, this); +- +- wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue); +- if (mEventQueue) { +- wl_display_roundtrip_queue(mDisplay, mEventQueue); +- } else { +- wl_display_roundtrip(mDisplay); +- } +- +- MOZ_RELEASE_ASSERT(mShm, "Wayland registry query failed!"); +- } +- +- return (mShm); +-} +- +-bool nsWaylandDisplay::DisplayLoop() { +- wl_display_dispatch_queue_pending(mDisplay, mEventQueue); +- return true; +-} +- +-bool nsWaylandDisplay::Matches(wl_display *aDisplay) { +- return mThreadId == PR_GetCurrentThread() && aDisplay == mDisplay; +-} +- +-NS_IMPL_ISUPPORTS(nsWaylandDisplay, nsISupports); +- +-nsWaylandDisplay::nsWaylandDisplay(wl_display *aDisplay) +- : mThreadId(PR_GetCurrentThread()) +- // gfx::SurfaceFormat::B8G8R8A8 is a basic Wayland format +- // and is always present. +- , +- mFormat(gfx::SurfaceFormat::B8G8R8A8), +- mShm(nullptr), +- mDisplay(aDisplay) { +- if (NS_IsMainThread()) { +- // Use default event queue in main thread operated by Gtk+. +- mEventQueue = nullptr; +- } else { +- mEventQueue = wl_display_create_queue(mDisplay); +- MessageLoop::current()->PostTask(NewRunnableFunction( +- "WaylandDisplayLoop", &WaylandDisplayLoop, mDisplay)); +- } +-} +- +-nsWaylandDisplay::~nsWaylandDisplay() { +- MOZ_ASSERT(mThreadId == PR_GetCurrentThread()); +- // Owned by Gtk+, we don't need to release +- mDisplay = nullptr; +- +- if (mEventQueue) { +- wl_event_queue_destroy(mEventQueue); +- mEventQueue = nullptr; +- } +-} ++gfx::SurfaceFormat WindowBackBuffer::mFormat = gfx::SurfaceFormat::B8G8R8A8; - // Get WaylandDisplay for given wl_display and actual calling thread. - static nsWaylandDisplay* -@@ -304,6 +305,7 @@ nsWaylandDisplay::nsWaylandDisplay(wl_di - : mThreadId(PR_GetCurrentThread()) - // gfx::SurfaceFormat::B8G8R8A8 is a basic Wayland format - // and is always present. -+ // TODO: Provide also format without alpha (Bug 1470126). - , mFormat(gfx::SurfaceFormat::B8G8R8A8) - , mShm(nullptr) - , mDisplay(aDisplay) -@@ -522,7 +524,7 @@ WindowBackBuffer::Detach() + int WaylandShmPool::CreateTemporaryFile(int aSize) { +- const char *tmppath = getenv("XDG_RUNTIME_DIR"); ++ const char* tmppath = getenv("XDG_RUNTIME_DIR"); + MOZ_RELEASE_ASSERT(tmppath, "Missing XDG_RUNTIME_DIR env variable."); + + nsPrintfCString tmpname("%s/mozilla-shared-XXXXXX", tmppath); + +- char *filename; ++ char* filename; + int fd = -1; + int ret = 0; + +@@ -353,7 +182,7 @@ int WaylandShmPool::CreateTemporaryFile( + return fd; } - bool --WindowBackBuffer::SetImageDataFromBackBuffer( -+WindowBackBuffer::SetImageDataFromBuffer( - class WindowBackBuffer* aSourceBuffer) - { +-WaylandShmPool::WaylandShmPool(nsWaylandDisplay *aWaylandDisplay, int aSize) ++WaylandShmPool::WaylandShmPool(nsWaylandDisplay* aWaylandDisplay, int aSize) + : mAllocatedSize(aSize) { + mShmPoolFd = CreateTemporaryFile(mAllocatedSize); + mImageData = mmap(nullptr, mAllocatedSize, PROT_READ | PROT_WRITE, MAP_SHARED, +@@ -365,7 +194,7 @@ WaylandShmPool::WaylandShmPool(nsWayland + wl_shm_create_pool(aWaylandDisplay->GetShm(), mShmPoolFd, mAllocatedSize); + + // We set our queue to get mShmPool events at compositor thread. +- wl_proxy_set_queue((struct wl_proxy *)mShmPool, ++ wl_proxy_set_queue((struct wl_proxy*)mShmPool, + aWaylandDisplay->GetEventQueue()); + } + +@@ -394,7 +223,7 @@ bool WaylandShmPool::Resize(int aSize) { + return true; + } + +-void WaylandShmPool::SetImageDataFromPool(class WaylandShmPool *aSourcePool, ++void WaylandShmPool::SetImageDataFromPool(class WaylandShmPool* aSourcePool, + int aImageDataSize) { + MOZ_ASSERT(mAllocatedSize >= aImageDataSize, "WaylandShmPool overflows!"); + memcpy(mImageData, aSourcePool->GetImageData(), aImageDataSize); +@@ -406,8 +235,8 @@ WaylandShmPool::~WaylandShmPool() { + close(mShmPoolFd); + } + +-static void buffer_release(void *data, wl_buffer *buffer) { +- auto surface = reinterpret_cast(data); ++static void buffer_release(void* data, wl_buffer* buffer) { ++ auto surface = reinterpret_cast(data); + surface->Detach(); + } + +@@ -422,7 +251,7 @@ void WindowBackBuffer::Create(int aWidth + mWaylandBuffer = + wl_shm_pool_create_buffer(mShmPool.GetShmPool(), 0, aWidth, aHeight, + aWidth * BUFFER_BPP, WL_SHM_FORMAT_ARGB8888); +- wl_proxy_set_queue((struct wl_proxy *)mWaylandBuffer, ++ wl_proxy_set_queue((struct wl_proxy*)mWaylandBuffer, + mWaylandDisplay->GetEventQueue()); + wl_buffer_add_listener(mWaylandBuffer, &buffer_listener, this); + +@@ -435,7 +264,11 @@ void WindowBackBuffer::Release() { + mWidth = mHeight = 0; + } + +-WindowBackBuffer::WindowBackBuffer(nsWaylandDisplay *aWaylandDisplay, ++void WindowBackBuffer::Clear() { ++ memset(mShmPool.GetImageData(), 0, mHeight * mWidth * BUFFER_BPP); ++} ++ ++WindowBackBuffer::WindowBackBuffer(nsWaylandDisplay* aWaylandDisplay, + int aWidth, int aHeight) + : mShmPool(aWaylandDisplay, aWidth * aHeight * BUFFER_BPP), + mWaylandBuffer(nullptr), +@@ -457,7 +290,7 @@ bool WindowBackBuffer::Resize(int aWidth + return (mWaylandBuffer != nullptr); + } + +-void WindowBackBuffer::Attach(wl_surface *aSurface) { ++void WindowBackBuffer::Attach(wl_surface* aSurface) { + wl_surface_attach(aSurface, mWaylandBuffer, 0, 0); + wl_surface_commit(aSurface); + wl_display_flush(mWaylandDisplay->GetDisplay()); +@@ -466,8 +299,8 @@ void WindowBackBuffer::Attach(wl_surface + + void WindowBackBuffer::Detach() { mAttached = false; } + +-bool WindowBackBuffer::SetImageDataFromBackBuffer( +- class WindowBackBuffer *aSourceBuffer) { ++bool WindowBackBuffer::SetImageDataFromBuffer( ++ class WindowBackBuffer* aSourceBuffer) { if (!IsMatchingSize(aSourceBuffer)) { -@@ -535,11 +537,9 @@ WindowBackBuffer::SetImageDataFromBackBu + Resize(aSourceBuffer->mWidth, aSourceBuffer->mHeight); + } +@@ -478,204 +311,381 @@ bool WindowBackBuffer::SetImageDataFromB + return true; } - already_AddRefed --WindowBackBuffer::Lock(const LayoutDeviceIntRegion& aRegion) -+WindowBackBuffer::Lock() - { +-already_AddRefed WindowBackBuffer::Lock( +- const LayoutDeviceIntRegion &aRegion) { - gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); - gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); - ++already_AddRefed WindowBackBuffer::Lock() { + gfx::IntSize lockSize(mWidth, mHeight); - return gfxPlatform::CreateDrawTargetForData(static_cast(mShmPool.GetImageData()), - lockSize, - BUFFER_BPP * mWidth, -@@ -560,26 +560,40 @@ static const struct wl_callback_listener - WindowSurfaceWayland::WindowSurfaceWayland(nsWindow *aWindow) - : mWindow(aWindow) - , mWaylandDisplay(WaylandDisplayGet(aWindow->GetWaylandDisplay())) -- , mFrontBuffer(nullptr) -- , mBackBuffer(nullptr) -+ , mWaylandBuffer(nullptr) -+ , mBackupBuffer(nullptr) - , mFrameCallback(nullptr) -- , mFrameCallbackSurface(nullptr) -+ , mLastCommittedSurface(nullptr) - , mDisplayThreadMessageLoop(MessageLoop::current()) -- , mDelayedCommit(false) -- , mFullScreenDamage(false) -+ , mDelayedCommitHandle(nullptr) -+ , mDrawToWaylandBufferDirectly(true) -+ , mPendingCommit(false) -+ , mWaylandBufferFullScreenDamage(false) - , mIsMainThread(NS_IsMainThread()) -+ , mNeedScaleFactorUpdate(true) - { + return gfxPlatform::CreateDrawTargetForData( +- static_cast(mShmPool.GetImageData()), lockSize, +- BUFFER_BPP * mWidth, mWaylandDisplay->GetSurfaceFormat()); ++ static_cast(mShmPool.GetImageData()), lockSize, ++ BUFFER_BPP * mWidth, mFormat); } - WindowSurfaceWayland::~WindowSurfaceWayland() - { +-static void frame_callback_handler(void *data, struct wl_callback *callback, ++static void frame_callback_handler(void* data, struct wl_callback* callback, + uint32_t time) { +- auto surface = reinterpret_cast(data); ++ auto surface = reinterpret_cast(data); + surface->FrameCallbackHandler(); + } + + static const struct wl_callback_listener frame_listener = { + frame_callback_handler}; + +-WindowSurfaceWayland::WindowSurfaceWayland(nsWindow *aWindow) ++WindowSurfaceWayland::WindowSurfaceWayland(nsWindow* aWindow) + : mWindow(aWindow), +- mWaylandDisplay(WaylandDisplayGet(aWindow->GetWaylandDisplay())), +- mFrontBuffer(nullptr), +- mBackBuffer(nullptr), ++ mWaylandDisplay(WaylandDisplayGet()), ++ mWaylandBuffer(nullptr), + mFrameCallback(nullptr), +- mFrameCallbackSurface(nullptr), ++ mLastCommittedSurface(nullptr), + mDisplayThreadMessageLoop(MessageLoop::current()), +- mDelayedCommit(false), +- mFullScreenDamage(false), +- mIsMainThread(NS_IsMainThread()) {} ++ mDelayedCommitHandle(nullptr), ++ mDrawToWaylandBufferDirectly(true), ++ mPendingCommit(false), ++ mWaylandBufferFullScreenDamage(false), ++ mIsMainThread(NS_IsMainThread()), ++ mNeedScaleFactorUpdate(true) { ++ for (int i = 0; i < BACK_BUFFER_NUM; i++) mBackupBuffer[i] = nullptr; ++} + + WindowSurfaceWayland::~WindowSurfaceWayland() { - delete mFrontBuffer; - delete mBackBuffer; + if (mPendingCommit) { @@ -3383,35 +3865,45 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb } + delete mWaylandBuffer; -+ delete mBackupBuffer; ++ ++ for (int i = 0; i < BACK_BUFFER_NUM; i++) { ++ if (mBackupBuffer[i]) { ++ delete mBackupBuffer[i]; ++ } ++ } + 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 +607,309 @@ WindowSurfaceWayland::~WindowSurfaceWayl - } - } - --void --WindowSurfaceWayland::UpdateScaleFactor() --{ -- wl_surface* waylandSurface = mWindow->GetWaylandSurface(); -- if (waylandSurface) { -- wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor()); + // in compositor thread. We have to unref/delete WaylandDisplay in + // compositor thread then and we can't use MessageLoop::current() here. +- mDisplayThreadMessageLoop->PostTask( +- NewRunnableFunction("WaylandDisplayRelease", &WaylandDisplayRelease, +- mWaylandDisplay->GetDisplay())); ++ mDisplayThreadMessageLoop->PostTask(NewRunnableFunction( ++ "WaylandDisplayRelease", &WaylandDisplayRelease, mWaylandDisplay)); + } else { +- WaylandDisplayRelease(mWaylandDisplay->GetDisplay()); - } -} - - WindowBackBuffer* --WindowSurfaceWayland::GetBufferToDraw(int aWidth, int aHeight) -+WindowSurfaceWayland::GetWaylandBufferToDraw(int aWidth, int aHeight) - { +-void WindowSurfaceWayland::UpdateScaleFactor() { +- wl_surface *waylandSurface = mWindow->GetWaylandSurface(); +- if (waylandSurface) { +- wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor()); ++ WaylandDisplayRelease(mWaylandDisplay); + } + } + +-WindowBackBuffer *WindowSurfaceWayland::GetBufferToDraw(int aWidth, +- int aHeight) { - if (!mFrontBuffer) { - mFrontBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); - mBackBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); - return mFrontBuffer; ++WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw(int aWidth, ++ int aHeight) { + if (!mWaylandBuffer) { + mWaylandBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); -+ mBackupBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); + return mWaylandBuffer; } @@ -3425,36 +3917,53 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb // when buffer size changed - UpdateScaleFactor(); + mNeedScaleFactorUpdate = true; ++ } ++ return mWaylandBuffer; ++ } ++ ++ MOZ_ASSERT(!mPendingCommit, ++ "Uncommitted buffer switch, screen artifacts ahead."); ++ ++ // Front buffer is used by compositor, select a back buffer ++ int availableBuffer; ++ for (availableBuffer = 0; availableBuffer < BACK_BUFFER_NUM; ++ availableBuffer++) { ++ if (!mBackupBuffer[availableBuffer]) { ++ mBackupBuffer[availableBuffer] = ++ new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); ++ break; ++ } ++ ++ if (!mBackupBuffer[availableBuffer]->IsAttached()) { ++ break; } - return mFrontBuffer; -+ return mWaylandBuffer; } - // Front buffer is used by compositor, draw to back buffer +- // Front buffer is used by compositor, draw to back buffer - if (mBackBuffer->IsAttached()) { -+ if (mBackupBuffer->IsAttached()) { ++ if (MOZ_UNLIKELY(availableBuffer == BACK_BUFFER_NUM)) { NS_WARNING("No drawing buffer available"); return nullptr; } - MOZ_ASSERT(!mDelayedCommit, -+ MOZ_ASSERT(!mPendingCommit, - "Uncommitted buffer switch, screen artifacts ahead."); - +- "Uncommitted buffer switch, screen artifacts ahead."); +- - WindowBackBuffer *tmp = mFrontBuffer; - mFrontBuffer = mBackBuffer; - mBackBuffer = tmp; -+ WindowBackBuffer *tmp = mWaylandBuffer; -+ mWaylandBuffer = mBackupBuffer; -+ mBackupBuffer = tmp; ++ WindowBackBuffer* lastWaylandBuffer = mWaylandBuffer; ++ mWaylandBuffer = mBackupBuffer[availableBuffer]; ++ mBackupBuffer[availableBuffer] = lastWaylandBuffer; - if (mBackBuffer->IsMatchingSize(aWidth, aHeight)) { -+ if (mBackupBuffer->IsMatchingSize(aWidth, aHeight)) { ++ if (lastWaylandBuffer->IsMatchingSize(aWidth, aHeight)) { // Former front buffer has the same size as a requested one. // Gecko may expect a content already drawn on screen so copy // existing data to the new buffer. - mFrontBuffer->SetImageDataFromBackBuffer(mBackBuffer); -+ mWaylandBuffer->SetImageDataFromBuffer(mBackupBuffer); ++ mWaylandBuffer->SetImageDataFromBuffer(lastWaylandBuffer); // When buffer switches we need to damage whole screen // (https://bugzilla.redhat.com/show_bug.cgi?id=1418260) - mFullScreenDamage = true; @@ -3464,42 +3973,56 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb // the new buffer and leave gecko to render new whole content. - mFrontBuffer->Resize(aWidth, aHeight); + mWaylandBuffer->Resize(aWidth, aHeight); -+ } -+ -+ return mWaylandBuffer; -+} -+ -+already_AddRefed -+WindowSurfaceWayland::LockWaylandBuffer(int aWidth, int aHeight) -+{ -+ WindowBackBuffer* buffer = GetWaylandBufferToDraw(aWidth, aHeight); -+ if (buffer) { -+ return buffer->Lock(); } - return mFrontBuffer; -+ NS_WARNING("WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); -+ return nullptr; ++ return mWaylandBuffer; } - already_AddRefed -+WindowSurfaceWayland::LockImageSurface(const gfx::IntSize& aLockSize) -+{ +-already_AddRefed WindowSurfaceWayland::Lock( +- const LayoutDeviceIntRegion &aRegion) { +- MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); +- +- // We allocate back buffer to widget size but return only +- // portion requested by aRegion. +- LayoutDeviceIntRect rect = mWindow->GetBounds(); +- WindowBackBuffer *buffer = GetBufferToDraw(rect.width, rect.height); ++already_AddRefed WindowSurfaceWayland::LockWaylandBuffer( ++ int aWidth, int aHeight, bool aClearBuffer) { ++ WindowBackBuffer* buffer = GetWaylandBufferToDraw(aWidth, aHeight); + if (!buffer) { +- NS_WARNING("No drawing buffer available"); ++ NS_WARNING( ++ "WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); + return nullptr; + } + +- return buffer->Lock(aRegion); ++ if (aClearBuffer) { ++ buffer->Clear(); ++ } ++ ++ return buffer->Lock(); ++} ++ ++already_AddRefed WindowSurfaceWayland::LockImageSurface( ++ const gfx::IntSize& aLockSize) { + if (!mImageSurface || mImageSurface->CairoStatus() || + !(aLockSize <= mImageSurface->GetSize())) { -+ mImageSurface = new gfxImageSurface(aLockSize, -+ SurfaceFormatToImageFormat(mWaylandDisplay->GetSurfaceFormat())); ++ mImageSurface = new gfxImageSurface( ++ aLockSize, ++ SurfaceFormatToImageFormat(WindowBackBuffer::GetSurfaceFormat())); + if (mImageSurface->CairoStatus()) { + return nullptr; + } + } + -+ return gfxPlatform::CreateDrawTargetForData(mImageSurface->Data(), -+ mImageSurface->GetSize(), -+ mImageSurface->Stride(), -+ mWaylandDisplay->GetSurfaceFormat()); -+} -+ ++ return gfxPlatform::CreateDrawTargetForData( ++ mImageSurface->Data(), mImageSurface->GetSize(), mImageSurface->Stride(), ++ WindowBackBuffer::GetSurfaceFormat()); + } + +-void WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion &aInvalidRegion) { +/* + There are some situations which can happen here: + @@ -3513,32 +4036,25 @@ 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 - WindowSurfaceWayland::Lock(const LayoutDeviceIntRegion& aRegion) - { ++already_AddRefed WindowSurfaceWayland::Lock( ++ const LayoutDeviceIntRegion& aRegion) { MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); -- // We allocate back buffer to widget size but return only -- // portion requested by aRegion. -- LayoutDeviceIntRect rect = mWindow->GetBounds(); -- WindowBackBuffer* buffer = GetBufferToDraw(rect.width, -- rect.height); -- if (!buffer) { -- NS_WARNING("No drawing buffer available"); -- return nullptr; +- wl_surface *waylandSurface = mWindow->GetWaylandSurface(); + LayoutDeviceIntRect screenRect = mWindow->GetBounds(); + gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); + gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); + + // Are we asked for entire nsWindow to draw? -+ mDrawToWaylandBufferDirectly = (aRegion.GetNumRects() == 1 && -+ bounds.x == 0 && bounds.y == 0 && -+ lockSize.width == screenRect.width && -+ lockSize.height == screenRect.height); ++ mDrawToWaylandBufferDirectly = ++ (aRegion.GetNumRects() == 1 && bounds.x == 0 && bounds.y == 0 && ++ lockSize.width == screenRect.width && ++ lockSize.height == screenRect.height); + + if (mDrawToWaylandBufferDirectly) { -+ RefPtr dt = LockWaylandBuffer(screenRect.width, -+ screenRect.height); ++ RefPtr dt = ++ LockWaylandBuffer(screenRect.width, screenRect.height, ++ mWindow->WaylandSurfaceNeedsClear()); + if (dt) { + return dt.forget(); + } @@ -3551,9 +4067,8 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + return LockImageSurface(lockSize); +} + -+bool -+WindowSurfaceWayland::CommitImageSurfaceToWaylandBuffer(const LayoutDeviceIntRegion& aRegion) -+{ ++bool WindowSurfaceWayland::CommitImageSurfaceToWaylandBuffer( ++ const LayoutDeviceIntRegion& aRegion) { + MOZ_ASSERT(!mDrawToWaylandBufferDirectly); + + LayoutDeviceIntRect screenRect = mWindow->GetBounds(); @@ -3564,17 +4079,16 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + return false; + } + -+ RefPtr dt = LockWaylandBuffer(screenRect.width, -+ screenRect.height); ++ RefPtr dt = LockWaylandBuffer( ++ screenRect.width, screenRect.height, mWindow->WaylandSurfaceNeedsClear()); + RefPtr surf = -+ gfx::Factory::CreateSourceSurfaceForCairoSurface(mImageSurface->CairoSurface(), -+ mImageSurface->GetSize(), -+ mImageSurface->Format()); ++ gfx::Factory::CreateSourceSurfaceForCairoSurface( ++ mImageSurface->CairoSurface(), mImageSurface->GetSize(), ++ mImageSurface->Format()); + if (!dt || !surf) { + return false; - } - -- return buffer->Lock(aRegion); ++ } ++ + uint32_t numRects = aRegion.GetNumRects(); + if (numRects != 1) { + AutoTArray rects; @@ -3594,9 +4108,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + return true; +} + -+static void -+WaylandBufferDelayCommitHandler(WindowSurfaceWayland **aSurface) -+{ ++static void WaylandBufferDelayCommitHandler(WindowSurfaceWayland** aSurface) { + if (*aSurface) { + (*aSurface)->DelayedCommitHandler(); + } else { @@ -3605,39 +4117,36 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + // WindowSurfaceWayland::CommitWaylandBuffer(). + free(aSurface); + } - } - - void --WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion) -+WindowSurfaceWayland::CommitWaylandBuffer() - { -- MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); ++} ++ ++void WindowSurfaceWayland::CommitWaylandBuffer() { + MOZ_ASSERT(mPendingCommit, "Committing empty surface!"); - - wl_surface* waylandSurface = mWindow->GetWaylandSurface(); ++ ++ wl_surface* waylandSurface = mWindow->GetWaylandSurface(); if (!waylandSurface) { - // Target window is already destroyed - don't bother to render there. + // Target window is not created yet - delay the commit. This can happen only + // when the window is newly created and there's no active + // frame callback pending. + MOZ_ASSERT(!mFrameCallback || waylandSurface != mLastCommittedSurface, -+ "Missing wayland surface at frame callback!"); ++ "Missing wayland surface at frame callback!"); + + // Do nothing if there's already mDelayedCommitHandle pending. + if (!mDelayedCommitHandle) { + mDelayedCommitHandle = static_cast( -+ moz_xmalloc(sizeof(*mDelayedCommitHandle))); ++ moz_xmalloc(sizeof(*mDelayedCommitHandle))); + *mDelayedCommitHandle = this; + + MessageLoop::current()->PostDelayedTask( -+ NewRunnableFunction("WaylandBackBufferCommit", -+ &WaylandBufferDelayCommitHandler, -+ mDelayedCommitHandle), -+ EVENT_LOOP_DELAY); ++ NewRunnableFunction("WaylandBackBufferCommit", ++ &WaylandBufferDelayCommitHandler, ++ mDelayedCommitHandle), ++ EVENT_LOOP_DELAY); + } return; } - wl_proxy_set_queue((struct wl_proxy *)waylandSurface, +- wl_proxy_set_queue((struct wl_proxy *)waylandSurface, ++ wl_proxy_set_queue((struct wl_proxy*)waylandSurface, mWaylandDisplay->GetEventQueue()); - if (mFullScreenDamage) { @@ -3662,14 +4171,16 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + mWaylandBufferFullScreenDamage = false; } else { - for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) { -+ gint scaleFactor = mWindow->GdkScaleFactor(); -+ for (auto iter = mWaylandBufferDamage.RectIter(); !iter.Done(); iter.Next()) { - const mozilla::LayoutDeviceIntRect &r = iter.Get(); +- const mozilla::LayoutDeviceIntRect &r = iter.Get(); - wl_surface_damage(waylandSurface, r.x, r.y, r.width, r.height); ++ gint scaleFactor = mWindow->GdkScaleFactor(); ++ for (auto iter = mWaylandBufferDamage.RectIter(); !iter.Done(); ++ iter.Next()) { ++ const mozilla::LayoutDeviceIntRect& r = iter.Get(); + // We need to remove the scale factor because the wl_surface_damage + // also multiplies by current scale factor. -+ wl_surface_damage(waylandSurface, r.x/scaleFactor, r.y/scaleFactor, -+ r.width/scaleFactor, r.height/scaleFactor); ++ wl_surface_damage(waylandSurface, r.x / scaleFactor, r.y / scaleFactor, ++ r.width / scaleFactor, r.height / scaleFactor); } } @@ -3683,7 +4194,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb - // commited to compositor in next frame callback event. - mDelayedCommit = true; - return; -- } else { +- } else { - if (mFrameCallback) { - // Delete frame callback connected to obsoleted wl_surface. - wl_callback_destroy(mFrameCallback); @@ -3706,7 +4217,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + if (mNeedScaleFactorUpdate || mLastCommittedSurface != waylandSurface) { + wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor()); + mNeedScaleFactorUpdate = false; -+ } + } + + mWaylandBuffer->Attach(waylandSurface); + mLastCommittedSurface = waylandSurface; @@ -3715,15 +4226,13 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + mPendingCommit = false; +} + -+void -+WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion) -+{ ++void WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion) { + MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); + + // We have new content at mImageSurface - copy data to mWaylandBuffer first. + if (!mDrawToWaylandBufferDirectly) { + CommitImageSurfaceToWaylandBuffer(aInvalidRegion); - } ++ } + + // If we're not at fullscreen damage add drawing area from aInvalidRegion + if (!mWaylandBufferFullScreenDamage) { @@ -3735,9 +4244,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + CommitWaylandBuffer(); } - void - WindowSurfaceWayland::FrameCallbackHandler() - { + void WindowSurfaceWayland::FrameCallbackHandler() { MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); + MOZ_ASSERT(mFrameCallback != nullptr, + "FrameCallbackHandler() called without valid frame callback!"); @@ -3757,7 +4264,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb +} - if (mDelayedCommit) { -- wl_surface* waylandSurface = mWindow->GetWaylandSurface(); +- wl_surface *waylandSurface = mWindow->GetWaylandSurface(); - if (!waylandSurface) { - // Target window is already destroyed - don't bother to render there. - NS_WARNING("No drawing buffer available"); @@ -3765,9 +4272,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb - } - wl_proxy_set_queue((struct wl_proxy *)waylandSurface, - mWaylandDisplay->GetEventQueue()); -+void -+WindowSurfaceWayland::DelayedCommitHandler() -+{ ++void WindowSurfaceWayland::DelayedCommitHandler() { + MOZ_ASSERT(mDelayedCommitHandle != nullptr, "Missing mDelayedCommitHandle!"); - // Send pending surface to compositor and register frame callback @@ -3786,18 +4291,58 @@ 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-21 13:42:00.763025640 +0100 -@@ -8,6 +8,7 @@ +diff -up thunderbird-60.5.0/widget/gtk/WindowSurfaceWayland.h.wayland thunderbird-60.5.0/widget/gtk/WindowSurfaceWayland.h +--- thunderbird-60.5.0/widget/gtk/WindowSurfaceWayland.h.wayland 2019-01-22 20:44:03.000000000 +0100 ++++ thunderbird-60.5.0/widget/gtk/WindowSurfaceWayland.h 2019-02-05 14:26:16.979316635 +0100 +@@ -1,4 +1,4 @@ +-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this +@@ -8,37 +8,14 @@ #define _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H #include +#include "mozilla/gfx/Types.h" ++#include "nsWaylandDisplay.h" ++ ++#define BACK_BUFFER_NUM 2 namespace mozilla { namespace widget { -@@ -66,14 +67,14 @@ public: + +-// Our general connection to Wayland display server, +-// holds our display connection and runs event loop. +-class nsWaylandDisplay : public nsISupports { +- NS_DECL_THREADSAFE_ISUPPORTS +- +- public: +- nsWaylandDisplay(wl_display* aDisplay); +- +- wl_shm* GetShm(); +- void SetShm(wl_shm* aShm) { mShm = aShm; }; +- +- wl_display* GetDisplay() { return mDisplay; }; +- wl_event_queue* GetEventQueue() { return mEventQueue; }; +- gfx::SurfaceFormat GetSurfaceFormat() { return mFormat; }; +- bool DisplayLoop(); +- bool Matches(wl_display* aDisplay); +- +- private: +- virtual ~nsWaylandDisplay(); +- +- PRThread* mThreadId; +- gfx::SurfaceFormat mFormat; +- wl_shm* mShm; +- wl_event_queue* mEventQueue; +- wl_display* mDisplay; +-}; +- + // Allocates and owns shared memory for Wayland drawing surface + class WaylandShmPool { + public: +@@ -66,14 +43,15 @@ class WindowBackBuffer { WindowBackBuffer(nsWaylandDisplay* aDisplay, int aWidth, int aHeight); ~WindowBackBuffer(); @@ -3808,49 +4353,76 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h.wayland thunderbir void Detach(); bool IsAttached() { return mAttached; } ++ void Clear(); bool Resize(int aWidth, int aHeight); - bool SetImageDataFromBackBuffer(class WindowBackBuffer* aSourceBuffer); + bool SetImageDataFromBuffer(class WindowBackBuffer* aSourceBuffer); - bool IsMatchingSize(int aWidth, int aHeight) - { -@@ -110,22 +111,32 @@ public: - already_AddRefed Lock(const LayoutDeviceIntRegion& aRegion) override; - void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final; - void FrameCallbackHandler(); -+ void DelayedCommitHandler(); + bool IsMatchingSize(int aWidth, int aHeight) { + return aWidth == mWidth && aHeight == mHeight; +@@ -82,6 +60,8 @@ class WindowBackBuffer { + return aBuffer->mWidth == mWidth && aBuffer->mHeight == mHeight; + } - private: -- WindowBackBuffer* GetBufferToDraw(int aWidth, int aHeight); -- void UpdateScaleFactor(); -+ WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight); ++ static gfx::SurfaceFormat GetSurfaceFormat() { return mFormat; } + -+ already_AddRefed LockWaylandBuffer(int aWidth, int aHeight); -+ already_AddRefed LockImageSurface(const gfx::IntSize& aLockSize); -+ bool CommitImageSurfaceToWaylandBuffer(const LayoutDeviceIntRegion& aRegion); -+ void CommitWaylandBuffer(); + private: + void Create(int aWidth, int aHeight); + void Release(); +@@ -96,35 +76,48 @@ class WindowBackBuffer { + int mHeight; + bool mAttached; + nsWaylandDisplay* mWaylandDisplay; ++ static gfx::SurfaceFormat mFormat; + }; + + // WindowSurfaceWayland is an abstraction for wl_surface + // and related management + class WindowSurfaceWayland : public WindowSurface { + public: +- WindowSurfaceWayland(nsWindow* aWindow); ++ explicit WindowSurfaceWayland(nsWindow* aWindow); + ~WindowSurfaceWayland(); + + already_AddRefed Lock( + const LayoutDeviceIntRegion& aRegion) override; + void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final; + void FrameCallbackHandler(); ++ void DelayedCommitHandler(); + + private: +- WindowBackBuffer* GetBufferToDraw(int aWidth, int aHeight); +- void UpdateScaleFactor(); ++ WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight); ++ ++ already_AddRefed LockWaylandBuffer(int aWidth, int aHeight, ++ bool aClearBuffer); ++ already_AddRefed LockImageSurface( ++ const gfx::IntSize& aLockSize); ++ bool CommitImageSurfaceToWaylandBuffer(const LayoutDeviceIntRegion& aRegion); ++ void CommitWaylandBuffer(); // TODO: Do we need to hold a reference to nsWindow object? - nsWindow* mWindow; - nsWaylandDisplay* mWaylandDisplay; -- WindowBackBuffer* mFrontBuffer; -- WindowBackBuffer* mBackBuffer; -+ WindowBackBuffer* mWaylandBuffer; -+ LayoutDeviceIntRegion mWaylandBufferDamage; -+ WindowBackBuffer* mBackupBuffer; -+ RefPtr mImageSurface; - wl_callback* mFrameCallback; -- wl_surface* mFrameCallbackSurface; -+ wl_surface* mLastCommittedSurface; - MessageLoop* mDisplayThreadMessageLoop; -- bool mDelayedCommit; -- bool mFullScreenDamage; -+ WindowSurfaceWayland** mDelayedCommitHandle; -+ bool mDrawToWaylandBufferDirectly; -+ bool mPendingCommit; -+ bool mWaylandBufferFullScreenDamage; - bool mIsMainThread; -+ bool mNeedScaleFactorUpdate; + nsWindow* mWindow; + nsWaylandDisplay* mWaylandDisplay; +- WindowBackBuffer* mFrontBuffer; +- WindowBackBuffer* mBackBuffer; ++ WindowBackBuffer* mWaylandBuffer; ++ LayoutDeviceIntRegion mWaylandBufferDamage; ++ WindowBackBuffer* mBackupBuffer[BACK_BUFFER_NUM]; ++ RefPtr mImageSurface; + wl_callback* mFrameCallback; +- wl_surface* mFrameCallbackSurface; ++ wl_surface* mLastCommittedSurface; + MessageLoop* mDisplayThreadMessageLoop; +- bool mDelayedCommit; +- bool mFullScreenDamage; ++ WindowSurfaceWayland** mDelayedCommitHandle; ++ bool mDrawToWaylandBufferDirectly; ++ bool mPendingCommit; ++ bool mWaylandBufferFullScreenDamage; + bool mIsMainThread; ++ bool mNeedScaleFactorUpdate; }; } // namespace widget diff --git a/mozbz-1500850-missing-dbus-header.patch b/mozbz-1500850-missing-dbus-header.patch deleted file mode 100644 index 9940e06..0000000 --- a/mozbz-1500850-missing-dbus-header.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/widget/xremoteclient/DBusRemoteClient.cpp b/widget/xremoteclient/DBusRemoteClient.cpp ---- a/widget/xremoteclient/DBusRemoteClient.cpp -+++ b/widget/xremoteclient/DBusRemoteClient.cpp -@@ -13,6 +13,7 @@ - #include "nsPrintfCString.h" - - #include -+#include - - using mozilla::LogLevel; - static mozilla::LazyLogModule sRemoteLm("DBusRemoteClient"); - diff --git a/thunderbird.spec b/thunderbird.spec index 7717b22..4826178 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -109,11 +109,9 @@ Patch37: build-jit-atomic-always-lucky.patch Patch40: build-aarch64-skia.patch Patch226: rhbz-1354671.patch Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch -#Patch417: bug1375074-save-restore-x28.patch # Build patches Patch103: rhbz-1219542-s390-build.patch -#Patch104: firefox-gcc-6.0.patch # PPC fix Patch304: mozilla-1245783.patch @@ -121,12 +119,9 @@ Patch305: build-big-endian.patch Patch306: mozilla-1353817.patch Patch307: build-disable-elfhack.patch Patch309: mozilla-1460871-ldap-query.patch -#Patch314: mozbz-1500850-missing-dbus-header.patch # Fedora specific patches -#Patch310: disable-dbus-remote.patch Patch311: firefox-wayland.patch -Patch313: firefox-wayland-crash-mozbz1507475.patch # Upstream patches @@ -235,17 +230,14 @@ debug %{name}, you want to install %{name}-debuginfo instead. %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build %endif -#%patch104 -p1 -b .gcc6 %patch304 -p1 -b .1245783 %patch309 -p1 -b .1460871-ldap-query -#%patch314 -p1 -b .1500850-missing-dbus-header # Patch for big endian platforms only %if 0%{?big_endian} %patch26 -p1 -b .icu %patch305 -p1 -b .big-endian %endif -#%patch310 -p1 -b .disable-dbus-remote %patch37 -p1 -b .jit-atomic-lucky %patch40 -p1 -b .aarch64-skia @@ -256,7 +248,6 @@ debug %{name}, you want to install %{name}-debuginfo instead. %ifarch %{arm} %patch415 -p1 -b .mozilla-1238661 %endif -#%patch417 -p1 -b .bug1375074-save-restore-x28 %patch306 -p1 -b .1353817 %if 0%{?disable_elfhack} @@ -264,9 +255,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %endif #cd .. -#TODO - needs fixes -#%patch311 -p1 -b .wayland -#%patch313 -p1 -b .mozbz1507475 +%patch311 -p1 -b .wayland %if %{official_branding} # Required by Mozilla Corporation