From 12b8d0b63e43c48a510e1c9a5955bad179d91dbe Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 28 Aug 2018 13:47:57 +0200 Subject: [PATCH 001/402] Added patches from Firefox --- bug1375074-save-restore-x28.patch | 74 +++++++++++++++++++++++++++++ build-aarch64-skia.patch | 21 ++++++++ build-jit-atomic-always-lucky.patch | 30 ++++++++++++ rhbz-1354671.patch | 12 +++++ thunderbird.spec | 17 ++++++- 5 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 bug1375074-save-restore-x28.patch create mode 100644 build-aarch64-skia.patch create mode 100644 build-jit-atomic-always-lucky.patch create mode 100644 rhbz-1354671.patch diff --git a/bug1375074-save-restore-x28.patch b/bug1375074-save-restore-x28.patch new file mode 100644 index 0000000..57a83a2 --- /dev/null +++ b/bug1375074-save-restore-x28.patch @@ -0,0 +1,74 @@ +# 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/build-aarch64-skia.patch b/build-aarch64-skia.patch new file mode 100644 index 0000000..33d2d35 --- /dev/null +++ b/build-aarch64-skia.patch @@ -0,0 +1,21 @@ +diff -up firefox-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia firefox-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp +--- firefox-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia 2018-04-20 12:07:26.242037226 +0200 ++++ firefox-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp 2018-04-20 12:12:58.916428432 +0200 +@@ -666,7 +666,7 @@ SI F approx_powf(F x, F y) { + } + + SI F from_half(U16 h) { +-#if defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. ++#if 0 && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. + return vcvt_f32_f16(h); + + #elif defined(JUMPER_IS_HSW) || defined(JUMPER_IS_AVX512) +@@ -686,7 +686,7 @@ SI F from_half(U16 h) { + } + + SI U16 to_half(F f) { +-#if defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. ++#if 0 && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. + return vcvt_f16_f32(f); + + #elif defined(JUMPER_IS_HSW) || defined(JUMPER_IS_AVX512) diff --git a/build-jit-atomic-always-lucky.patch b/build-jit-atomic-always-lucky.patch new file mode 100644 index 0000000..31bc5ec --- /dev/null +++ b/build-jit-atomic-always-lucky.patch @@ -0,0 +1,30 @@ +diff -up firefox-57.0b5/js/src/jit/AtomicOperations.h.jit-atomic-lucky firefox-57.0b5/js/src/jit/AtomicOperations.h +--- firefox-57.0b5/js/src/jit/AtomicOperations.h.jit-atomic-lucky 2017-10-06 12:34:02.338973607 +0200 ++++ firefox-57.0b5/js/src/jit/AtomicOperations.h 2017-10-06 12:38:24.632622215 +0200 +@@ -415,7 +415,7 @@ AtomicOperations::isLockfreeJS(int32_t s + #elif defined(__s390__) || defined(__s390x__) + # include "jit/none/AtomicOperations-feeling-lucky.h" + #else +-# error "No AtomicOperations support provided for this platform" ++# include "jit/none/AtomicOperations-feeling-lucky.h" + #endif + + #endif // jit_AtomicOperations_h +diff -up firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h.jit-atomic-lucky firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h +--- firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h.jit-atomic-lucky 2017-09-19 06:18:28.000000000 +0200 ++++ firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h 2017-10-06 12:34:02.338973607 +0200 +@@ -79,6 +79,14 @@ + # define GNUC_COMPATIBLE + #endif + ++#ifdef __s390__ ++# define GNUC_COMPATIBLE ++#endif ++ ++#ifdef __s390x__ ++# define GNUC_COMPATIBLE ++#endif ++ + // The default implementation tactic for gcc/clang is to use the newer + // __atomic intrinsics added for use in C++11 . Where that + // isn't available, we use GCC's older __sync functions instead. diff --git a/rhbz-1354671.patch b/rhbz-1354671.patch new file mode 100644 index 0000000..6ee89b7 --- /dev/null +++ b/rhbz-1354671.patch @@ -0,0 +1,12 @@ +diff -up firefox-53.0/layout/base/nsIPresShell.h.1354671 firefox-53.0/layout/base/nsIPresShell.h +--- firefox-53.0/layout/base/nsIPresShell.h.1354671 2017-04-27 13:07:43.808653320 +0200 ++++ firefox-53.0/layout/base/nsIPresShell.h 2017-04-27 13:09:40.404427641 +0200 +@@ -212,7 +212,7 @@ public: + * to the same aSize value. AllocateFrame is infallible and will abort + * on out-of-memory. + */ +- void* AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) ++ void* __attribute__((optimize("no-lifetime-dse"))) AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) + { + void* result = mFrameArena.AllocateByFrameID(aID, aSize); + RecordAlloc(result); diff --git a/thunderbird.spec b/thunderbird.spec index ba27549..faa5c66 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -105,12 +105,16 @@ Source21: thunderbird.sh.in # Mozilla (XULRunner) patches Patch9: mozilla-build-arm.patch Patch26: build-icu-big-endian.patch +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 Patch305: build-big-endian.patch @@ -228,6 +232,17 @@ debug %{name}, you want to install %{name}-debuginfo instead. # Patch for big endian platforms only %if 0%{?big_endian} %patch26 -p1 -b .icu +%patch37 -p1 -b .jit-atomic-lucky +%patch40 -p1 -b .aarch64-skia +#ARM run-time patch +%ifarch aarch64 +%patch226 -p1 -b .1354671 +%endif +%ifarch %{arm} +%patch415 -p1 -b .mozilla-1238661 +%endif +%patch417 -p1 -b .bug1375074-save-restore-x28 + %patch305 -p1 -b .big-endian %patch306 -p1 -b .1353817 %endif From 2fb4c70ebdf48fa3c55537a590d481cd4fe8a51b Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 28 Aug 2018 13:48:45 +0200 Subject: [PATCH 002/402] Adding missing patch - signalTrampoline --- ...fix-mozillaSignalTrampoline-to-work-.patch | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch diff --git a/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch b/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch new file mode 100644 index 0000000..70e45ff --- /dev/null +++ b/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch @@ -0,0 +1,19 @@ +diff -up firefox-60.0/mfbt/LinuxSignal.h.mozilla-1238661 firefox-60.0/mfbt/LinuxSignal.h +--- firefox-60.0/mfbt/LinuxSignal.h.mozilla-1238661 2018-04-27 08:55:38.848241768 +0200 ++++ firefox-60.0/mfbt/LinuxSignal.h 2018-04-27 09:06:47.946769859 +0200 +@@ -25,10 +25,13 @@ SignalTrampoline(int aSignal, siginfo_t* + "nop; nop; nop; nop" + : : : "memory"); + ++ // Because the assembler may generate additional insturctions below, we ++ // need to ensure NOPs are inserted first by separating them out above. ++ + asm volatile ( +- "b %0" ++ "bx %0" + : +- : "X"(H) ++ : "r"(H), "l"(aSignal), "l"(aInfo), "l"(aContext) + : "memory"); + } + From b9538e9ed2af1db13b91cace8be84e1493a5170b Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 28 Aug 2018 14:40:26 +0200 Subject: [PATCH 003/402] Fixing patch application and rejected aarch64 patch --- build-aarch64-skia.patch | 14 +++++++------- thunderbird.spec | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/build-aarch64-skia.patch b/build-aarch64-skia.patch index 33d2d35..b23296e 100644 --- a/build-aarch64-skia.patch +++ b/build-aarch64-skia.patch @@ -1,12 +1,12 @@ -diff -up firefox-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia firefox-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp ---- firefox-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia 2018-04-20 12:07:26.242037226 +0200 -+++ firefox-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp 2018-04-20 12:12:58.916428432 +0200 +diff -up thunderbird-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia thunderbird-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp +--- thunderbird-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia 2018-08-28 14:36:13.555012053 +0200 ++++ thunderbird-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp 2018-08-28 14:38:17.160274150 +0200 @@ -666,7 +666,7 @@ SI F approx_powf(F x, F y) { } SI F from_half(U16 h) { --#if defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. -+#if 0 && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. +-#if defined(JUMPER_IS_NEON) && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. ++#if 0 && defined(JUMPER_IS_NEON) && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. return vcvt_f32_f16(h); #elif defined(JUMPER_IS_HSW) || defined(JUMPER_IS_AVX512) @@ -14,8 +14,8 @@ diff -up firefox-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia } SI U16 to_half(F f) { --#if defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. -+#if 0 && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. +-#if defined(JUMPER_IS_NEON) && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. ++#if 0 && defined(JUMPER_IS_NEON) && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. return vcvt_f16_f32(f); #elif defined(JUMPER_IS_HSW) || defined(JUMPER_IS_AVX512) diff --git a/thunderbird.spec b/thunderbird.spec index faa5c66..0252e73 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -232,6 +232,9 @@ debug %{name}, you want to install %{name}-debuginfo instead. # Patch for big endian platforms only %if 0%{?big_endian} %patch26 -p1 -b .icu +%patch305 -p1 -b .big-endian +%endif + %patch37 -p1 -b .jit-atomic-lucky %patch40 -p1 -b .aarch64-skia #ARM run-time patch @@ -243,9 +246,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %endif %patch417 -p1 -b .bug1375074-save-restore-x28 -%patch305 -p1 -b .big-endian %patch306 -p1 -b .1353817 -%endif #cd .. %if %{official_branding} From 0ba1a86917a7f852b3d1ae37d63954c93cab1391 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 29 Aug 2018 14:22:44 +0200 Subject: [PATCH 004/402] Enable ion for arm --- thunderbird.spec | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index 0252e73..f4d4985 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -312,7 +312,7 @@ echo "ac_add_options --enable-system-ffi" >> .mozconfig echo "ac_add_options --disable-debug" >> .mozconfig %endif -%ifarch %{arm} aarch64 +%ifarch aarch64 echo "ac_add_options --disable-ion" >> .mozconfig %endif @@ -329,13 +329,11 @@ echo "ac_add_options --with-fpu=vfpv3-d16" >> .mozconfig echo "ac_add_options --with-arch=armv7-a" >> .mozconfig echo "ac_add_options --with-float-abi=hard" >> .mozconfig echo "ac_add_options --with-fpu=neon" >> .mozconfig -echo "ac_add_options --disable-ion" >> .mozconfig echo "ac_add_options --disable-yarr-jit" >> .mozconfig %endif %ifarch armv5tel echo "ac_add_options --with-arch=armv5te" >> .mozconfig echo "ac_add_options --with-float-abi=soft" >> .mozconfig -echo "ac_add_options --disable-ion" >> .mozconfig echo "ac_add_options --disable-yarr-jit" >> .mozconfig %endif From 2a711384ebd8f9b1142138135ae3b7e494f3b06b Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 2 Oct 2018 13:10:36 +0200 Subject: [PATCH 005/402] Disable elfhack for fedora 29+ because of build failures --- thunderbird.spec | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/thunderbird.spec b/thunderbird.spec index f4d4985..96910ab 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -13,6 +13,11 @@ %define build_langpacks 1 +%global disable_elfhack 0 +%if 0%{?fedora} > 28 +%global disable_elfhack 1 +%endif + %if %{?system_nss} %global nspr_version 4.10.6 %global nspr_build_version %(pkg-config --silence-errors --modversion nspr 2>/dev/null || echo 65536) @@ -119,6 +124,7 @@ Patch104: firefox-gcc-6.0.patch Patch304: mozilla-1245783.patch Patch305: build-big-endian.patch Patch306: mozilla-1353817.patch +Patch307: build-big-endian.patch # Fedora specific patches @@ -247,6 +253,9 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch417 -p1 -b .bug1375074-save-restore-x28 %patch306 -p1 -b .1353817 +%if 0%{?disable_elfhack} +%patch307 -p1 -b .build-big-endian +%endif #cd .. %if %{official_branding} From 901572971a0f939d25e2bababebe518d617314e2 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 2 Oct 2018 13:56:36 +0200 Subject: [PATCH 006/402] Fixing elfhack patch apply --- thunderbird.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index 96910ab..0c400df 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -124,7 +124,7 @@ Patch104: firefox-gcc-6.0.patch Patch304: mozilla-1245783.patch Patch305: build-big-endian.patch Patch306: mozilla-1353817.patch -Patch307: build-big-endian.patch +Patch307: build-disable-elfhack.patch # Fedora specific patches @@ -254,7 +254,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch306 -p1 -b .1353817 %if 0%{?disable_elfhack} -%patch307 -p1 -b .build-big-endian +%patch307 -p1 -b .elfhack %endif #cd .. From 311a9c954d0870ec92b5d6e808e99198cf0f11f9 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 2 Oct 2018 14:28:58 +0200 Subject: [PATCH 007/402] added build-triplet-failure.patch for configure failure with latest rust --- build-triplet-failure.patch | 18 ++++++++++++++++++ thunderbird.spec | 2 ++ 2 files changed, 20 insertions(+) create mode 100644 build-triplet-failure.patch diff --git a/build-triplet-failure.patch b/build-triplet-failure.patch new file mode 100644 index 0000000..068d27c --- /dev/null +++ b/build-triplet-failure.patch @@ -0,0 +1,18 @@ +diff -up thunderbird-60.0/build/moz.configure/init.configure.triplet-failure thunderbird-60.0/build/moz.configure/init.configure +--- thunderbird-60.0/build/moz.configure/init.configure.triplet-failure 2018-10-02 14:13:04.276835572 +0200 ++++ thunderbird-60.0/build/moz.configure/init.configure 2018-10-02 14:13:18.921865210 +0200 +@@ -577,7 +577,13 @@ def split_triplet(triplet, allow_unknown + # There is also a quartet form: + # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM + # But we can consider the "KERNEL-OPERATING_SYSTEM" as one. +- cpu, manufacturer, os = triplet.split('-', 2) ++ parts = triplet.split('-', 2) ++ if len(parts) == 3: ++ cpu, _, os = parts ++ elif len(parts) == 2: ++ cpu, os = parts ++ else: ++ die("Unexpected triplet string: %s" % triplet) + + # Autoconf uses config.sub to validate and canonicalize those triplets, + # but the granularity of its results has never been satisfying to our diff --git a/thunderbird.spec b/thunderbird.spec index 0c400df..5795a5e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -125,6 +125,7 @@ Patch304: mozilla-1245783.patch Patch305: build-big-endian.patch Patch306: mozilla-1353817.patch Patch307: build-disable-elfhack.patch +Patch308: build-triplet-failure.patch # Fedora specific patches @@ -235,6 +236,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch104 -p1 -b .gcc6 %patch304 -p1 -b .1245783 +%patch308 -p1 -b .triplet-failure # Patch for big endian platforms only %if 0%{?big_endian} %patch26 -p1 -b .icu From 01e163380f1c9ed8cd105223b2a579f627b526ab Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 2 Oct 2018 14:43:30 +0200 Subject: [PATCH 008/402] Added build disable elfhack patch file --- build-disable-elfhack.patch | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 build-disable-elfhack.patch diff --git a/build-disable-elfhack.patch b/build-disable-elfhack.patch new file mode 100644 index 0000000..11e6a54 --- /dev/null +++ b/build-disable-elfhack.patch @@ -0,0 +1,12 @@ +diff -up firefox-62.0.2/toolkit/moz.configure.elfhack firefox-62.0.2/toolkit/moz.configure +--- firefox-62.0.2/toolkit/moz.configure.elfhack 2018-09-27 14:32:56.549507561 +0200 ++++ firefox-62.0.2/toolkit/moz.configure 2018-09-27 14:33:08.219532121 +0200 +@@ -1195,7 +1195,7 @@ with only_when(has_elfhack): + option('--disable-elf-hack', help='Disable elf hacks') + + set_config('USE_ELF_HACK', +- depends_if('--enable-elf-hack')(lambda _: True)) ++ depends_if('--enable-elf-hack')(lambda _: False)) + + + @depends(check_build_environment) From 72b8b277f2d7ce6430e4e193003dd12428bc4bf1 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 2 Oct 2018 14:58:28 +0200 Subject: [PATCH 009/402] Added clang-devel as BR --- thunderbird.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/thunderbird.spec b/thunderbird.spec index 5795a5e..ec944a0 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -195,6 +195,7 @@ Obsoletes: thunderbird-lightning-gdata <= 1:3.3.0.14 #Obsoletes: thunderbird-52.9.1 BuildRequires: rust BuildRequires: cargo +BuildRequires: clang-devel BuildRequires: python2-devel Suggests: u2f-hidraw-policy From c6fa01d4d1fd3b1322c72994c97c628c772537b1 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 3 Oct 2018 17:23:10 +0200 Subject: [PATCH 010/402] Update to 60.2.1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index aa94189..0f51c38 100644 --- a/.gitignore +++ b/.gitignore @@ -210,3 +210,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.0.source.tar.xz /thunderbird-langpacks-60.0-20180815.tar.xz /l10n-lightning-60.0.tar.xz +/thunderbird-60.2.1.source.tar.xz +/thunderbird-langpacks-60.2.1-20181003.tar.xz +/l10n-lightning-60.2.1.tar.xz diff --git a/sources b/sources index 2f5508d..3e2710f 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.0.source.tar.xz) = ca3346eb4b6e1237a74ffc5c3d483fcad8d2f0d1146f56a4b11f1ab0f83b47b28fb2da8c0344f228bfff8c84b755f46a86a5b44fd7172de387ceb83650b33152 -SHA512 (thunderbird-langpacks-60.0-20180815.tar.xz) = 918c0ce7c38f1c1f7c91f24977c6f922738572dc0ec5af4c03650b8c7d21df5790bae8743cde4758d21a10728d98fd952c9ee228e6cfed5cc7c71a5bfa4033e7 -SHA512 (l10n-lightning-60.0.tar.xz) = 4dd57741b09475cd8fcf0d6c6a61d3a56dd7aa2077d5cbf2c16d5841e150cc3add9fb155daa822b565ad15fc1ba7d1bc1424bc3bb2d1eb946b0d2606a6009221 +SHA512 (thunderbird-60.2.1.source.tar.xz) = d74da3c90658c5baf09c22760cad31594524c09f2cd5aba81c5b15bb6db64d78f613562cb015d8a725b4902caa4a57a2d1dafce28284533747faed00f8268a02 +SHA512 (thunderbird-langpacks-60.2.1-20181003.tar.xz) = c8ac34e9d8f8bd996b9a17f59dc4266f3c5b9c283f6d1fdc693ed3d64dc8fc43992304b07b7941c026c350351da85700ef99c6b2550c3530582db4b262c2a563 +SHA512 (l10n-lightning-60.2.1.tar.xz) = 1c686cf889908792d979fd2a2811da8e82f2eef4ff27b1430c2842aaa2c50996b52c52fe5b2504ff419fc0b3e9791f453be14a02640f633210eef7c39e83c4ab diff --git a/thunderbird.spec b/thunderbird.spec index ec944a0..14f9733 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -88,14 +88,14 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.0 +Version: 60.2.1 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20180815.tar.xz +Source1: thunderbird-langpacks-%{version}-20181003.tar.xz %endif # Locales for lightning Source2: l10n-lightning-%{version}.tar.xz @@ -693,6 +693,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Oct 3 2018 Jan Horak - 60.2.1-1 +- Update to 60.2.1 + * Wed Aug 15 2018 Jan Horak - 60.0-1 - Update to 60.0 - Removing gdata-provider extension because it's no longer provided by Thunderbird From 78bde015a4168ff4f45ed5bf748e46dd22ceab75 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 4 Oct 2018 10:44:47 +0200 Subject: [PATCH 011/402] Added patch to mozbz#1460871 --- mozilla-1460871-ldap-query.patch | 164 +++++++++++++++++++++++++++++++ thunderbird.spec | 7 +- 2 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 mozilla-1460871-ldap-query.patch diff --git a/mozilla-1460871-ldap-query.patch b/mozilla-1460871-ldap-query.patch new file mode 100644 index 0000000..2f9c23d --- /dev/null +++ b/mozilla-1460871-ldap-query.patch @@ -0,0 +1,164 @@ +diff -up thunderbird-60.2.1/comm/ldap/xpcom/public/nsILDAPOperation.idl.1460871-ldap-query thunderbird-60.2.1/comm/ldap/xpcom/public/nsILDAPOperation.idl +--- thunderbird-60.2.1/comm/ldap/xpcom/public/nsILDAPOperation.idl.1460871-ldap-query 2018-10-01 16:52:39.000000000 +0200 ++++ thunderbird-60.2.1/comm/ldap/xpcom/public/nsILDAPOperation.idl 2018-10-04 09:40:04.491575949 +0200 +@@ -52,6 +52,10 @@ interface nsILDAPOperation : nsISupports + * private parameter (anything caller desires) + */ + attribute nsISupports closure; ++ /** ++ * number of the request for compare that the request is still valid. ++ */ ++ attribute unsigned long requestNum; + + /** + * No time and/or size limit specified +diff -up thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.cpp.1460871-ldap-query thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.cpp +--- thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.cpp.1460871-ldap-query 2018-10-01 16:52:39.000000000 +0200 ++++ thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.cpp 2018-10-04 09:40:04.491575949 +0200 +@@ -400,6 +400,19 @@ convertControlArray(nsIArray *aXpcomArra + return NS_OK; + } + ++ /* attribute unsigned long requestNum; */ ++NS_IMETHODIMP nsLDAPOperation::GetRequestNum(uint32_t *aRequestNum) ++{ ++ *aRequestNum = mRequestNum; ++ return NS_OK; ++} ++ ++NS_IMETHODIMP nsLDAPOperation::SetRequestNum(uint32_t aRequestNum) ++{ ++ mRequestNum = aRequestNum; ++ return NS_OK; ++} ++ + NS_IMETHODIMP + nsLDAPOperation::SearchExt(const nsACString& aBaseDn, int32_t aScope, + const nsACString& aFilter, +diff -up thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.h.1460871-ldap-query thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.h +--- thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.h.1460871-ldap-query 2018-10-01 16:52:39.000000000 +0200 ++++ thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.h 2018-10-04 09:40:04.491575949 +0200 +@@ -36,6 +36,8 @@ class nsLDAPOperation : public nsILDAPOp + * used to break cycles + */ + void Clear(); ++ // Stores the request number for later check of the operation is still valid ++ int32_t mRequestNum; + + private: + virtual ~nsLDAPOperation(); +diff -up thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp.1460871-ldap-query thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp +--- thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp.1460871-ldap-query 2018-10-01 16:52:43.000000000 +0200 ++++ thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp 2018-10-04 09:40:55.334670404 +0200 +@@ -22,6 +22,8 @@ + + using namespace mozilla; + ++extern mozilla::LazyLogModule gLDAPLogModule; // defined in nsLDAPService.cpp ++ + // nsAbLDAPListenerBase inherits nsILDAPMessageListener + class nsAbQueryLDAPMessageListener : public nsAbLDAPListenerBase + { +@@ -66,7 +68,6 @@ protected: + + bool mFinished; + bool mCanceled; +- bool mWaitingForPrevQueryToFinish; + + nsCOMPtr mServerSearchControls; + nsCOMPtr mClientSearchControls; +@@ -94,7 +95,6 @@ nsAbQueryLDAPMessageListener::nsAbQueryL + mResultLimit(resultLimit), + mFinished(false), + mCanceled(false), +- mWaitingForPrevQueryToFinish(false), + mServerSearchControls(serverSearchControls), + mClientSearchControls(clientSearchControls) + { +@@ -116,9 +116,6 @@ nsresult nsAbQueryLDAPMessageListener::C + return NS_OK; + + mCanceled = true; +- if (!mFinished) +- mWaitingForPrevQueryToFinish = true; +- + return NS_OK; + } + +@@ -129,6 +126,8 @@ NS_IMETHODIMP nsAbQueryLDAPMessageListen + + int32_t messageType; + rv = aMessage->GetType(&messageType); ++ uint32_t requestNum; ++ mOperation->GetRequestNum(&requestNum); + NS_ENSURE_SUCCESS(rv, rv); + + bool cancelOperation = false; +@@ -137,6 +136,14 @@ NS_IMETHODIMP nsAbQueryLDAPMessageListen + { + MutexAutoLock lock (mLock); + ++ if (requestNum != sCurrentRequestNum) { ++ MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug, ++ ("nsAbQueryLDAPMessageListener::OnLDAPMessage: Ignoring message with " ++ "request num %d, current request num is %d.", ++ requestNum, sCurrentRequestNum)); ++ return NS_OK; ++ } ++ + if (mFinished) + return NS_OK; + +@@ -166,11 +173,10 @@ NS_IMETHODIMP nsAbQueryLDAPMessageListen + rv = OnLDAPMessageSearchResult(aMessage); + break; + case nsILDAPMessage::RES_SEARCH_ENTRY: +- if (!mFinished && !mWaitingForPrevQueryToFinish) ++ if (!mFinished) + rv = OnLDAPMessageSearchEntry(aMessage); + break; + case nsILDAPMessage::RES_SEARCH_RESULT: +- mWaitingForPrevQueryToFinish = false; + rv = OnLDAPMessageSearchResult(aMessage); + NS_ENSURE_SUCCESS(rv, rv); + break; +@@ -207,6 +213,8 @@ nsresult nsAbQueryLDAPMessageListener::D + rv = mOperation->Init(mConnection, this, nullptr); + NS_ENSURE_SUCCESS(rv, rv); + ++ mOperation->SetRequestNum(++sCurrentRequestNum); ++ + nsAutoCString dn; + rv = mSearchUrl->GetDn(dn); + NS_ENSURE_SUCCESS(rv, rv); +diff -up thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp.1460871-ldap-query thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp +--- thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp.1460871-ldap-query 2018-10-01 16:52:43.000000000 +0200 ++++ thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp 2018-10-04 09:40:04.492575951 +0200 +@@ -20,6 +20,8 @@ + + using namespace mozilla; + ++uint32_t nsAbLDAPListenerBase::sCurrentRequestNum = 0; ++ + nsAbLDAPListenerBase::nsAbLDAPListenerBase(nsILDAPURL* url, + nsILDAPConnection* connection, + const nsACString &login, +@@ -249,6 +251,7 @@ NS_IMETHODIMP nsAbLDAPListenerBase::OnLD + InitFailed(); + return rv; + } ++ mOperation->SetRequestNum(++sCurrentRequestNum); + + // Try non-password mechanisms first + if (mSaslMechanism.EqualsLiteral("GSSAPI")) +diff -up thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.h.1460871-ldap-query thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.h +--- thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.h.1460871-ldap-query 2018-10-01 16:52:43.000000000 +0200 ++++ thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.h 2018-10-04 09:40:04.492575951 +0200 +@@ -47,6 +47,7 @@ protected: + int32_t mTimeOut; + bool mBound; + bool mInitialized; ++ static uint32_t sCurrentRequestNum; + + mozilla::Mutex mLock; + }; diff --git a/thunderbird.spec b/thunderbird.spec index 14f9733..6111ed8 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -89,7 +89,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.2.1 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -126,6 +126,7 @@ Patch305: build-big-endian.patch Patch306: mozilla-1353817.patch Patch307: build-disable-elfhack.patch Patch308: build-triplet-failure.patch +Patch309: mozilla-1460871-ldap-query.patch # Fedora specific patches @@ -238,6 +239,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch304 -p1 -b .1245783 %patch308 -p1 -b .triplet-failure +%patch309 -p1 -b .1460871-ldap-query # Patch for big endian platforms only %if 0%{?big_endian} %patch26 -p1 -b .icu @@ -693,8 +695,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog -* Wed Oct 3 2018 Jan Horak - 60.2.1-1 +* Wed Oct 3 2018 Jan Horak - 60.2.1-2 - Update to 60.2.1 +- Added fix for rhbz#1546988 * Wed Aug 15 2018 Jan Horak - 60.0-1 - Update to 60.0 From 2ac34672c3b22858696b46a6ace89533a710a7c6 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 30 Oct 2018 16:21:52 +0100 Subject: [PATCH 012/402] Fixed calendar langpacks --- .gitignore | 1 + get-calendar-langpacks.sh | 126 ++++++++++++++++++++++++++++++++++++++ mklangsource.sh | 52 ---------------- sources | 1 + thunderbird-mozconfig | 1 - thunderbird.spec | 27 +++----- 6 files changed, 137 insertions(+), 71 deletions(-) create mode 100755 get-calendar-langpacks.sh delete mode 100755 mklangsource.sh diff --git a/.gitignore b/.gitignore index 0f51c38..4c6e54e 100644 --- a/.gitignore +++ b/.gitignore @@ -213,3 +213,4 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.2.1.source.tar.xz /thunderbird-langpacks-60.2.1-20181003.tar.xz /l10n-lightning-60.2.1.tar.xz +/lightning-langpacks-60.2.1.tar.xz diff --git a/get-calendar-langpacks.sh b/get-calendar-langpacks.sh new file mode 100755 index 0000000..d3f5e86 --- /dev/null +++ b/get-calendar-langpacks.sh @@ -0,0 +1,126 @@ +#!/bin/bash +#set -x +set -e +usage() +{ +cat << EOF +usage: $0 options + +This script downloads calendar langpacks for Thunderbird. + +OPTIONS: + -h Show this message + -v Version string (7.0.1) + -b Build number (1, 2, 3) + -r Reuse downloaded files (when you don't want to redownload) +EOF +} + +VER= +BUILDNUM= +LANG_DATE=`date "+%Y%m%d"` +while getopts “hv:b:r” OPTION +do + case $OPTION in + h) + usage + exit 1 + ;; + v) + VER=$OPTARG + ;; + b) + BUILDNUM=$OPTARG + ;; + ?) + usage + exit + ;; + esac +done + +if [ -z "$VER" -o -z "$BUILDNUM" ] +then + echo "Missing version or build number." + usage + exit 1 +fi + +WHITE='\033[1;33m' +NC='\033[0m' # No Color + +LOCALES=`curl -f https://archive.mozilla.org/pub/thunderbird/candidates/$VER-candidates/build$BUILDNUM/linux-i686/ | grep "a href"|sed -e "s|.*/\([^/]*\)/\".*|\1|"|tail -n+2 |grep -v xpi` +#echo $LOCALES +rm -rf lightning-langpacks +mkdir -p lightning-langpacks +cd lightning-langpacks +LOCALE_COUNT=`echo $LOCALES| tr ' ' '\n' | wc -l` +LOCALE_NUM=0 +for lang in $LOCALES; do + LOCALE_NUM=$((LOCALE_NUM+1)) + echo -e "${WHITE}Processing calendar locale: $lang ($LOCALE_NUM/$LOCALE_COUNT)${NC}" + mkdir -p extracted_lightning + mkdir -p calendar-locales + #echo Downloading TB binary for locale: $lang + wget --quiet https://archive.mozilla.org/pub/thunderbird/candidates/$VER-candidates/build$BUILDNUM/linux-i686/$lang/thunderbird-$VER.tar.bz2 + + cd extracted_lightning + tar -xf ../thunderbird-$VER.tar.bz2 thunderbird/distribution/extensions/\{e2fda1a4-762b-4020-b5ad-a41df1933103\}.xpi + set +e + unzip -qq thunderbird/distribution/extensions/\{e2fda1a4-762b-4020-b5ad-a41df1933103\}.xpi + set -e + LIGHTNING_VERSION=`cat app.ini |grep "^Version="|sed -e 's/Version=//'` + BUILD_ID=`cat app.ini |grep "^BuildID="|sed -e 's/BuildID=//'` + MAX_VERSION=`cat app.ini |grep MaxVersion|sed -e s/MaxVersion=//` + MIN_VERSION=`cat app.ini |grep MinVersion|sed -e s/MinVersion=//` + rm -rf thunderbird + mkdir -p ../calendar-locales/chrome + cp -r chrome/calendar-$lang ../calendar-locales/chrome + cp -r chrome/lightning-$lang ../calendar-locales/chrome + cd - + + cd calendar-locales + # create manifest + cat > manifest.json <> .mozconfig echo "ac_add_options --disable-crashreporter" >> .mozconfig %endif -# install lightning langpacks -cd .. -%{__tar} xf %{SOURCE2} -cd - #=============================================================================== %build @@ -466,17 +462,6 @@ MOZ_SMP_FLAGS=-j1 export MOZ_MAKE_FLAGS="$MOZ_SMP_FLAGS" export STRIP=/bin/true ./mach build -#make -f client.mk build STRIP="/bin/true" MOZ_MAKE_FLAGS="$MOZ_SMP_FLAGS" - -# Package l10n files -cd %{objdir}/comm/calendar/lightning -grep -v 'osx' ../../../calendar/locales/shipped-locales | while read lang x -do - make AB_CD=en-US L10N_XPI_NAME=lightning libs-$lang -done -# install l10n files -make tools -cd - # create debuginfo for crash-stats.mozilla.com %if %{enable_mozilla_crashreporter} @@ -548,6 +533,12 @@ for langpack in `ls thunderbird-langpacks/*.xpi`; do echo "%%lang($language) %{langpackdir}/${extensionID}.xpi" >> %{name}.lang done %{__rm} -rf thunderbird-langpacks + +# lightning langpacks install +cd %{buildroot}%{langpackdir} +%{__tar} xf %{SOURCE2} +chmod a+r *.xpi +cd - %endif # build_langpacks # Get rid of devel package and its debugsymbols From e436bf67f096bb16a6f737c195005112047b7ed9 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 30 Oct 2018 17:22:08 +0100 Subject: [PATCH 013/402] Update to 60.3.0 --- .gitignore | 3 +++ build-triplet-failure.patch | 18 ------------------ sources | 7 +++---- thunderbird.spec | 11 ++++++----- 4 files changed, 12 insertions(+), 27 deletions(-) delete mode 100644 build-triplet-failure.patch diff --git a/.gitignore b/.gitignore index 4c6e54e..53a1369 100644 --- a/.gitignore +++ b/.gitignore @@ -214,3 +214,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-langpacks-60.2.1-20181003.tar.xz /l10n-lightning-60.2.1.tar.xz /lightning-langpacks-60.2.1.tar.xz +/thunderbird-60.3.0.source.tar.xz +/thunderbird-langpacks-60.3.0-20181030.tar.xz +/lightning-langpacks-60.3.0.tar.xz diff --git a/build-triplet-failure.patch b/build-triplet-failure.patch deleted file mode 100644 index 068d27c..0000000 --- a/build-triplet-failure.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff -up thunderbird-60.0/build/moz.configure/init.configure.triplet-failure thunderbird-60.0/build/moz.configure/init.configure ---- thunderbird-60.0/build/moz.configure/init.configure.triplet-failure 2018-10-02 14:13:04.276835572 +0200 -+++ thunderbird-60.0/build/moz.configure/init.configure 2018-10-02 14:13:18.921865210 +0200 -@@ -577,7 +577,13 @@ def split_triplet(triplet, allow_unknown - # There is also a quartet form: - # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM - # But we can consider the "KERNEL-OPERATING_SYSTEM" as one. -- cpu, manufacturer, os = triplet.split('-', 2) -+ parts = triplet.split('-', 2) -+ if len(parts) == 3: -+ cpu, _, os = parts -+ elif len(parts) == 2: -+ cpu, os = parts -+ else: -+ die("Unexpected triplet string: %s" % triplet) - - # Autoconf uses config.sub to validate and canonicalize those triplets, - # but the granularity of its results has never been satisfying to our diff --git a/sources b/sources index 1569963..62ce96c 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ -SHA512 (thunderbird-60.2.1.source.tar.xz) = d74da3c90658c5baf09c22760cad31594524c09f2cd5aba81c5b15bb6db64d78f613562cb015d8a725b4902caa4a57a2d1dafce28284533747faed00f8268a02 -SHA512 (thunderbird-langpacks-60.2.1-20181003.tar.xz) = c8ac34e9d8f8bd996b9a17f59dc4266f3c5b9c283f6d1fdc693ed3d64dc8fc43992304b07b7941c026c350351da85700ef99c6b2550c3530582db4b262c2a563 -SHA512 (l10n-lightning-60.2.1.tar.xz) = 1c686cf889908792d979fd2a2811da8e82f2eef4ff27b1430c2842aaa2c50996b52c52fe5b2504ff419fc0b3e9791f453be14a02640f633210eef7c39e83c4ab -SHA512 (lightning-langpacks-60.2.1.tar.xz) = 9b9edaba374d7fae103b42b2ca2add51807846ae93c57221407cd72818c78f5adeb70deef2a6bb3de54eccc99eba10e2a0f793e5c6e923328e5efc8a8497dedb +SHA512 (thunderbird-60.3.0.source.tar.xz) = 6cc390129dd2ce30c4685748bc5cdbf07c1326bf1ba4727d34b105f800ee3d0c7344a1bda3b8f6a666f635eb6d2fba7da5afb1222aac05a536d2dd77afb3a8d3 +SHA512 (thunderbird-langpacks-60.3.0-20181030.tar.xz) = 61e8a37ea8c17636f55b52d76bcdef412061dfa494a4d3e7dce6bbc7a699995f277912595f367c2146c231742147df6c7334a7a3d26e143a1cae24f02cd8bd41 +SHA512 (lightning-langpacks-60.3.0.tar.xz) = 5cf4fe7d75124210726536eeb39c774b831ef0c8edbca0afd1ffcc6ed622704535fb063718b1af88e77cbe52b20d5d45b8283b7131051363bb387cbe3dddfe0f diff --git a/thunderbird.spec b/thunderbird.spec index edec5f5..779dfbf 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -88,14 +88,14 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.2.1 -Release: 2%{?dist} +Version: 60.3.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20181003.tar.xz +Source1: thunderbird-langpacks-%{version}-20181030.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -125,7 +125,6 @@ Patch304: mozilla-1245783.patch Patch305: build-big-endian.patch Patch306: mozilla-1353817.patch Patch307: build-disable-elfhack.patch -Patch308: build-triplet-failure.patch Patch309: mozilla-1460871-ldap-query.patch # Fedora specific patches @@ -238,7 +237,6 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch104 -p1 -b .gcc6 %patch304 -p1 -b .1245783 -%patch308 -p1 -b .triplet-failure %patch309 -p1 -b .1460871-ldap-query # Patch for big endian platforms only %if 0%{?big_endian} @@ -686,6 +684,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Oct 30 2018 Jan Horak - 60.3.0-1 +- Update to 60.3.0 + * Wed Oct 3 2018 Jan Horak - 60.2.1-2 - Update to 60.2.1 - Added fix for rhbz#1546988 From b50d537124eae35b7dda6b92a7726c00bba6dbcc Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 6 Nov 2018 11:30:12 +0100 Subject: [PATCH 014/402] Disabled DBus remote --- disable-dbus-remote.patch | 12 ++++++++++++ thunderbird.spec | 2 ++ 2 files changed, 14 insertions(+) create mode 100644 disable-dbus-remote.patch diff --git a/disable-dbus-remote.patch b/disable-dbus-remote.patch new file mode 100644 index 0000000..72040f2 --- /dev/null +++ b/disable-dbus-remote.patch @@ -0,0 +1,12 @@ +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/thunderbird.spec b/thunderbird.spec index 779dfbf..13532c3 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -128,6 +128,7 @@ Patch307: build-disable-elfhack.patch Patch309: mozilla-1460871-ldap-query.patch # Fedora specific patches +Patch310: disable-dbus-remote.patch # Upstream patches @@ -243,6 +244,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %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 From a256e6800b5398708713e8f9253a169826a4d40c Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 6 Nov 2018 11:32:21 +0100 Subject: [PATCH 015/402] Changelog update + release up --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 13532c3..204815e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -89,7 +89,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.3.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -686,6 +686,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Nov 6 Martin Stransky - 60.3.0-2 +- Disabled DBus remote + * Tue Oct 30 2018 Jan Horak - 60.3.0-1 - Update to 60.3.0 From 5be96046e101859fa61439331a8a17e610fb83ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Tue, 13 Nov 2018 15:59:13 +0000 Subject: [PATCH 016/402] rebuild for hunspell-1.7.0 --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 204815e..71750ba 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -89,7 +89,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.3.0 -Release: 2%{?dist} +Release: 3%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -686,6 +686,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Nov 13 2018 Caolán McNamara - 60.3.0-3 +- rebuild for hunspell-1.7.0 + * Tue Nov 6 Martin Stransky - 60.3.0-2 - Disabled DBus remote From f15f217198dc0731fdf7b2770ef6052adf3586c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Tue, 13 Nov 2018 16:04:18 +0000 Subject: [PATCH 017/402] fix date --- thunderbird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 71750ba..3a8955c 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -689,7 +689,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : * Tue Nov 13 2018 Caolán McNamara - 60.3.0-3 - rebuild for hunspell-1.7.0 -* Tue Nov 6 Martin Stransky - 60.3.0-2 +* Tue Nov 6 2018 Martin Stransky - 60.3.0-2 - Disabled DBus remote * Tue Oct 30 2018 Jan Horak - 60.3.0-1 From f9e5809e1179fa199d6bc94634fb4e8012ec68d6 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 20 Nov 2018 13:38:58 +0100 Subject: [PATCH 018/402] Enabled Wayland support --- firefox-wayland.patch | 8831 +++++++++++++++++++++++++++++++++ thunderbird-dbus-remote.patch | 188 + thunderbird-mozconfig | 2 +- thunderbird-wayland.desktop | 30 + thunderbird-wayland.sh.in | 7 + thunderbird.sh.in | 7 + thunderbird.spec | 70 +- 7 files changed, 9104 insertions(+), 31 deletions(-) create mode 100644 firefox-wayland.patch create mode 100644 thunderbird-dbus-remote.patch create mode 100644 thunderbird-wayland.desktop create mode 100644 thunderbird-wayland.sh.in diff --git a/firefox-wayland.patch b/firefox-wayland.patch new file mode 100644 index 0000000..d5d1306 --- /dev/null +++ b/firefox-wayland.patch @@ -0,0 +1,8831 @@ +diff -up thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp.wayland thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp +--- thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp 2018-11-20 12:04:43.731787368 +0100 +@@ -24,7 +24,7 @@ static gboolean checkbox_check_state; + static gboolean notebook_has_tab_gap; + + static ScrollbarGTKMetrics sScrollbarMetrics[2]; +-static ScrollbarGTKMetrics sScrollbarMetricsActive[2]; ++static ScrollbarGTKMetrics sActiveScrollbarMetrics[2]; + static ToggleGTKMetrics sCheckboxMetrics; + static ToggleGTKMetrics sRadioMetrics; + static ToolbarGTKMetrics sToolbarMetrics; +@@ -39,6 +39,28 @@ static ToolbarGTKMetrics sToolbarMetrics + #endif + + static GtkBorder ++operator-(const GtkBorder& first, const GtkBorder& second) ++{ ++ GtkBorder result; ++ result.left = first.left - second.left; ++ result.right = first.right - second.right; ++ result.top = first.top - second.top; ++ result.bottom = first.bottom - second.bottom; ++ return result; ++} ++ ++static GtkBorder ++operator+(const GtkBorder& first, const GtkBorder& second) ++{ ++ GtkBorder result; ++ result.left = first.left + second.left; ++ result.right = first.right + second.right; ++ result.top = first.top + second.top; ++ result.bottom = first.bottom + second.bottom; ++ return result; ++} ++ ++static GtkBorder + operator+=(GtkBorder& first, const GtkBorder& second) + { + first.left += second.left; +@@ -84,7 +106,7 @@ moz_gtk_add_style_border(GtkStyleContext + { + GtkBorder border; + +- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); ++ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); + + *left += border.left; + *right += border.right; +@@ -98,7 +120,7 @@ moz_gtk_add_style_padding(GtkStyleContex + { + GtkBorder padding; + +- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); ++ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); + + *left += padding.left; + *right += padding.right; +@@ -193,8 +215,8 @@ moz_gtk_refresh() + + sScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; + sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; +- sScrollbarMetricsActive[GTK_ORIENTATION_HORIZONTAL].initialized = false; +- sScrollbarMetricsActive[GTK_ORIENTATION_VERTICAL].initialized = false; ++ sActiveScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; ++ sActiveScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; + sCheckboxMetrics.initialized = false; + sRadioMetrics.initialized = false; + sToolbarMetrics.initialized = false; +@@ -229,8 +251,8 @@ moz_gtk_get_focus_outline_size(GtkStyleC + { + GtkBorder border; + GtkBorder padding; +- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); +- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); ++ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); ++ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); + *focus_h_width = border.left + padding.left; + *focus_v_width = border.top + padding.top; + return MOZ_GTK_SUCCESS; +@@ -688,8 +710,8 @@ calculate_button_inner_rect(GtkWidget* b + style = gtk_widget_get_style_context(button); + + /* This mirrors gtkbutton's child positioning */ +- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); +- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); ++ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); ++ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); + + inner_rect->x = rect->x + border.left + padding.left; + inner_rect->y = rect->y + padding.top + border.top; +@@ -1008,19 +1030,21 @@ moz_gtk_scrollbar_thumb_paint(WidgetNode + GtkTextDirection direction) + { + GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); ++ GtkStyleContext* style = GetStyleContext(widget, direction, state_flags); ++ ++ GtkOrientation orientation = (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ? ++ GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; + + GdkRectangle rect = *aRect; +- GtkStyleContext* style = GetStyleContext(widget, direction, state_flags); +- InsetByMargin(&rect, style); + +- gtk_render_slider(style, cr, +- rect.x, +- rect.y, +- rect.width, +- rect.height, +- (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ? +- GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); ++ const ScrollbarGTKMetrics* metrics = ++ (state->depressed || state->active || state->inHover) ? ++ GetActiveScrollbarMetrics(orientation) : ++ GetScrollbarMetrics(orientation); ++ Inset(&rect, metrics->margin.thumb); + ++ gtk_render_slider(style, cr, rect.x, rect.y, rect.width, rect.height, ++ orientation); + + return MOZ_GTK_SUCCESS; + } +@@ -1217,7 +1241,7 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRect + GtkStyleContext* style) + { + gint x = rect->x, y = rect->y, width = rect->width, height = rect->height; +- int draw_focus_outline_only = state->depressed; // NS_THEME_FOCUS_OUTLINE ++ int draw_focus_outline_only = state->depressed; // StyleAppearance::FocusOutline + + if (draw_focus_outline_only) { + // Inflate the given 'rect' with the focus outline size. +@@ -1621,7 +1645,7 @@ moz_gtk_toolbar_separator_paint(cairo_t + rect->height * (end_fraction - start_fraction)); + } else { + GtkBorder padding; +- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); ++ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); + + paint_width = padding.left; + if (paint_width > rect->width) +@@ -1790,7 +1814,7 @@ moz_gtk_get_tab_thickness(GtkStyleContex + return 0; /* tabs do not overdraw the tabpanel border with "no gap" style */ + + GtkBorder border; +- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); ++ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); + if (border.top < 2) + return 2; /* some themes don't set ythickness correctly */ + +@@ -2127,7 +2151,7 @@ moz_gtk_menu_separator_paint(cairo_t *cr + GtkBorder padding; + + style = GetStyleContext(MOZ_GTK_MENUSEPARATOR, direction); +- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); ++ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); + + x = rect->x; + y = rect->y; +@@ -2433,7 +2457,7 @@ moz_gtk_get_widget_border(WidgetNodeType + NULL); + + if (!wide_separators) { +- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, ++ gtk_style_context_get_border(style, gtk_style_context_get_state(style), + &border); + separator_width = border.left; + } +@@ -2606,13 +2630,13 @@ moz_gtk_get_tab_border(gint* left, gint* + } else { + GtkBorder margin; + +- gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin); ++ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), &margin); + *left += margin.left; + *right += margin.right; + + if (flags & MOZ_GTK_TAB_FIRST) { + style = GetStyleContext(MOZ_GTK_NOTEBOOK_HEADER, direction); +- gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin); ++ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), &margin); + *left += margin.left; + *right += margin.right; + } +@@ -2687,7 +2711,7 @@ moz_gtk_get_toolbar_separator_width(gint + "separator-width", &separator_width, + NULL); + /* Just in case... */ +- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); ++ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); + *size = MAX(*size, (wide_separators ? separator_width : border.left)); + return MOZ_GTK_SUCCESS; + } +@@ -2718,7 +2742,7 @@ moz_gtk_get_menu_separator_height(gint * + gint separator_height; + GtkBorder padding; + GtkStyleContext* style = GetStyleContext(MOZ_GTK_MENUSEPARATOR); +- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); ++ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); + + gtk_style_context_save(style); + gtk_style_context_add_class(style, GTK_STYLE_CLASS_SEPARATOR); +@@ -2750,8 +2774,8 @@ moz_gtk_get_entry_min_height(gint* heigh + + GtkBorder border; + GtkBorder padding; +- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); +- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); ++ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); ++ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); + + *height += (border.top + border.bottom + padding.top + padding.bottom); + } +@@ -2901,23 +2925,17 @@ GetToggleMetrics(bool isRadio) + return metrics; + } + +-const ScrollbarGTKMetrics* +-GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive) ++static void ++InitScrollbarMetrics(ScrollbarGTKMetrics* aMetrics, ++ GtkOrientation aOrientation, ++ GtkStateFlags aStateFlags) + { +- auto metrics = aActive ? &sScrollbarMetricsActive[aOrientation] : +- &sScrollbarMetrics[aOrientation]; +- if (metrics->initialized) +- return metrics; +- +- metrics->initialized = true; +- + WidgetNodeType scrollbar = aOrientation == GTK_ORIENTATION_HORIZONTAL ? + MOZ_GTK_SCROLLBAR_HORIZONTAL : MOZ_GTK_SCROLLBAR_VERTICAL; + + gboolean backward, forward, secondary_backward, secondary_forward; + GtkStyleContext* style = GetStyleContext(scrollbar, GTK_TEXT_DIR_NONE, +- aActive ? GTK_STATE_FLAG_PRELIGHT : +- GTK_STATE_FLAG_NORMAL); ++ aStateFlags); + gtk_style_context_get_style(style, + "has-backward-stepper", &backward, + "has-forward-stepper", &forward, +@@ -2938,15 +2956,15 @@ GetScrollbarMetrics(GtkOrientation aOrie + "min-slider-length", &min_slider_size, + nullptr); + +- metrics->size.thumb = ++ aMetrics->size.thumb = + SizeFromLengthAndBreadth(aOrientation, min_slider_size, slider_width); +- metrics->size.button = ++ aMetrics->size.button = + SizeFromLengthAndBreadth(aOrientation, stepper_size, slider_width); + // overall scrollbar + gint breadth = slider_width + 2 * trough_border; + // Require room for the slider in the track if we don't have buttons. + gint length = hasButtons ? 0 : min_slider_size + 2 * trough_border; +- metrics->size.scrollbar = ++ aMetrics->size.scrollbar = + SizeFromLengthAndBreadth(aOrientation, length, breadth); + + // Borders on the major axis are set on the outermost scrollbar +@@ -2956,23 +2974,24 @@ GetScrollbarMetrics(GtkOrientation aOrie + // receives mouse events, as in GTK. + // Other borders have been zero-initialized. + if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { +- metrics->border.scrollbar.left = +- metrics->border.scrollbar.right = +- metrics->border.track.top = +- metrics->border.track.bottom = trough_border; ++ aMetrics->border.scrollbar.left = ++ aMetrics->border.scrollbar.right = ++ aMetrics->border.track.top = ++ aMetrics->border.track.bottom = trough_border; + } else { +- metrics->border.scrollbar.top = +- metrics->border.scrollbar.bottom = +- metrics->border.track.left = +- metrics->border.track.right = trough_border; ++ aMetrics->border.scrollbar.top = ++ aMetrics->border.scrollbar.bottom = ++ aMetrics->border.track.left = ++ aMetrics->border.track.right = trough_border; + } + +- return metrics; ++ // We're done here for Gtk+ < 3.20... ++ return; + } + + // GTK version > 3.20 + // scrollbar +- metrics->border.scrollbar = GetMarginBorderPadding(style); ++ aMetrics->border.scrollbar = GetMarginBorderPadding(style); + + WidgetNodeType contents, track, thumb; + if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { +@@ -3003,72 +3022,102 @@ GetScrollbarMetrics(GtkOrientation aOrie + */ + + // thumb +- style = CreateStyleContextWithStates(thumb, GTK_TEXT_DIR_NONE, +- aActive ? GTK_STATE_FLAG_PRELIGHT : +- GTK_STATE_FLAG_NORMAL); +- metrics->size.thumb = GetMinMarginBox(style); ++ style = CreateStyleContextWithStates(thumb, GTK_TEXT_DIR_NONE, aStateFlags); ++ aMetrics->size.thumb = GetMinMarginBox(style); ++ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), ++ &aMetrics->margin.thumb); + g_object_unref(style); + + // track +- style = CreateStyleContextWithStates(track, GTK_TEXT_DIR_NONE, +- aActive ? GTK_STATE_FLAG_PRELIGHT : +- GTK_STATE_FLAG_NORMAL); +- metrics->border.track = GetMarginBorderPadding(style); +- MozGtkSize trackMinSize = GetMinContentBox(style) + metrics->border.track; +- MozGtkSize trackSizeForThumb = metrics->size.thumb + metrics->border.track; ++ style = CreateStyleContextWithStates(track, GTK_TEXT_DIR_NONE, aStateFlags); ++ aMetrics->border.track = GetMarginBorderPadding(style); ++ MozGtkSize trackMinSize = GetMinContentBox(style) + aMetrics->border.track; ++ MozGtkSize trackSizeForThumb = aMetrics->size.thumb + aMetrics->border.track; + g_object_unref(style); + + // button + if (hasButtons) { + style = CreateStyleContextWithStates(MOZ_GTK_SCROLLBAR_BUTTON, +- GTK_TEXT_DIR_NONE, +- aActive ? GTK_STATE_FLAG_PRELIGHT : +- GTK_STATE_FLAG_NORMAL); +- metrics->size.button = GetMinMarginBox(style); ++ GTK_TEXT_DIR_NONE, aStateFlags); ++ aMetrics->size.button = GetMinMarginBox(style); + g_object_unref(style); + } else { +- metrics->size.button = {0, 0}; ++ aMetrics->size.button = {0, 0}; + } + if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { +- metrics->size.button.Rotate(); ++ aMetrics->size.button.Rotate(); + // If the track is wider than necessary for the thumb, including when + // the buttons will cause Gecko to expand the track to fill + // available breadth, then add to the track border to prevent Gecko + // from expanding the thumb to fill available breadth. + gint extra = + std::max(trackMinSize.height, +- metrics->size.button.height) - trackSizeForThumb.height; ++ aMetrics->size.button.height) - trackSizeForThumb.height; + if (extra > 0) { + // If extra is odd, then the thumb is 0.5 pixels above + // center as in gtk_range_compute_slider_position(). +- metrics->border.track.top += extra / 2; +- metrics->border.track.bottom += extra - extra / 2; ++ aMetrics->border.track.top += extra / 2; ++ aMetrics->border.track.bottom += extra - extra / 2; + // Update size for change in border. + trackSizeForThumb.height += extra; + } + } else { + gint extra = + std::max(trackMinSize.width, +- metrics->size.button.width) - trackSizeForThumb.width; ++ aMetrics->size.button.width) - trackSizeForThumb.width; + if (extra > 0) { + // If extra is odd, then the thumb is 0.5 pixels to the left + // of center as in gtk_range_compute_slider_position(). +- metrics->border.track.left += extra / 2; +- metrics->border.track.right += extra - extra / 2; ++ aMetrics->border.track.left += extra / 2; ++ aMetrics->border.track.right += extra - extra / 2; + trackSizeForThumb.width += extra; + } + } + + style = CreateStyleContextWithStates(contents, GTK_TEXT_DIR_NONE, +- aActive ? GTK_STATE_FLAG_PRELIGHT : +- GTK_STATE_FLAG_NORMAL); ++ aStateFlags); + GtkBorder contentsBorder = GetMarginBorderPadding(style); + g_object_unref(style); + +- metrics->size.scrollbar = +- trackSizeForThumb + contentsBorder + metrics->border.scrollbar; ++ aMetrics->size.scrollbar = ++ trackSizeForThumb + contentsBorder + aMetrics->border.scrollbar; ++} ++ ++const ScrollbarGTKMetrics* ++GetScrollbarMetrics(GtkOrientation aOrientation) ++{ ++ auto metrics = &sScrollbarMetrics[aOrientation]; ++ if (!metrics->initialized) { ++ InitScrollbarMetrics(metrics, aOrientation, GTK_STATE_FLAG_NORMAL); ++ ++ // We calculate thumb margin here because it's composited from ++ // thumb class margin + difference margin between active and inactive ++ // scrollbars. It's a workaround which alows us to emulate ++ // overlay scrollbars for some Gtk+ themes (Ubuntu/Ambiance), ++ // when an inactive scrollbar thumb is smaller than the active one. ++ const ScrollbarGTKMetrics *metricsActive = ++ GetActiveScrollbarMetrics(aOrientation); ++ ++ if (metrics->size.thumb < metricsActive->size.thumb) { ++ metrics->margin.thumb += ++ (metrics->border.scrollbar + metrics->border.track) - ++ (metricsActive->border.scrollbar + metricsActive->border.track); ++ } + +- return metrics; ++ metrics->initialized = true; ++ } ++ return metrics; ++} ++ ++const ScrollbarGTKMetrics* ++GetActiveScrollbarMetrics(GtkOrientation aOrientation) ++{ ++ auto metrics = &sActiveScrollbarMetrics[aOrientation]; ++ if (!metrics->initialized) { ++ InitScrollbarMetrics(metrics, aOrientation, GTK_STATE_FLAG_PRELIGHT); ++ metrics->initialized = true; ++ } ++ return metrics; + } + + /* +@@ -3078,6 +3127,16 @@ GetScrollbarMetrics(GtkOrientation aOrie + bool + GetCSDDecorationSize(GtkWindow *aGtkWindow, GtkBorder* aDecorationSize) + { ++ // Available on GTK 3.20+. ++ static auto sGtkRenderBackgroundGetClip = ++ (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*)) ++ dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip"); ++ ++ if (!sGtkRenderBackgroundGetClip) { ++ *aDecorationSize = {0,0,0,0}; ++ return false; ++ } ++ + GtkStyleContext* context = gtk_widget_get_style_context(GTK_WIDGET(aGtkWindow)); + bool solidDecorations = gtk_style_context_has_class(context, "solid-csd"); + context = GetStyleContext(solidDecorations ? +@@ -3091,54 +3150,32 @@ GetCSDDecorationSize(GtkWindow *aGtkWind + gtk_style_context_get_padding(context, state, &padding); + *aDecorationSize += padding; + +- // Available on GTK 3.20+. +- static auto sGtkRenderBackgroundGetClip = +- (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*)) +- dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip"); + + GtkBorder margin; + gtk_style_context_get_margin(context, state, &margin); + +- GtkBorder extents = {0, 0, 0, 0}; +- if (sGtkRenderBackgroundGetClip) { +- /* Get shadow extents but combine with style margin; use the bigger value. +- */ +- GdkRectangle clip; +- sGtkRenderBackgroundGetClip(context, 0, 0, 0, 0, &clip); +- +- extents.top = -clip.y; +- extents.right = clip.width + clip.x; +- extents.bottom = clip.height + clip.y; +- extents.left = -clip.x; +- +- // Margin is used for resize grip size - it's not present on +- // popup windows. +- if (gtk_window_get_window_type(aGtkWindow) != GTK_WINDOW_POPUP) { +- extents.top = MAX(extents.top, margin.top); +- extents.right = MAX(extents.right, margin.right); +- extents.bottom = MAX(extents.bottom, margin.bottom); +- extents.left = MAX(extents.left, margin.left); +- } +- } else { +- /* If we can't get shadow extents use decoration-resize-handle instead +- * as a workaround. This is inspired by update_border_windows() +- * from gtkwindow.c although this is not 100% accurate as we emulate +- * the extents here. +- */ +- gint handle; +- gtk_widget_style_get(GetWidget(MOZ_GTK_WINDOW), +- "decoration-resize-handle", &handle, +- NULL); +- +- extents.top = handle + margin.top; +- extents.right = handle + margin.right; +- extents.bottom = handle + margin.bottom; +- extents.left = handle + margin.left; ++ /* Get shadow extents but combine with style margin; use the bigger value. ++ */ ++ GdkRectangle clip; ++ sGtkRenderBackgroundGetClip(context, 0, 0, 0, 0, &clip); ++ ++ GtkBorder extents; ++ extents.top = -clip.y; ++ extents.right = clip.width + clip.x; ++ extents.bottom = clip.height + clip.y; ++ extents.left = -clip.x; ++ ++ // Margin is used for resize grip size - it's not present on ++ // popup windows. ++ if (gtk_window_get_window_type(aGtkWindow) != GTK_WINDOW_POPUP) { ++ extents.top = MAX(extents.top, margin.top); ++ extents.right = MAX(extents.right, margin.right); ++ extents.bottom = MAX(extents.bottom, margin.bottom); ++ extents.left = MAX(extents.left, margin.left); + } + + *aDecorationSize += extents; +- +- return (sGtkRenderBackgroundGetClip != nullptr); ++ return true; + } + + /* cairo_t *cr argument has to be a system-cairo. */ +diff -up thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp.wayland thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp +--- thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp 2018-11-20 12:04:43.731787368 +0100 +@@ -40,7 +40,9 @@ GtkCompositorWidget::GtkCompositorWidget + + // Grab the window's visual and depth + XWindowAttributes windowAttrs; +- XGetWindowAttributes(mXDisplay, mXWindow, &windowAttrs); ++ if (!XGetWindowAttributes(mXDisplay, mXWindow, &windowAttrs)) { ++ NS_WARNING("GtkCompositorWidget(): XGetWindowAttributes() failed!"); ++ } + + Visual* visual = windowAttrs.visual; + int depth = windowAttrs.depth; +@@ -50,8 +52,8 @@ GtkCompositorWidget::GtkCompositorWidget + mXDisplay, + mXWindow, + visual, +- depth +- ); ++ depth, ++ aInitData.Shaped()); + } + mClientSize = aInitData.InitialClientSize(); + } +diff -up thunderbird-60.3.0/widget/gtk/gtkdrawing.h.wayland thunderbird-60.3.0/widget/gtk/gtkdrawing.h +--- thunderbird-60.3.0/widget/gtk/gtkdrawing.h.wayland 2018-10-30 12:45:37.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/gtkdrawing.h 2018-11-20 12:04:43.731787368 +0100 +@@ -83,6 +83,9 @@ typedef struct { + GtkBorder scrollbar; + GtkBorder track; + } border; ++ struct { ++ GtkBorder thumb; ++ } margin; + } ScrollbarGTKMetrics; + + typedef struct { +@@ -502,11 +505,17 @@ moz_gtk_get_scalethumb_metrics(GtkOrient + /** + * Get the metrics in GTK pixels for a scrollbar. + * aOrientation: [IN] the scrollbar orientation +- * aActive: [IN] Metricts for scrollbar with mouse pointer over it. +- * + */ + const ScrollbarGTKMetrics* +-GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive = false); ++GetScrollbarMetrics(GtkOrientation aOrientation); ++ ++/** ++ * Get the metrics in GTK pixels for a scrollbar which is active ++ * (selected by mouse pointer). ++ * aOrientation: [IN] the scrollbar orientation ++ */ ++const ScrollbarGTKMetrics* ++GetActiveScrollbarMetrics(GtkOrientation aOrientation); + + /** + * Get the desired size of a dropdown arrow button +diff -up thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp.wayland thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp +--- thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp 2018-11-20 12:04:43.732787365 +0100 +@@ -14,6 +14,7 @@ + #include "mozilla/Likely.h" + #include "mozilla/MiscEvents.h" + #include "mozilla/Preferences.h" ++#include "mozilla/Telemetry.h" + #include "mozilla/TextEventDispatcher.h" + #include "mozilla/TextEvents.h" + #include "WritingModes.h" +@@ -59,6 +60,73 @@ GetEventType(GdkEventKey* aKeyEvent) + } + } + ++class GetEventStateName : public nsAutoCString ++{ ++public: ++ explicit GetEventStateName(guint aState, ++ IMContextWrapper::IMContextID aIMContextID = ++ IMContextWrapper::IMContextID::eUnknown) ++ { ++ if (aState & GDK_SHIFT_MASK) { ++ AppendModifier("shift"); ++ } ++ if (aState & GDK_CONTROL_MASK) { ++ AppendModifier("control"); ++ } ++ if (aState & GDK_MOD1_MASK) { ++ AppendModifier("mod1"); ++ } ++ if (aState & GDK_MOD2_MASK) { ++ AppendModifier("mod2"); ++ } ++ if (aState & GDK_MOD3_MASK) { ++ AppendModifier("mod3"); ++ } ++ if (aState & GDK_MOD4_MASK) { ++ AppendModifier("mod4"); ++ } ++ if (aState & GDK_MOD4_MASK) { ++ AppendModifier("mod5"); ++ } ++ if (aState & GDK_MOD4_MASK) { ++ AppendModifier("mod5"); ++ } ++ switch (aIMContextID) { ++ case IMContextWrapper::IMContextID::eIBus: ++ static const guint IBUS_HANDLED_MASK = 1 << 24; ++ static const guint IBUS_IGNORED_MASK = 1 << 25; ++ if (aState & IBUS_HANDLED_MASK) { ++ AppendModifier("IBUS_HANDLED_MASK"); ++ } ++ if (aState & IBUS_IGNORED_MASK) { ++ AppendModifier("IBUS_IGNORED_MASK"); ++ } ++ break; ++ case IMContextWrapper::IMContextID::eFcitx: ++ static const guint FcitxKeyState_HandledMask = 1 << 24; ++ static const guint FcitxKeyState_IgnoredMask = 1 << 25; ++ if (aState & FcitxKeyState_HandledMask) { ++ AppendModifier("FcitxKeyState_HandledMask"); ++ } ++ if (aState & FcitxKeyState_IgnoredMask) { ++ AppendModifier("FcitxKeyState_IgnoredMask"); ++ } ++ break; ++ default: ++ break; ++ } ++ } ++ ++private: ++ void AppendModifier(const char* aModifierName) ++ { ++ if (!IsEmpty()) { ++ AppendLiteral(" + "); ++ } ++ Append(aModifierName); ++ } ++}; ++ + class GetWritingModeName : public nsAutoCString + { + public: +@@ -281,12 +349,17 @@ IMContextWrapper::IMContextWrapper(nsWin + , mCompositionStart(UINT32_MAX) + , mProcessingKeyEvent(nullptr) + , mCompositionState(eCompositionState_NotComposing) ++ , mIMContextID(IMContextID::eUnknown) + , mIsIMFocused(false) ++ , mFallbackToKeyEvent(false) ++ , mKeyboardEventWasDispatched(false) + , mIsDeletingSurrounding(false) + , mLayoutChanged(false) + , mSetCursorPositionOnKeyEvent(true) + , mPendingResettingIMContext(false) + , mRetrieveSurroundingSignalReceived(false) ++ , mMaybeInDeadKeySequence(false) ++ , mIsIMInAsyncKeyHandlingMode(false) + { + static bool sFirstInstance = true; + if (sFirstInstance) { +@@ -299,15 +372,101 @@ IMContextWrapper::IMContextWrapper(nsWin + Init(); + } + ++static bool ++IsIBusInSyncMode() ++{ ++ // See ibus_im_context_class_init() in client/gtk2/ibusimcontext.c ++ // https://github.com/ibus/ibus/blob/86963f2f94d1e4fc213b01c2bc2ba9dcf4b22219/client/gtk2/ibusimcontext.c#L610 ++ const char* env = PR_GetEnv("IBUS_ENABLE_SYNC_MODE"); ++ ++ // See _get_boolean_env() in client/gtk2/ibusimcontext.c ++ // https://github.com/ibus/ibus/blob/86963f2f94d1e4fc213b01c2bc2ba9dcf4b22219/client/gtk2/ibusimcontext.c#L520-L537 ++ if (!env) { ++ return false; ++ } ++ nsDependentCString envStr(env); ++ if (envStr.IsEmpty() || ++ envStr.EqualsLiteral("0") || ++ envStr.EqualsLiteral("false") || ++ envStr.EqualsLiteral("False") || ++ envStr.EqualsLiteral("FALSE")) { ++ return false; ++ } ++ return true; ++} ++ ++static bool ++GetFcitxBoolEnv(const char* aEnv) ++{ ++ // See fcitx_utils_get_boolean_env in src/lib/fcitx-utils/utils.c ++ // https://github.com/fcitx/fcitx/blob/0c87840dc7d9460c2cb5feaeefec299d0d3d62ec/src/lib/fcitx-utils/utils.c#L721-L736 ++ const char* env = PR_GetEnv(aEnv); ++ if (!env) { ++ return false; ++ } ++ nsDependentCString envStr(env); ++ if (envStr.IsEmpty() || ++ envStr.EqualsLiteral("0") || ++ envStr.EqualsLiteral("false")) { ++ return false; ++ } ++ return true; ++} ++ ++static bool ++IsFcitxInSyncMode() ++{ ++ // See fcitx_im_context_class_init() in src/frontend/gtk2/fcitximcontext.c ++ // https://github.com/fcitx/fcitx/blob/78b98d9230dc9630e99d52e3172bdf440ffd08c4/src/frontend/gtk2/fcitximcontext.c#L395-L398 ++ return GetFcitxBoolEnv("IBUS_ENABLE_SYNC_MODE") || ++ GetFcitxBoolEnv("FCITX_ENABLE_SYNC_MODE"); ++} ++ ++nsDependentCSubstring ++IMContextWrapper::GetIMName() const ++{ ++ const char* contextIDChar = ++ gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(mContext)); ++ if (!contextIDChar) { ++ return nsDependentCSubstring(); ++ } ++ ++ nsDependentCSubstring im(contextIDChar, strlen(contextIDChar)); ++ ++ // If the context is XIM, actual engine must be specified with ++ // |XMODIFIERS=@im=foo|. ++ const char* xmodifiersChar = PR_GetEnv("XMODIFIERS"); ++ if (!im.EqualsLiteral("xim") || !xmodifiersChar) { ++ return im; ++ } ++ ++ nsDependentCString xmodifiers(xmodifiersChar); ++ int32_t atIMValueStart = xmodifiers.Find("@im=") + 4; ++ if (atIMValueStart < 4 || ++ xmodifiers.Length() <= static_cast(atIMValueStart)) { ++ return im; ++ } ++ ++ int32_t atIMValueEnd = ++ xmodifiers.Find("@", false, atIMValueStart); ++ if (atIMValueEnd > atIMValueStart) { ++ return nsDependentCSubstring(xmodifiersChar + atIMValueStart, ++ atIMValueEnd - atIMValueStart); ++ } ++ ++ if (atIMValueEnd == kNotFound) { ++ return nsDependentCSubstring(xmodifiersChar + atIMValueStart, ++ strlen(xmodifiersChar) - atIMValueStart); ++ } ++ ++ return im; ++} ++ + void + IMContextWrapper::Init() + { +- MOZ_LOG(gGtkIMLog, LogLevel::Info, +- ("0x%p Init(), mOwnerWindow=0x%p", +- this, mOwnerWindow)); +- + MozContainer* container = mOwnerWindow->GetMozContainer(); +- NS_PRECONDITION(container, "container is null"); ++ MOZ_ASSERT(container, "container is null"); + GdkWindow* gdkWindow = gtk_widget_get_window(GTK_WIDGET(container)); + + // Overwrite selection colors of the window before associating the window +@@ -333,6 +492,47 @@ IMContextWrapper::Init() + G_CALLBACK(IMContextWrapper::OnStartCompositionCallback), this); + g_signal_connect(mContext, "preedit_end", + G_CALLBACK(IMContextWrapper::OnEndCompositionCallback), this); ++ nsDependentCSubstring im = GetIMName(); ++ if (im.EqualsLiteral("ibus")) { ++ mIMContextID = IMContextID::eIBus; ++ mIsIMInAsyncKeyHandlingMode = !IsIBusInSyncMode(); ++ // Although ibus has key snooper mode, it's forcibly disabled on Firefox ++ // in default settings by its whitelist since we always send key events ++ // to IME before handling shortcut keys. The whitelist can be ++ // customized with env, IBUS_NO_SNOOPER_APPS, but we don't need to ++ // support such rare cases for reducing maintenance cost. ++ mIsKeySnooped = false; ++ } else if (im.EqualsLiteral("fcitx")) { ++ mIMContextID = IMContextID::eFcitx; ++ mIsIMInAsyncKeyHandlingMode = !IsFcitxInSyncMode(); ++ // Although Fcitx has key snooper mode similar to ibus, it's also ++ // disabled on Firefox in default settings by its whitelist. The ++ // whitelist can be customized with env, IBUS_NO_SNOOPER_APPS or ++ // FCITX_NO_SNOOPER_APPS, but we don't need to support such rare cases ++ // for reducing maintenance cost. ++ mIsKeySnooped = false; ++ } else if (im.EqualsLiteral("uim")) { ++ mIMContextID = IMContextID::eUim; ++ mIsIMInAsyncKeyHandlingMode = false; ++ // We cannot know if uim uses key snooper since it's build option of ++ // uim. Therefore, we need to retrieve the consideration from the ++ // pref for making users and distributions allowed to choose their ++ // preferred value. ++ mIsKeySnooped = ++ Preferences::GetBool("intl.ime.hack.uim.using_key_snooper", true); ++ } else if (im.EqualsLiteral("scim")) { ++ mIMContextID = IMContextID::eScim; ++ mIsIMInAsyncKeyHandlingMode = false; ++ mIsKeySnooped = false; ++ } else if (im.EqualsLiteral("iiim")) { ++ mIMContextID = IMContextID::eIIIMF; ++ mIsIMInAsyncKeyHandlingMode = false; ++ mIsKeySnooped = false; ++ } else { ++ mIMContextID = IMContextID::eUnknown; ++ mIsIMInAsyncKeyHandlingMode = false; ++ mIsKeySnooped = false; ++ } + + // Simple context + if (sUseSimpleContext) { +@@ -361,6 +561,18 @@ IMContextWrapper::Init() + // Dummy context + mDummyContext = gtk_im_multicontext_new(); + gtk_im_context_set_client_window(mDummyContext, gdkWindow); ++ ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p Init(), mOwnerWindow=%p, mContext=%p (im=\"%s\"), " ++ "mIsIMInAsyncKeyHandlingMode=%s, mIsKeySnooped=%s, " ++ "mSimpleContext=%p, mDummyContext=%p, " ++ "gtk_im_multicontext_get_context_id()=\"%s\", " ++ "PR_GetEnv(\"XMODIFIERS\")=\"%s\"", ++ this, mOwnerWindow, mContext, nsAutoCString(im).get(), ++ ToChar(mIsIMInAsyncKeyHandlingMode), ToChar(mIsKeySnooped), ++ mSimpleContext, mDummyContext, ++ gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(mContext)), ++ PR_GetEnv("XMODIFIERS"))); + } + + /* static */ +@@ -469,7 +681,7 @@ IMContextWrapper::OnDestroyWindow(nsWind + "mOwnerWindow=0x%p, mLastFocusedModule=0x%p", + this, aWindow, mLastFocusedWindow, mOwnerWindow, sLastFocusedContext)); + +- NS_PRECONDITION(aWindow, "aWindow must not be null"); ++ MOZ_ASSERT(aWindow, "aWindow must not be null"); + + if (mLastFocusedWindow == aWindow) { + EndIMEComposition(aWindow); +@@ -524,46 +736,46 @@ IMContextWrapper::OnDestroyWindow(nsWind + mOwnerWindow = nullptr; + mLastFocusedWindow = nullptr; + mInputContext.mIMEState.mEnabled = IMEState::DISABLED; ++ mPostingKeyEvents.Clear(); + + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("0x%p OnDestroyWindow(), succeeded, Completely destroyed", + this)); + } + +-// Work around gtk bug http://bugzilla.gnome.org/show_bug.cgi?id=483223: +-// (and the similar issue of GTK+ IIIM) +-// The GTK+ XIM and IIIM modules register handlers for the "closed" signal +-// on the display, but: +-// * The signal handlers are not disconnected when the module is unloaded. +-// +-// The GTK+ XIM module has another problem: +-// * When the signal handler is run (with the module loaded) it tries +-// XFree (and fails) on a pointer that did not come from Xmalloc. +-// +-// To prevent these modules from being unloaded, use static variables to +-// hold ref of GtkIMContext class. +-// For GTK+ XIM module, to prevent the signal handler from being run, +-// find the signal handlers and remove them. +-// +-// GtkIMContextXIMs share XOpenIM connections and display closed signal +-// handlers (where possible). +- + void + IMContextWrapper::PrepareToDestroyContext(GtkIMContext* aContext) + { +- GtkIMContext *slave = nullptr; //TODO GTK3 +- if (!slave) { +- return; +- } +- +- GType slaveType = G_TYPE_FROM_INSTANCE(slave); +- const gchar *im_type_name = g_type_name(slaveType); +- if (strcmp(im_type_name, "GtkIMContextIIIM") == 0) { +- // Add a reference to prevent the IIIM module from being unloaded +- static gpointer gtk_iiim_context_class = +- g_type_class_ref(slaveType); +- // Mute unused variable warning: +- (void)gtk_iiim_context_class; ++ if (mIMContextID == IMContextID::eIIIMF) { ++ // IIIM module registers handlers for the "closed" signal on the ++ // display, but the signal handler is not disconnected when the module ++ // is unloaded. To prevent the module from being unloaded, use static ++ // variable to hold reference of slave context class declared by IIIM. ++ // Note that this does not grab any instance, it grabs the "class". ++ static gpointer sGtkIIIMContextClass = nullptr; ++ if (!sGtkIIIMContextClass) { ++ // We retrieved slave context class with g_type_name() and actual ++ // slave context instance when our widget was GTK2. That must be ++ // _GtkIMContext::priv::slave in GTK3. However, _GtkIMContext::priv ++ // is an opacity struct named _GtkIMMulticontextPrivate, i.e., it's ++ // not exposed by GTK3. Therefore, we cannot access the instance ++ // safely. So, we need to retrieve the slave context class with ++ // g_type_from_name("GtkIMContextIIIM") directly (anyway, we needed ++ // to compare the class name with "GtkIMContextIIIM"). ++ GType IIMContextType = g_type_from_name("GtkIMContextIIIM"); ++ if (IIMContextType) { ++ sGtkIIIMContextClass = g_type_class_ref(IIMContextType); ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p PrepareToDestroyContext(), added to reference to " ++ "GtkIMContextIIIM class to prevent it from being unloaded", ++ this)); ++ } else { ++ MOZ_LOG(gGtkIMLog, LogLevel::Error, ++ ("0x%p PrepareToDestroyContext(), FAILED to prevent the " ++ "IIIM module from being uploaded", ++ this)); ++ } ++ } + } + } + +@@ -603,9 +815,9 @@ IMContextWrapper::OnBlurWindow(nsWindow* + bool + IMContextWrapper::OnKeyEvent(nsWindow* aCaller, + GdkEventKey* aEvent, +- bool aKeyDownEventWasSent /* = false */) ++ bool aKeyboardEventWasDispatched /* = false */) + { +- NS_PRECONDITION(aEvent, "aEvent must be non-null"); ++ MOZ_ASSERT(aEvent, "aEvent must be non-null"); + + if (!mInputContext.mIMEState.MaybeEditable() || + MOZ_UNLIKELY(IsDestroyed())) { +@@ -613,13 +825,24 @@ IMContextWrapper::OnKeyEvent(nsWindow* a + } + + MOZ_LOG(gGtkIMLog, LogLevel::Info, +- ("0x%p OnKeyEvent(aCaller=0x%p, aKeyDownEventWasSent=%s), " +- "mCompositionState=%s, current context=0x%p, active context=0x%p, " +- "aEvent(0x%p): { type=%s, keyval=%s, unicode=0x%X }", +- this, aCaller, ToChar(aKeyDownEventWasSent), ++ ("0x%p OnKeyEvent(aCaller=0x%p, " ++ "aEvent(0x%p): { type=%s, keyval=%s, unicode=0x%X, state=%s, " ++ "time=%u, hardware_keycode=%u, group=%u }, " ++ "aKeyboardEventWasDispatched=%s)", ++ this, aCaller, aEvent, GetEventType(aEvent), ++ gdk_keyval_name(aEvent->keyval), ++ gdk_keyval_to_unicode(aEvent->keyval), ++ GetEventStateName(aEvent->state, mIMContextID).get(), ++ aEvent->time, aEvent->hardware_keycode, aEvent->group, ++ ToChar(aKeyboardEventWasDispatched))); ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p OnKeyEvent(), mMaybeInDeadKeySequence=%s, " ++ "mCompositionState=%s, current context=%p, active context=%p, " ++ "mIMContextID=%s, mIsIMInAsyncKeyHandlingMode=%s", ++ this, ToChar(mMaybeInDeadKeySequence), + GetCompositionStateName(), GetCurrentContext(), GetActiveContext(), +- aEvent, GetEventType(aEvent), gdk_keyval_name(aEvent->keyval), +- gdk_keyval_to_unicode(aEvent->keyval))); ++ GetIMContextIDName(mIMContextID), ++ ToChar(mIsIMInAsyncKeyHandlingMode))); + + if (aCaller != mLastFocusedWindow) { + MOZ_LOG(gGtkIMLog, LogLevel::Error, +@@ -644,49 +867,158 @@ IMContextWrapper::OnKeyEvent(nsWindow* a + mSetCursorPositionOnKeyEvent = false; + } + +- mKeyDownEventWasSent = aKeyDownEventWasSent; +- mFilterKeyEvent = true; ++ // Let's support dead key event even if active keyboard layout also ++ // supports complicated composition like CJK IME. ++ bool isDeadKey = ++ KeymapWrapper::ComputeDOMKeyNameIndex(aEvent) == KEY_NAME_INDEX_Dead; ++ mMaybeInDeadKeySequence |= isDeadKey; ++ ++ // If current context is mSimpleContext, both ibus and fcitx handles key ++ // events synchronously. So, only when current context is mContext which ++ // is GtkIMMulticontext, the key event may be handled by IME asynchronously. ++ bool maybeHandledAsynchronously = ++ mIsIMInAsyncKeyHandlingMode && currentContext == mContext; ++ ++ // If IM is ibus or fcitx and it handles key events asynchronously, ++ // they mark aEvent->state as "handled by me" when they post key event ++ // to another process. Unfortunately, we need to check this hacky ++ // flag because it's difficult to store all pending key events by ++ // an array or a hashtable. ++ if (maybeHandledAsynchronously) { ++ switch (mIMContextID) { ++ case IMContextID::eIBus: ++ // ibus won't send back key press events in a dead key sequcne. ++ if (mMaybeInDeadKeySequence && aEvent->type == GDK_KEY_PRESS) { ++ maybeHandledAsynchronously = false; ++ break; ++ } ++ // ibus handles key events synchronously if focused editor is ++ // or |ime-mode: disabled;|. ++ if (mInputContext.mIMEState.mEnabled == IMEState::PASSWORD) { ++ maybeHandledAsynchronously = false; ++ break; ++ } ++ // See src/ibustypes.h ++ static const guint IBUS_IGNORED_MASK = 1 << 25; ++ // If IBUS_IGNORED_MASK was set to aEvent->state, the event ++ // has already been handled by another process and it wasn't ++ // used by IME. ++ if (aEvent->state & IBUS_IGNORED_MASK) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p OnKeyEvent(), aEvent->state has " ++ "IBUS_IGNORED_MASK, so, it won't be handled " ++ "asynchronously anymore. Removing posted events from " ++ "the queue", ++ this)); ++ maybeHandledAsynchronously = false; ++ mPostingKeyEvents.RemoveEvent(aEvent); ++ break; ++ } ++ break; ++ case IMContextID::eFcitx: ++ // fcitx won't send back key press events in a dead key sequcne. ++ if (mMaybeInDeadKeySequence && aEvent->type == GDK_KEY_PRESS) { ++ maybeHandledAsynchronously = false; ++ break; ++ } ++ ++ // fcitx handles key events asynchronously even if focused ++ // editor cannot use IME actually. ++ ++ // See src/lib/fcitx-utils/keysym.h ++ static const guint FcitxKeyState_IgnoredMask = 1 << 25; ++ // If FcitxKeyState_IgnoredMask was set to aEvent->state, ++ // the event has already been handled by another process and ++ // it wasn't used by IME. ++ if (aEvent->state & FcitxKeyState_IgnoredMask) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p OnKeyEvent(), aEvent->state has " ++ "FcitxKeyState_IgnoredMask, so, it won't be handled " ++ "asynchronously anymore. Removing posted events from " ++ "the queue", ++ this)); ++ maybeHandledAsynchronously = false; ++ mPostingKeyEvents.RemoveEvent(aEvent); ++ break; ++ } ++ break; ++ default: ++ MOZ_ASSERT_UNREACHABLE("IME may handle key event " ++ "asyncrhonously, but not yet confirmed if it comes agian " ++ "actually"); ++ } ++ } ++ ++ mKeyboardEventWasDispatched = aKeyboardEventWasDispatched; ++ mFallbackToKeyEvent = false; + mProcessingKeyEvent = aEvent; + gboolean isFiltered = + gtk_im_context_filter_keypress(currentContext, aEvent); +- mProcessingKeyEvent = nullptr; + +- // We filter the key event if the event was not committed (because +- // it's probably part of a composition) or if the key event was +- // committed _and_ changed. This way we still let key press +- // events go through as simple key press events instead of +- // composed characters. +- bool filterThisEvent = isFiltered && mFilterKeyEvent; +- +- if (IsComposingOnCurrentContext() && !isFiltered) { +- if (aEvent->type == GDK_KEY_PRESS) { +- if (!mDispatchedCompositionString.IsEmpty()) { +- // If there is composition string, we shouldn't dispatch +- // any keydown events during composition. +- filterThisEvent = true; +- } else { +- // A Hangul input engine for SCIM doesn't emit preedit_end +- // signal even when composition string becomes empty. On the +- // other hand, we should allow to make composition with empty +- // string for other languages because there *might* be such +- // IM. For compromising this issue, we should dispatch +- // compositionend event, however, we don't need to reset IM +- // actually. +- DispatchCompositionCommitEvent(currentContext, &EmptyString()); +- filterThisEvent = false; +- } +- } else { +- // Key release event may not be consumed by IM, however, we +- // shouldn't dispatch any keyup event during composition. +- filterThisEvent = true; ++ // The caller of this shouldn't handle aEvent anymore if we've dispatched ++ // composition events or modified content with other events. ++ bool filterThisEvent = isFiltered && !mFallbackToKeyEvent; ++ ++ if (IsComposingOnCurrentContext() && !isFiltered && ++ aEvent->type == GDK_KEY_PRESS && ++ mDispatchedCompositionString.IsEmpty()) { ++ // A Hangul input engine for SCIM doesn't emit preedit_end ++ // signal even when composition string becomes empty. On the ++ // other hand, we should allow to make composition with empty ++ // string for other languages because there *might* be such ++ // IM. For compromising this issue, we should dispatch ++ // compositionend event, however, we don't need to reset IM ++ // actually. ++ // NOTE: Don't dispatch key events as "processed by IME" since ++ // we need to dispatch keyboard events as IME wasn't handled it. ++ mProcessingKeyEvent = nullptr; ++ DispatchCompositionCommitEvent(currentContext, &EmptyString()); ++ mProcessingKeyEvent = aEvent; ++ // In this case, even though we handle the keyboard event here, ++ // but we should dispatch keydown event as ++ filterThisEvent = false; ++ } ++ ++ if (filterThisEvent && !mKeyboardEventWasDispatched) { ++ // If IME handled the key event but we've not dispatched eKeyDown nor ++ // eKeyUp event yet, we need to dispatch here unless the key event is ++ // now being handled by other IME process. ++ if (!maybeHandledAsynchronously) { ++ MaybeDispatchKeyEventAsProcessedByIME(eVoidEvent); ++ // Be aware, the widget might have been gone here. ++ } ++ // If we need to wait reply from IM, IM may send some signals to us ++ // without sending the key event again. In such case, we need to ++ // dispatch keyboard events with a copy of aEvent. Therefore, we ++ // need to use information of this key event to dispatch an KeyDown ++ // or eKeyUp event later. ++ else { ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p OnKeyEvent(), putting aEvent into the queue...", ++ this)); ++ mPostingKeyEvents.PutEvent(aEvent); + } + } + ++ mProcessingKeyEvent = nullptr; ++ ++ if (aEvent->type == GDK_KEY_PRESS && !filterThisEvent) { ++ // If the key event hasn't been handled by active IME nor keyboard ++ // layout, we can assume that the dead key sequence has been or was ++ // ended. Note that we should not reset it when the key event is ++ // GDK_KEY_RELEASE since it may not be filtered by active keyboard ++ // layout even in composition. ++ mMaybeInDeadKeySequence = false; ++ } ++ + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("0x%p OnKeyEvent(), succeeded, filterThisEvent=%s " +- "(isFiltered=%s, mFilterKeyEvent=%s), mCompositionState=%s", ++ "(isFiltered=%s, mFallbackToKeyEvent=%s, " ++ "maybeHandledAsynchronously=%s), mCompositionState=%s, " ++ "mMaybeInDeadKeySequence=%s", + this, ToChar(filterThisEvent), ToChar(isFiltered), +- ToChar(mFilterKeyEvent), GetCompositionStateName())); ++ ToChar(mFallbackToKeyEvent), ToChar(maybeHandledAsynchronously), ++ GetCompositionStateName(), ToChar(mMaybeInDeadKeySequence))); + + return filterThisEvent; + } +@@ -1005,6 +1337,10 @@ IMContextWrapper::Focus() + + sLastFocusedContext = this; + ++ // Forget all posted key events when focus is moved since they shouldn't ++ // be fired in different editor. ++ mPostingKeyEvents.Clear(); ++ + gtk_im_context_focus_in(currentContext); + mIsIMFocused = true; + mSetCursorPositionOnKeyEvent = true; +@@ -1400,6 +1736,7 @@ IMContextWrapper::OnCommitCompositionNat + { + const gchar emptyStr = 0; + const gchar *commitString = aUTF8Char ? aUTF8Char : &emptyStr; ++ NS_ConvertUTF8toUTF16 utf16CommitString(commitString); + + MOZ_LOG(gGtkIMLog, LogLevel::Info, + ("0x%p OnCommitCompositionNative(aContext=0x%p), " +@@ -1422,7 +1759,7 @@ IMContextWrapper::OnCommitCompositionNat + // signal, we would dispatch compositionstart, text, compositionend + // events with empty string. Of course, they are unnecessary events + // for Web applications and our editor. +- if (!IsComposingOn(aContext) && !commitString[0]) { ++ if (!IsComposingOn(aContext) && utf16CommitString.IsEmpty()) { + MOZ_LOG(gGtkIMLog, LogLevel::Warning, + ("0x%p OnCommitCompositionNative(), Warning, does nothing " + "because has not started composition and commit string is empty", +@@ -1431,11 +1768,14 @@ IMContextWrapper::OnCommitCompositionNat + } + + // If IME doesn't change their keyevent that generated this commit, +- // don't send it through XIM - just send it as a normal key press +- // event. ++ // we should treat that IME didn't handle the key event because ++ // web applications want to receive "keydown" and "keypress" event ++ // in such case. + // NOTE: While a key event is being handled, this might be caused on + // current context. Otherwise, this may be caused on active context. +- if (!IsComposingOn(aContext) && mProcessingKeyEvent && ++ if (!IsComposingOn(aContext) && ++ mProcessingKeyEvent && ++ mProcessingKeyEvent->type == GDK_KEY_PRESS && + aContext == GetCurrentContext()) { + char keyval_utf8[8]; /* should have at least 6 bytes of space */ + gint keyval_utf8_len; +@@ -1445,12 +1785,80 @@ IMContextWrapper::OnCommitCompositionNat + keyval_utf8_len = g_unichar_to_utf8(keyval_unicode, keyval_utf8); + keyval_utf8[keyval_utf8_len] = '\0'; + ++ // If committing string is exactly same as a character which is ++ // produced by the key, eKeyDown and eKeyPress event should be ++ // dispatched by the caller of OnKeyEvent() normally. Note that ++ // mMaybeInDeadKeySequence will be set to false by OnKeyEvent() ++ // since we set mFallbackToKeyEvent to true here. + if (!strcmp(commitString, keyval_utf8)) { + MOZ_LOG(gGtkIMLog, LogLevel::Info, + ("0x%p OnCommitCompositionNative(), " + "we'll send normal key event", + this)); +- mFilterKeyEvent = false; ++ mFallbackToKeyEvent = true; ++ return; ++ } ++ ++ // If we're in a dead key sequence, commit string is a character in ++ // the BMP and mProcessingKeyEvent produces some characters but it's ++ // not same as committing string, we should dispatch an eKeyPress ++ // event from here. ++ WidgetKeyboardEvent keyDownEvent(true, eKeyDown, ++ mLastFocusedWindow); ++ KeymapWrapper::InitKeyEvent(keyDownEvent, mProcessingKeyEvent, false); ++ if (mMaybeInDeadKeySequence && ++ utf16CommitString.Length() == 1 && ++ keyDownEvent.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) { ++ mKeyboardEventWasDispatched = true; ++ // Anyway, we're not in dead key sequence anymore. ++ mMaybeInDeadKeySequence = false; ++ ++ RefPtr dispatcher = GetTextEventDispatcher(); ++ nsresult rv = dispatcher->BeginNativeInputTransaction(); ++ if (NS_WARN_IF(NS_FAILED(rv))) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Error, ++ ("0x%p OnCommitCompositionNative(), FAILED, " ++ "due to BeginNativeInputTransaction() failure", ++ this)); ++ return; ++ } ++ ++ // First, dispatch eKeyDown event. ++ keyDownEvent.mKeyValue = utf16CommitString; ++ nsEventStatus status = nsEventStatus_eIgnore; ++ bool dispatched = ++ dispatcher->DispatchKeyboardEvent(eKeyDown, keyDownEvent, ++ status, mProcessingKeyEvent); ++ if (!dispatched || status == nsEventStatus_eConsumeNoDefault) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p OnCommitCompositionNative(), " ++ "doesn't dispatch eKeyPress event because the preceding " ++ "eKeyDown event was not dispatched or was consumed", ++ this)); ++ return; ++ } ++ if (mLastFocusedWindow != keyDownEvent.mWidget || ++ mLastFocusedWindow->Destroyed()) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Warning, ++ ("0x%p OnCommitCompositionNative(), Warning, " ++ "stop dispatching eKeyPress event because the preceding " ++ "eKeyDown event caused changing focused widget or " ++ "destroyed", ++ this)); ++ return; ++ } ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p OnCommitCompositionNative(), " ++ "dispatched eKeyDown event for the committed character", ++ this)); ++ ++ // Next, dispatch eKeyPress event. ++ dispatcher->MaybeDispatchKeypressEvents(keyDownEvent, status, ++ mProcessingKeyEvent); ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p OnCommitCompositionNative(), " ++ "dispatched eKeyPress event for the committed character", ++ this)); + return; + } + } +@@ -1470,7 +1878,7 @@ IMContextWrapper::GetCompositionString(G + gtk_im_context_get_preedit_string(aContext, &preedit_string, + &feedback_list, &cursor_pos); + if (preedit_string && *preedit_string) { +- CopyUTF8toUTF16(preedit_string, aCompositionString); ++ CopyUTF8toUTF16(MakeStringSpan(preedit_string), aCompositionString); + } else { + aCompositionString.Truncate(); + } +@@ -1485,6 +1893,173 @@ IMContextWrapper::GetCompositionString(G + } + + bool ++IMContextWrapper::MaybeDispatchKeyEventAsProcessedByIME( ++ EventMessage aFollowingEvent) ++{ ++ if (!mLastFocusedWindow) { ++ return false; ++ } ++ ++ if (!mIsKeySnooped && ++ ((!mProcessingKeyEvent && mPostingKeyEvents.IsEmpty()) || ++ (mProcessingKeyEvent && mKeyboardEventWasDispatched))) { ++ return true; ++ } ++ ++ // A "keydown" or "keyup" event handler may change focus with the ++ // following event. In such case, we need to cancel this composition. ++ // So, we need to store IM context now because mComposingContext may be ++ // overwritten with different context if calling this method recursively. ++ // Note that we don't need to grab the context here because |context| ++ // will be used only for checking if it's same as mComposingContext. ++ GtkIMContext* oldCurrentContext = GetCurrentContext(); ++ GtkIMContext* oldComposingContext = mComposingContext; ++ ++ RefPtr lastFocusedWindow(mLastFocusedWindow); ++ ++ if (mProcessingKeyEvent || !mPostingKeyEvents.IsEmpty()) { ++ if (mProcessingKeyEvent) { ++ mKeyboardEventWasDispatched = true; ++ } ++ // If we're not handling a key event synchronously, the signal may be ++ // sent by IME without sending key event to us. In such case, we ++ // should dispatch keyboard event for the last key event which was ++ // posted to other IME process. ++ GdkEventKey* sourceEvent = ++ mProcessingKeyEvent ? mProcessingKeyEvent : ++ mPostingKeyEvents.GetFirstEvent(); ++ ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(" ++ "aFollowingEvent=%s), dispatch %s %s " ++ "event: { type=%s, keyval=%s, unicode=0x%X, state=%s, " ++ "time=%u, hardware_keycode=%u, group=%u }", ++ this, ToChar(aFollowingEvent), ++ ToChar(sourceEvent->type == GDK_KEY_PRESS ? eKeyDown : eKeyUp), ++ mProcessingKeyEvent ? "processing" : "posted", ++ GetEventType(sourceEvent), gdk_keyval_name(sourceEvent->keyval), ++ gdk_keyval_to_unicode(sourceEvent->keyval), ++ GetEventStateName(sourceEvent->state, mIMContextID).get(), ++ sourceEvent->time, sourceEvent->hardware_keycode, ++ sourceEvent->group)); ++ ++ // Let's dispatch eKeyDown event or eKeyUp event now. Note that only ++ // when we're not in a dead key composition, we should mark the ++ // eKeyDown and eKeyUp event as "processed by IME" since we should ++ // expose raw keyCode and key value to web apps the key event is a ++ // part of a dead key sequence. ++ // FYI: We should ignore if default of preceding keydown or keyup ++ // event is prevented since even on the other browsers, web ++ // applications cannot cancel the following composition event. ++ // Spec bug: https://github.com/w3c/uievents/issues/180 ++ bool isCancelled; ++ lastFocusedWindow->DispatchKeyDownOrKeyUpEvent(sourceEvent, ++ !mMaybeInDeadKeySequence, ++ &isCancelled); ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), keydown or keyup " ++ "event is dispatched", ++ this)); ++ ++ if (!mProcessingKeyEvent) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), removing first " ++ "event from the queue", ++ this)); ++ mPostingKeyEvents.RemoveEvent(sourceEvent); ++ } ++ } else { ++ MOZ_ASSERT(mIsKeySnooped); ++ // Currently, we support key snooper mode of uim only. ++ MOZ_ASSERT(mIMContextID == IMContextID::eUim); ++ // uim sends "preedit_start" signal and "preedit_changed" separately ++ // at starting composition, "commit" and "preedit_end" separately at ++ // committing composition. ++ ++ // Currently, we should dispatch only fake eKeyDown event because ++ // we cannot decide which is the last signal of each key operation ++ // and Chromium also dispatches only "keydown" event in this case. ++ bool dispatchFakeKeyDown = false; ++ switch (aFollowingEvent) { ++ case eCompositionStart: ++ case eCompositionCommit: ++ case eCompositionCommitAsIs: ++ dispatchFakeKeyDown = true; ++ break; ++ // XXX Unfortunately, I don't have a good idea to prevent to ++ // dispatch redundant eKeyDown event for eCompositionStart ++ // immediately after "delete_surrounding" signal. However, ++ // not dispatching eKeyDown event is worse than dispatching ++ // redundant eKeyDown events. ++ case eContentCommandDelete: ++ dispatchFakeKeyDown = true; ++ break; ++ // We need to prevent to dispatch redundant eKeyDown event for ++ // eCompositionChange immediately after eCompositionStart. So, ++ // We should not dispatch eKeyDown event if dispatched composition ++ // string is still empty string. ++ case eCompositionChange: ++ dispatchFakeKeyDown = !mDispatchedCompositionString.IsEmpty(); ++ break; ++ default: ++ MOZ_ASSERT_UNREACHABLE("Do you forget to handle the case?"); ++ break; ++ } ++ ++ if (dispatchFakeKeyDown) { ++ WidgetKeyboardEvent fakeKeyDownEvent(true, eKeyDown, ++ lastFocusedWindow); ++ fakeKeyDownEvent.mKeyCode = NS_VK_PROCESSKEY; ++ fakeKeyDownEvent.mKeyNameIndex = KEY_NAME_INDEX_Process; ++ // It's impossible to get physical key information in this case but ++ // this should be okay since web apps shouldn't do anything with ++ // physical key information during composition. ++ fakeKeyDownEvent.mCodeNameIndex = CODE_NAME_INDEX_UNKNOWN; ++ ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(" ++ "aFollowingEvent=%s), dispatch fake eKeyDown event", ++ this, ToChar(aFollowingEvent))); ++ ++ bool isCancelled; ++ lastFocusedWindow->DispatchKeyDownOrKeyUpEvent(fakeKeyDownEvent, ++ &isCancelled); ++ MOZ_LOG(gGtkIMLog, LogLevel::Info, ++ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), " ++ "fake keydown event is dispatched", ++ this)); ++ } ++ } ++ ++ if (lastFocusedWindow->IsDestroyed() || ++ lastFocusedWindow != mLastFocusedWindow) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Warning, ++ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), Warning, the " ++ "focused widget was destroyed/changed by a key event", ++ this)); ++ return false; ++ } ++ ++ // If the dispatched keydown event caused moving focus and that also ++ // caused changing active context, we need to cancel composition here. ++ if (GetCurrentContext() != oldCurrentContext) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Warning, ++ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), Warning, the key " ++ "event causes changing active IM context", ++ this)); ++ if (mComposingContext == oldComposingContext) { ++ // Only when the context is still composing, we should call ++ // ResetIME() here. Otherwise, it should've already been ++ // cleaned up. ++ ResetIME(); ++ } ++ return false; ++ } ++ ++ return true; ++} ++ ++bool + IMContextWrapper::DispatchCompositionStart(GtkIMContext* aContext) + { + MOZ_LOG(gGtkIMLog, LogLevel::Info, +@@ -1528,50 +2103,16 @@ IMContextWrapper::DispatchCompositionSta + mCompositionStart = mSelection.mOffset; + mDispatchedCompositionString.Truncate(); + +- if (mProcessingKeyEvent && !mKeyDownEventWasSent && +- mProcessingKeyEvent->type == GDK_KEY_PRESS) { +- // A keydown event handler may change focus with the following keydown +- // event. In such case, we need to cancel this composition. So, we +- // need to store IM context now because mComposingContext may be +- // overwritten with different context if calling this method +- // recursively. +- // Note that we don't need to grab the context here because |context| +- // will be used only for checking if it's same as mComposingContext. +- GtkIMContext* context = mComposingContext; +- +- // If this composition is started by a native keydown event, we need to +- // dispatch our keydown event here (before composition start). +- bool isCancelled; +- mLastFocusedWindow->DispatchKeyDownEvent(mProcessingKeyEvent, +- &isCancelled); +- MOZ_LOG(gGtkIMLog, LogLevel::Debug, +- ("0x%p DispatchCompositionStart(), preceding keydown event is " +- "dispatched", ++ // If this composition is started by a key press, we need to dispatch ++ // eKeyDown or eKeyUp event before dispatching eCompositionStart event. ++ // Note that dispatching a keyboard event which is marked as "processed ++ // by IME" is okay since Chromium also dispatches keyboard event as so. ++ if (!MaybeDispatchKeyEventAsProcessedByIME(eCompositionStart)) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Warning, ++ ("0x%p DispatchCompositionStart(), Warning, " ++ "MaybeDispatchKeyEventAsProcessedByIME() returned false", + this)); +- if (lastFocusedWindow->IsDestroyed() || +- lastFocusedWindow != mLastFocusedWindow) { +- MOZ_LOG(gGtkIMLog, LogLevel::Warning, +- ("0x%p DispatchCompositionStart(), Warning, the focused " +- "widget was destroyed/changed by keydown event", +- this)); +- return false; +- } +- +- // If the dispatched keydown event caused moving focus and that also +- // caused changing active context, we need to cancel composition here. +- if (GetCurrentContext() != context) { +- MOZ_LOG(gGtkIMLog, LogLevel::Warning, +- ("0x%p DispatchCompositionStart(), Warning, the preceding " +- "keydown event causes changing active IM context", +- this)); +- if (mComposingContext == context) { +- // Only when the context is still composing, we should call +- // ResetIME() here. Otherwise, it should've already been +- // cleaned up. +- ResetIME(); +- } +- return false; +- } ++ return false; + } + + RefPtr dispatcher = GetTextEventDispatcher(); +@@ -1584,6 +2125,25 @@ IMContextWrapper::DispatchCompositionSta + return false; + } + ++ static bool sHasSetTelemetry = false; ++ if (!sHasSetTelemetry) { ++ sHasSetTelemetry = true; ++ NS_ConvertUTF8toUTF16 im(GetIMName()); ++ // 72 is kMaximumKeyStringLength in TelemetryScalar.cpp ++ if (im.Length() > 72) { ++ if (NS_IS_LOW_SURROGATE(im[72 - 1]) && ++ NS_IS_HIGH_SURROGATE(im[72 - 2])) { ++ im.Truncate(72 - 2); ++ } else { ++ im.Truncate(72 - 1); ++ } ++ // U+2026 is "..." ++ im.Append(char16_t(0x2026)); ++ } ++ Telemetry::ScalarSet(Telemetry::ScalarID::WIDGET_IME_NAME_ON_LINUX, ++ im, true); ++ } ++ + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("0x%p DispatchCompositionStart(), dispatching " + "compositionstart... (mCompositionStart=%u)", +@@ -1629,6 +2189,15 @@ IMContextWrapper::DispatchCompositionCha + return false; + } + } ++ // If this composition string change caused by a key press, we need to ++ // dispatch eKeyDown or eKeyUp before dispatching eCompositionChange event. ++ else if (!MaybeDispatchKeyEventAsProcessedByIME(eCompositionChange)) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Warning, ++ ("0x%p DispatchCompositionChangeEvent(), Warning, " ++ "MaybeDispatchKeyEventAsProcessedByIME() returned false", ++ this)); ++ return false; ++ } + + RefPtr dispatcher = GetTextEventDispatcher(); + nsresult rv = dispatcher->BeginNativeInputTransaction(); +@@ -1718,6 +2287,14 @@ IMContextWrapper::DispatchCompositionCom + return false; + } + ++ // TODO: We need special care to handle request to commit composition ++ // by content while we're committing composition because we have ++ // commit string information now but IME may not have composition ++ // anymore. Therefore, we may not be able to handle commit as ++ // expected. However, this is rare case because this situation ++ // never occurs with remote content. So, it's okay to fix this ++ // issue later. (Perhaps, TextEventDisptcher should do it for ++ // all platforms. E.g., creating WillCommitComposition()?) + if (!IsComposing()) { + if (!aCommitString || aCommitString->IsEmpty()) { + MOZ_LOG(gGtkIMLog, LogLevel::Error, +@@ -1734,6 +2311,17 @@ IMContextWrapper::DispatchCompositionCom + return false; + } + } ++ // If this commit caused by a key press, we need to dispatch eKeyDown or ++ // eKeyUp before dispatching composition events. ++ else if (!MaybeDispatchKeyEventAsProcessedByIME( ++ aCommitString ? eCompositionCommit : eCompositionCommitAsIs)) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Warning, ++ ("0x%p DispatchCompositionCommitEvent(), Warning, " ++ "MaybeDispatchKeyEventAsProcessedByIME() returned false", ++ this)); ++ mCompositionState = eCompositionState_NotComposing; ++ return false; ++ } + + RefPtr dispatcher = GetTextEventDispatcher(); + nsresult rv = dispatcher->BeginNativeInputTransaction(); +@@ -1755,6 +2343,11 @@ IMContextWrapper::DispatchCompositionCom + mSelection.mWritingMode); + + mCompositionState = eCompositionState_NotComposing; ++ // Reset dead key sequence too because GTK doesn't support dead key chain ++ // (i.e., a key press doesn't cause both producing some characters and ++ // restarting new dead key sequence at one time). So, committing ++ // composition means end of a dead key sequence. ++ mMaybeInDeadKeySequence = false; + mCompositionStart = UINT32_MAX; + mCompositionTargetRange.Clear(); + mDispatchedCompositionString.Truncate(); +@@ -2427,6 +3020,16 @@ IMContextWrapper::DeleteText(GtkIMContex + this)); + return NS_ERROR_FAILURE; + } ++ ++ // If this deleting text caused by a key press, we need to dispatch ++ // eKeyDown or eKeyUp before dispatching eContentCommandDelete event. ++ if (!MaybeDispatchKeyEventAsProcessedByIME(eContentCommandDelete)) { ++ MOZ_LOG(gGtkIMLog, LogLevel::Warning, ++ ("0x%p DeleteText(), Warning, " ++ "MaybeDispatchKeyEventAsProcessedByIME() returned false", ++ this)); ++ return NS_ERROR_FAILURE; ++ } + + // Delete the selection + WidgetContentCommandEvent contentCommandEvent(true, eContentCommandDelete, +diff -up thunderbird-60.3.0/widget/gtk/IMContextWrapper.h.wayland thunderbird-60.3.0/widget/gtk/IMContextWrapper.h +--- thunderbird-60.3.0/widget/gtk/IMContextWrapper.h.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/IMContextWrapper.h 2018-11-20 12:04:43.733787362 +0100 +@@ -70,13 +70,26 @@ public: + // OnThemeChanged is called when desktop theme is changed. + static void OnThemeChanged(); + +- // OnKeyEvent is called when aWindow gets a native key press event or a +- // native key release event. If this returns TRUE, the key event was +- // filtered by IME. Otherwise, this returns FALSE. +- // NOTE: When the keypress event starts composition, this returns TRUE but +- // this dispatches keydown event before compositionstart event. ++ /** ++ * OnKeyEvent() is called when aWindow gets a native key press event or a ++ * native key release event. If this returns true, the key event was ++ * filtered by IME. Otherwise, this returns false. ++ * NOTE: When the native key press event starts composition, this returns ++ * true but dispatches an eKeyDown event or eKeyUp event before ++ * dispatching composition events or content command event. ++ * ++ * @param aWindow A window on which user operate the ++ * key. ++ * @param aEvent A native key press or release ++ * event. ++ * @param aKeyboardEventWasDispatched true if eKeyDown or eKeyUp event ++ * for aEvent has already been ++ * dispatched. In this case, ++ * this class doesn't dispatch ++ * keyboard event anymore. ++ */ + bool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent, +- bool aKeyDownEventWasSent = false); ++ bool aKeyboardEventWasDispatched = false); + + // IME related nsIWidget methods. + nsresult EndIMEComposition(nsWindow* aCaller); +@@ -89,6 +102,43 @@ public: + + TextEventDispatcher* GetTextEventDispatcher(); + ++ // TODO: Typically, new IM comes every several years. And now, our code ++ // becomes really IM behavior dependent. So, perhaps, we need prefs ++ // to control related flags for IM developers. ++ enum class IMContextID : uint8_t ++ { ++ eFcitx, ++ eIBus, ++ eIIIMF, ++ eScim, ++ eUim, ++ eUnknown, ++ }; ++ ++ static const char* GetIMContextIDName(IMContextID aIMContextID) ++ { ++ switch (aIMContextID) { ++ case IMContextID::eFcitx: ++ return "eFcitx"; ++ case IMContextID::eIBus: ++ return "eIBus"; ++ case IMContextID::eIIIMF: ++ return "eIIIMF"; ++ case IMContextID::eScim: ++ return "eScim"; ++ case IMContextID::eUim: ++ return "eUim"; ++ default: ++ return "eUnknown"; ++ } ++ } ++ ++ /** ++ * GetIMName() returns IM name associated with mContext. If the context is ++ * xim, this look for actual engine from XMODIFIERS environment variable. ++ */ ++ nsDependentCSubstring GetIMName() const; ++ + protected: + ~IMContextWrapper(); + +@@ -144,6 +194,100 @@ protected: + // event. + GdkEventKey* mProcessingKeyEvent; + ++ /** ++ * GdkEventKeyQueue stores *copy* of GdkEventKey instances. However, this ++ * must be safe to our usecase since it has |time| and the value should not ++ * be same as older event. ++ */ ++ class GdkEventKeyQueue final ++ { ++ public: ++ ~GdkEventKeyQueue() { Clear(); } ++ ++ void Clear() ++ { ++ if (!mEvents.IsEmpty()) { ++ RemoveEventsAt(0, mEvents.Length()); ++ } ++ } ++ ++ /** ++ * PutEvent() puts new event into the queue. ++ */ ++ void PutEvent(const GdkEventKey* aEvent) ++ { ++ GdkEventKey* newEvent = ++ reinterpret_cast( ++ gdk_event_copy(reinterpret_cast(aEvent))); ++ newEvent->state &= GDK_MODIFIER_MASK; ++ mEvents.AppendElement(newEvent); ++ } ++ ++ /** ++ * RemoveEvent() removes oldest same event and its preceding events ++ * from the queue. ++ */ ++ void RemoveEvent(const GdkEventKey* aEvent) ++ { ++ size_t index = IndexOf(aEvent); ++ if (NS_WARN_IF(index == mEvents.NoIndex)) { ++ return; ++ } ++ RemoveEventsAt(0, index + 1); ++ } ++ ++ /** ++ * FirstEvent() returns oldest event in the queue. ++ */ ++ GdkEventKey* GetFirstEvent() const ++ { ++ if (mEvents.IsEmpty()) { ++ return nullptr; ++ } ++ return mEvents[0]; ++ } ++ ++ bool IsEmpty() const { return mEvents.IsEmpty(); } ++ ++ private: ++ nsTArray mEvents; ++ ++ void RemoveEventsAt(size_t aStart, size_t aCount) ++ { ++ for (size_t i = aStart; i < aStart + aCount; i++) { ++ gdk_event_free(reinterpret_cast(mEvents[i])); ++ } ++ mEvents.RemoveElementsAt(aStart, aCount); ++ } ++ ++ size_t IndexOf(const GdkEventKey* aEvent) const ++ { ++ static_assert(!(GDK_MODIFIER_MASK & (1 << 24)), ++ "We assumes 25th bit is used by some IM, but used by GDK"); ++ static_assert(!(GDK_MODIFIER_MASK & (1 << 25)), ++ "We assumes 26th bit is used by some IM, but used by GDK"); ++ for (size_t i = 0; i < mEvents.Length(); i++) { ++ GdkEventKey* event = mEvents[i]; ++ // It must be enough to compare only type, time, keyval and ++ // part of state. Note that we cannot compaire two events ++ // simply since IME may have changed unused bits of state. ++ if (event->time == aEvent->time) { ++ if (NS_WARN_IF(event->type != aEvent->type) || ++ NS_WARN_IF(event->keyval != aEvent->keyval) || ++ NS_WARN_IF(event->state != ++ (aEvent->state & GDK_MODIFIER_MASK))) { ++ continue; ++ } ++ } ++ return i; ++ } ++ return mEvents.NoIndex; ++ } ++ }; ++ // OnKeyEvent() append mPostingKeyEvents when it believes that a key event ++ // is posted to other IME process. ++ GdkEventKeyQueue mPostingKeyEvents; ++ + struct Range + { + uint32_t mOffset; +@@ -167,7 +311,8 @@ protected: + Range mCompositionTargetRange; + + // mCompositionState indicates current status of composition. +- enum eCompositionState { ++ enum eCompositionState : uint8_t ++ { + eCompositionState_NotComposing, + eCompositionState_CompositionStartDispatched, + eCompositionState_CompositionChangeEventDispatched +@@ -219,6 +364,10 @@ protected: + } + } + ++ // mIMContextID indicates the ID of mContext. This is actually indicates ++ // IM which user selected. ++ IMContextID mIMContextID; ++ + struct Selection final + { + nsString mString; +@@ -268,16 +417,20 @@ protected: + // mIsIMFocused is set to TRUE when we call gtk_im_context_focus_in(). And + // it's set to FALSE when we call gtk_im_context_focus_out(). + bool mIsIMFocused; +- // mFilterKeyEvent is used by OnKeyEvent(). If the commit event should +- // be processed as simple key event, this is set to TRUE by the commit +- // handler. +- bool mFilterKeyEvent; +- // mKeyDownEventWasSent is used by OnKeyEvent() and +- // DispatchCompositionStart(). DispatchCompositionStart() dispatches +- // a keydown event if the composition start is caused by a native +- // keypress event. If this is true, the keydown event has been dispatched. +- // Then, DispatchCompositionStart() doesn't dispatch keydown event. +- bool mKeyDownEventWasSent; ++ // mFallbackToKeyEvent is set to false when this class starts to handle ++ // a native key event (at that time, mProcessingKeyEvent is set to the ++ // native event). If active IME just commits composition with a character ++ // which is produced by the key with current keyboard layout, this is set ++ // to true. ++ bool mFallbackToKeyEvent; ++ // mKeyboardEventWasDispatched is used by OnKeyEvent() and ++ // MaybeDispatchKeyEventAsProcessedByIME(). ++ // MaybeDispatchKeyEventAsProcessedByIME() dispatches an eKeyDown or ++ // eKeyUp event event if the composition is caused by a native ++ // key press event. If this is true, a keyboard event has been dispatched ++ // for the native event. If so, MaybeDispatchKeyEventAsProcessedByIME() ++ // won't dispatch keyboard event anymore. ++ bool mKeyboardEventWasDispatched; + // mIsDeletingSurrounding is true while OnDeleteSurroundingNative() is + // trying to delete the surrounding text. + bool mIsDeletingSurrounding; +@@ -298,6 +451,24 @@ protected: + // mRetrieveSurroundingSignalReceived is true after "retrieve_surrounding" + // signal is received until selection is changed in Gecko. + bool mRetrieveSurroundingSignalReceived; ++ // mMaybeInDeadKeySequence is set to true when we detect a dead key press ++ // and set to false when we're sure dead key sequence has been finished. ++ // Note that we cannot detect which key event causes ending a dead key ++ // sequence. For example, when you press dead key grave with ibus Spanish ++ // keyboard layout, it just consumes the key event when we call ++ // gtk_im_context_filter_keypress(). Then, pressing "Escape" key cancels ++ // the dead key sequence but we don't receive any signal and it's consumed ++ // by gtk_im_context_filter_keypress() normally. On the other hand, when ++ // pressing "Shift" key causes exactly same behavior but dead key sequence ++ // isn't finished yet. ++ bool mMaybeInDeadKeySequence; ++ // mIsIMInAsyncKeyHandlingMode is set to true if we know that IM handles ++ // key events asynchronously. I.e., filtered key event may come again ++ // later. ++ bool mIsIMInAsyncKeyHandlingMode; ++ // mIsKeySnooped is set to true if IM uses key snooper to listen key events. ++ // In such case, we won't receive key events if IME consumes the event. ++ bool mIsKeySnooped; + + // sLastFocusedContext is a pointer to the last focused instance of this + // class. When a instance is destroyed and sLastFocusedContext refers it, +@@ -448,12 +619,31 @@ protected: + * Following methods dispatch gecko events. Then, the focused widget + * can be destroyed, and also it can be stolen focus. If they returns + * FALSE, callers cannot continue the composition. ++ * - MaybeDispatchKeyEventAsProcessedByIME + * - DispatchCompositionStart + * - DispatchCompositionChangeEvent + * - DispatchCompositionCommitEvent + */ + + /** ++ * Dispatch an eKeyDown or eKeyUp event whose mKeyCode value is ++ * NS_VK_PROCESSKEY and mKeyNameIndex is KEY_NAME_INDEX_Process if ++ * we're not in a dead key sequence, mProcessingKeyEvent is nullptr ++ * but mPostingKeyEvents is not empty or mProcessingKeyEvent is not ++ * nullptr and mKeyboardEventWasDispatched is still false. If this ++ * dispatches a keyboard event, this sets mKeyboardEventWasDispatched ++ * to true. ++ * ++ * @param aFollowingEvent The following event message. ++ * @return If the caller can continue to handle ++ * composition, returns true. Otherwise, ++ * false. For example, if focus is moved ++ * by dispatched keyboard event, returns ++ * false. ++ */ ++ bool MaybeDispatchKeyEventAsProcessedByIME(EventMessage aFollowingEvent); ++ ++ /** + * Dispatches a composition start event. + * + * @param aContext A GtkIMContext which is being handled. +diff -up thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h.wayland thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h +--- thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h 2018-11-20 12:04:43.733787362 +0100 +@@ -3,8 +3,8 @@ + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +-#ifndef widget_gtk_InProcessGtkCompositorWidgetParent_h +-#define widget_gtk_InProcessGtkCompositorWidgetParent_h ++#ifndef widget_gtk_InProcessGtkCompositorWidget_h ++#define widget_gtk_InProcessGtkCompositorWidget_h + + #include "GtkCompositorWidget.h" + +@@ -28,4 +28,4 @@ public: + } // namespace widget + } // namespace mozilla + +-#endif // widget_gtk_InProcessGtkCompositorWidgetParent_h ++#endif // widget_gtk_InProcessGtkCompositorWidget_h +diff -up thunderbird-60.3.0/widget/gtk/moz.build.wayland thunderbird-60.3.0/widget/gtk/moz.build +--- thunderbird-60.3.0/widget/gtk/moz.build.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/moz.build 2018-11-20 12:09:34.756903818 +0100 +@@ -123,6 +123,7 @@ include('/ipc/chromium/chromium-config.m + FINAL_LIBRARY = 'xul' + + LOCAL_INCLUDES += [ ++ '/layout/base', + '/layout/generic', + '/layout/xul', + '/other-licenses/atk-1.0', +diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.3.0/widget/gtk/mozcontainer.cpp +--- thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozcontainer.cpp 2018-11-20 12:04:43.733787362 +0100 +@@ -10,6 +10,7 @@ + #ifdef MOZ_WAYLAND + #include + #include ++#include + #endif + #include + #include +@@ -207,6 +208,12 @@ moz_container_init (MozContainer *contai + + #if defined(MOZ_WAYLAND) + { ++ container->subcompositor = nullptr; ++ container->surface = nullptr; ++ container->subsurface = nullptr; ++ container->eglwindow = nullptr; ++ container->parent_surface_committed = false; ++ + 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; + } + + #endif +@@ -434,6 +479,11 @@ moz_container_size_allocate (GtkWidget + gdk_window_get_position(gtk_widget_get_window(widget), &x, &y); + wl_subsurface_set_position(container->subsurface, x, y); + } ++ if (container->eglwindow) { ++ wl_egl_window_resize(container->eglwindow, ++ allocation->width, allocation->height, ++ 0, 0); ++ } + #endif + } + +@@ -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); ++ } ++ } + } + + return container->surface; + } ++ ++struct wl_egl_window * ++moz_container_get_wl_egl_window(MozContainer *container) ++{ ++ if (!container->eglwindow) { ++ struct wl_surface *wlsurf = moz_container_get_wl_surface(container); ++ if (!wlsurf) ++ return nullptr; ++ ++ GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container)); ++ container->eglwindow ++ = wl_egl_window_create(wlsurf, ++ gdk_window_get_width(window), ++ gdk_window_get_height(window)); ++ } ++ return container->eglwindow; ++} ++ ++gboolean ++moz_container_has_wl_egl_window(MozContainer *container) ++{ ++ return container->eglwindow ? true : false; ++} + #endif +diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.h.wayland thunderbird-60.3.0/widget/gtk/mozcontainer.h +--- thunderbird-60.3.0/widget/gtk/mozcontainer.h.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozcontainer.h 2018-11-20 12:04:43.733787362 +0100 +@@ -72,6 +72,9 @@ struct _MozContainer + struct wl_subcompositor *subcompositor; + struct wl_surface *surface; + struct wl_subsurface *subsurface; ++ struct wl_egl_window *eglwindow; ++ gboolean parent_surface_committed; ++ gulong parent_surface_committed_handler; + #endif + }; + +@@ -95,6 +98,8 @@ void moz_container_move ( + + #ifdef MOZ_WAYLAND + struct wl_surface* moz_container_get_wl_surface(MozContainer *container); ++struct wl_egl_window* moz_container_get_wl_egl_window(MozContainer *container); ++gboolean moz_container_has_wl_egl_window(MozContainer *container); + #endif + + #endif /* __MOZ_CONTAINER_H__ */ +diff -up thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c +--- thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c 2018-11-20 12:04:43.734787359 +0100 +@@ -135,6 +135,8 @@ STUB(gdk_x11_get_xatom_by_name) + STUB(gdk_x11_get_xatom_by_name_for_display) + STUB(gdk_x11_lookup_xdisplay) + STUB(gdk_x11_screen_get_xscreen) ++STUB(gdk_x11_screen_get_screen_number) ++STUB(gdk_x11_screen_lookup_visual) + STUB(gdk_x11_screen_supports_net_wm_hint) + STUB(gdk_x11_visual_get_xvisual) + STUB(gdk_x11_window_foreign_new_for_display) +@@ -266,6 +268,7 @@ STUB(gtk_im_context_set_client_window) + STUB(gtk_im_context_set_cursor_location) + STUB(gtk_im_context_set_surrounding) + STUB(gtk_im_context_simple_new) ++STUB(gtk_im_multicontext_get_context_id) + STUB(gtk_im_multicontext_get_type) + STUB(gtk_im_multicontext_new) + STUB(gtk_info_bar_get_type) +diff -up thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c.wayland thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c +--- thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c 2018-11-20 12:04:43.734787359 +0100 +@@ -271,3 +271,21 @@ wl_log_set_handler_client(wl_log_func_t + { + } + ++MOZ_EXPORT struct wl_egl_window * ++wl_egl_window_create(struct wl_surface *surface, ++ int width, int height) ++{ ++ return NULL; ++} ++ ++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.3.0/widget/gtk/nsAppShell.cpp.wayland thunderbird-60.3.0/widget/gtk/nsAppShell.cpp +--- thunderbird-60.3.0/widget/gtk/nsAppShell.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsAppShell.cpp 2018-11-20 12:04:43.734787359 +0100 +@@ -14,7 +14,8 @@ + #include "nsWindow.h" + #include "mozilla/Logging.h" + #include "prenv.h" +-#include "mozilla/HangMonitor.h" ++#include "mozilla/BackgroundHangMonitor.h" ++#include "mozilla/Hal.h" + #include "mozilla/Unused.h" + #include "mozilla/WidgetUtils.h" + #include "GeckoProfiler.h" +@@ -46,13 +47,14 @@ static GPollFunc sPollFunc; + static gint + PollWrapper(GPollFD *ufds, guint nfsd, gint timeout_) + { +- mozilla::HangMonitor::Suspend(); ++ mozilla::BackgroundHangMonitor().NotifyWait(); + gint result; + { ++ AUTO_PROFILER_LABEL("PollWrapper", IDLE); + AUTO_PROFILER_THREAD_SLEEP; + result = (*sPollFunc)(ufds, nfsd, timeout_); + } +- mozilla::HangMonitor::NotifyActivity(); ++ mozilla::BackgroundHangMonitor().NotifyActivity(); + return result; + } + +@@ -133,6 +135,8 @@ nsAppShell::EventProcessorCallback(GIOCh + + nsAppShell::~nsAppShell() + { ++ mozilla::hal::Shutdown(); ++ + if (mTag) + g_source_remove(mTag); + if (mPipeFDs[0]) +@@ -150,6 +154,8 @@ nsAppShell::Init() + // is a no-op. + g_type_init(); + ++ mozilla::hal::Init(); ++ + #ifdef MOZ_ENABLE_DBUS + if (XRE_IsParentProcess()) { + nsCOMPtr powerManagerService = +diff -up thunderbird-60.3.0/widget/gtk/nsClipboard.cpp.wayland thunderbird-60.3.0/widget/gtk/nsClipboard.cpp +--- thunderbird-60.3.0/widget/gtk/nsClipboard.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsClipboard.cpp 2018-11-20 12:04:43.734787359 +0100 +@@ -671,11 +671,9 @@ void ConvertHTMLtoUCS2(const char* data, + *unicodeData = + reinterpret_cast + (moz_xmalloc((outUnicodeLen + sizeof('\0')) * sizeof(char16_t))); +- if (*unicodeData) { +- memcpy(*unicodeData, data + sizeof(char16_t), +- outUnicodeLen * sizeof(char16_t)); +- (*unicodeData)[outUnicodeLen] = '\0'; +- } ++ memcpy(*unicodeData, data + sizeof(char16_t), ++ outUnicodeLen * sizeof(char16_t)); ++ (*unicodeData)[outUnicodeLen] = '\0'; + } else if (charset.EqualsLiteral("UNKNOWN")) { + outUnicodeLen = 0; + return; +@@ -701,27 +699,25 @@ void ConvertHTMLtoUCS2(const char* data, + if (needed.value()) { + *unicodeData = reinterpret_cast( + moz_xmalloc((needed.value() + 1) * sizeof(char16_t))); +- if (*unicodeData) { +- uint32_t result; +- size_t read; +- size_t written; +- bool hadErrors; +- Tie(result, read, written, hadErrors) = +- decoder->DecodeToUTF16(AsBytes(MakeSpan(data, dataLength)), +- MakeSpan(*unicodeData, needed.value()), +- true); +- MOZ_ASSERT(result == kInputEmpty); +- MOZ_ASSERT(read == size_t(dataLength)); +- MOZ_ASSERT(written <= needed.value()); +- Unused << hadErrors; ++ uint32_t result; ++ size_t read; ++ size_t written; ++ bool hadErrors; ++ Tie(result, read, written, hadErrors) = ++ decoder->DecodeToUTF16(AsBytes(MakeSpan(data, dataLength)), ++ MakeSpan(*unicodeData, needed.value()), ++ true); ++ MOZ_ASSERT(result == kInputEmpty); ++ MOZ_ASSERT(read == size_t(dataLength)); ++ MOZ_ASSERT(written <= needed.value()); ++ Unused << hadErrors; + #ifdef DEBUG_CLIPBOARD +- if (read != dataLength) +- printf("didn't consume all the bytes\n"); ++ if (read != dataLength) ++ printf("didn't consume all the bytes\n"); + #endif +- outUnicodeLen = written; +- // null terminate. +- (*unicodeData)[outUnicodeLen] = '\0'; +- } ++ outUnicodeLen = written; ++ // null terminate. ++ (*unicodeData)[outUnicodeLen] = '\0'; + } // if valid length + } + } +diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp +--- thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp 2018-11-20 12:04:43.735787356 +0100 +@@ -23,6 +23,7 @@ + #include "mozilla/Services.h" + #include "mozilla/RefPtr.h" + #include "mozilla/TimeStamp.h" ++#include "nsDragService.h" + + #include "imgIContainer.h" + +@@ -46,6 +47,44 @@ nsRetrievalContextWayland::sTextMimeType + "COMPOUND_TEXT" + }; + ++static inline GdkDragAction ++wl_to_gdk_actions(uint32_t dnd_actions) ++{ ++ GdkDragAction actions = GdkDragAction(0); ++ ++ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) ++ actions = GdkDragAction(actions|GDK_ACTION_COPY); ++ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) ++ actions = GdkDragAction(actions|GDK_ACTION_MOVE); ++ ++ return actions; ++} ++ ++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)) ++ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; ++ if (action & GDK_ACTION_MOVE) ++ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; ++ ++ 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)); ++ ++ gpointer user_data = nullptr; ++ gdk_window_get_user_data(gdkParentWindow, &user_data); ++ ++ return GTK_WIDGET(user_data); ++} ++ + void + DataOffer::AddMIMEType(const char *aMimeType) + { +@@ -114,7 +153,7 @@ DataOffer::GetData(wl_display* aDisplay, + + GIOChannel *channel = g_io_channel_unix_new(pipe_fd[0]); + GError* error = nullptr; +- char* clipboardData; ++ char* clipboardData = nullptr; + + g_io_channel_set_encoding(channel, nullptr, &error); + if (!error) { +@@ -155,6 +194,61 @@ WaylandDataOffer::RequestDataTransfer(co + return false; + } + ++void ++WaylandDataOffer::DragOfferAccept(const char* aMimeType, uint32_t aTime) ++{ ++ wl_data_offer_accept(mWaylandDataOffer, aTime, aMimeType); ++} ++ ++/* We follow logic of gdk_wayland_drag_context_commit_status()/gdkdnd-wayland.c ++ * here. ++ */ ++void ++WaylandDataOffer::SetDragStatus(GdkDragAction aAction, uint32_t aTime) ++{ ++ uint32_t dnd_actions = gdk_to_wl_actions(aAction); ++ uint32_t all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | ++ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; ++ ++ wl_data_offer_set_actions(mWaylandDataOffer, all_actions, dnd_actions); ++ ++ /* Workaround Wayland D&D architecture here. To get the data_device_drop() ++ signal (which routes to nsDragService::GetData() call) we need to ++ accept at least one mime type before data_device_leave(). ++ ++ Real wl_data_offer_accept() for actualy requested data mime type is ++ called from nsDragService::GetData(). ++ */ ++ if (mTargetMIMETypes[0]) { ++ wl_data_offer_accept(mWaylandDataOffer, aTime, ++ gdk_atom_name(mTargetMIMETypes[0])); ++ } ++} ++ ++void ++WaylandDataOffer::SetSelectedDragAction(uint32_t aWaylandAction) ++{ ++ mSelectedDragAction = aWaylandAction; ++} ++ ++GdkDragAction ++WaylandDataOffer::GetSelectedDragAction() ++{ ++ return wl_to_gdk_actions(mSelectedDragAction); ++} ++ ++void ++WaylandDataOffer::SetAvailableDragActions(uint32_t aWaylandActions) ++{ ++ mAvailableDragAction = aWaylandActions; ++} ++ ++GdkDragAction ++WaylandDataOffer::GetAvailableDragActions() ++{ ++ return wl_to_gdk_actions(mAvailableDragAction); ++} ++ + static void + data_offer_offer (void *data, + struct wl_data_offer *wl_data_offer, +@@ -164,25 +258,39 @@ data_offer_offer (void * + offer->AddMIMEType(type); + } + ++/* Advertise all available drag and drop actions from source. ++ * We don't use that but follow gdk_wayland_drag_context_commit_status() ++ * from gdkdnd-wayland.c here. ++ */ + static void + data_offer_source_actions(void *data, + struct wl_data_offer *wl_data_offer, + uint32_t source_actions) + { ++ auto *offer = static_cast(data); ++ offer->SetAvailableDragActions(source_actions); + } + ++/* Advertise recently selected drag and drop action by compositor, based ++ * on source actions and user choice (key modifiers, etc.). ++ */ + static void + data_offer_action(void *data, + struct wl_data_offer *wl_data_offer, + uint32_t dnd_action) + { ++ auto *offer = static_cast(data); ++ offer->SetSelectedDragAction(dnd_action); + } + + /* wl_data_offer callback description: + * + * data_offer_offer - Is called for each MIME type available at wl_data_offer. +- * data_offer_source_actions - Exposes all available D&D actions. +- * data_offer_action - Expose one actually selected D&D action. ++ * data_offer_source_actions - This event indicates the actions offered by ++ * the data source. ++ * data_offer_action - This event indicates the action selected by ++ * the compositor after matching the source/destination ++ * side actions. + */ + static const struct wl_data_offer_listener data_offer_listener = { + data_offer_offer, +@@ -246,12 +354,94 @@ PrimaryDataOffer::~PrimaryDataOffer(void + } + } + ++NS_IMPL_ISUPPORTS(nsWaylandDragContext, nsISupports); ++ ++nsWaylandDragContext::nsWaylandDragContext(WaylandDataOffer* aDataOffer, ++ wl_display *aDisplay) ++ : mDataOffer(aDataOffer) ++ , mDisplay(aDisplay) ++ , mTime(0) ++ , mGtkWidget(nullptr) ++ , mX(0) ++ , mY(0) ++{ ++} ++ ++void ++nsWaylandDragContext::DropDataEnter(GtkWidget* aGtkWidget, uint32_t aTime, ++ nscoord aX, nscoord aY) ++{ ++ mTime = aTime; ++ mGtkWidget = aGtkWidget; ++ mX = aX; ++ mY = aY; ++} ++ + void +-nsRetrievalContextWayland::RegisterDataOffer(wl_data_offer *aWaylandDataOffer) ++nsWaylandDragContext::DropMotion(uint32_t aTime, nscoord aX, nscoord aY) ++{ ++ mTime = aTime; ++ mX = aX; ++ mY = aY; ++} ++ ++void ++nsWaylandDragContext::GetLastDropInfo(uint32_t *aTime, nscoord *aX, nscoord *aY) ++{ ++ *aTime = mTime; ++ *aX = mX; ++ *aY = mY; ++} ++ ++void ++nsWaylandDragContext::SetDragStatus(GdkDragAction aAction) ++{ ++ mDataOffer->SetDragStatus(aAction, mTime); ++} ++ ++GdkDragAction ++nsWaylandDragContext::GetSelectedDragAction() ++{ ++ GdkDragAction gdkAction = mDataOffer->GetSelectedDragAction(); ++ ++ // We emulate gdk_drag_context_get_actions() here. ++ if (!gdkAction) { ++ gdkAction = mDataOffer->GetAvailableDragActions(); ++ } ++ ++ return gdkAction; ++} ++ ++GList* ++nsWaylandDragContext::GetTargets() ++{ ++ int targetNums; ++ GdkAtom *atoms = mDataOffer->GetTargets(&targetNums); ++ ++ GList* targetList = nullptr; ++ for (int i = 0; i < targetNums; i++) { ++ targetList = g_list_append(targetList, GDK_ATOM_TO_POINTER(atoms[i])); ++ } ++ ++ return targetList; ++} ++ ++char* ++nsWaylandDragContext::GetData(const char* aMimeType, uint32_t* aContentLength) ++{ ++ mDataOffer->DragOfferAccept(aMimeType, mTime); ++ return mDataOffer->GetData(mDisplay, aMimeType, aContentLength); ++} ++ ++void ++nsRetrievalContextWayland::RegisterNewDataOffer(wl_data_offer *aWaylandDataOffer) + { + DataOffer* dataOffer = + static_cast(g_hash_table_lookup(mActiveOffers, + aWaylandDataOffer)); ++ MOZ_ASSERT(dataOffer == nullptr, ++ "Registered WaylandDataOffer already exists. Wayland protocol error?"); ++ + if (!dataOffer) { + dataOffer = new WaylandDataOffer(aWaylandDataOffer); + g_hash_table_insert(mActiveOffers, aWaylandDataOffer, dataOffer); +@@ -259,12 +449,15 @@ nsRetrievalContextWayland::RegisterDataO + } + + void +-nsRetrievalContextWayland::RegisterDataOffer( ++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* 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 + } + + 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; ++ ++ 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); ++ } ++} ++ ++nsWaylandDragContext* ++nsRetrievalContextWayland::GetDragContext(void) ++{ ++ return mDragContext; ++} ++ ++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); + } + + // 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); ++ ++ 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; ++ } ++ ++ 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)); + } + + static void + data_device_leave (void *data, + struct wl_data_device *data_device) + { ++ nsRetrievalContextWayland *context = ++ static_cast(data); ++ ++ nsWaylandDragContext* dropContext = context->GetDragContext(); ++ WindowDragLeaveHandler(dropContext->GetWidget()); ++ ++ 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); ++ ++ 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); + } + + static void + data_device_drop (void *data, + struct wl_data_device *data_device) + { ++ nsRetrievalContextWayland *context = ++ static_cast(data); ++ ++ 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); + } + + static void +@@ -418,6 +682,18 @@ primary_selection_selection (void + 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. ++ * ++ * 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 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(); +-} +- +-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, +-}; +- +-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); +- } else if (mKeyboard && !(caps & WL_SEAT_CAPABILITY_KEYBOARD)) { +- 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 const struct wl_seat_listener seat_listener = { +- 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); + } + + 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) ++{ ++#ifdef DEBUG ++ nsPrintfCString msg("nsRetrievalContextWayland(): leaked nsDataOffer %p\n", ++ aDataOffer); ++ NS_WARNING(msg.get()); ++#endif ++ delete static_cast(aDataOffer); ++ return true; ++} ++ + nsRetrievalContextWayland::~nsRetrievalContextWayland(void) + { ++ g_hash_table_foreach_remove(mActiveOffers, offer_hash_remove, nullptr); + g_hash_table_destroy(mActiveOffers); + } + +@@ -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'; + } + } else { + NS_WARNING("Received obsoleted clipboard data!"); +@@ -727,7 +943,7 @@ nsRetrievalContextWayland::GetClipboardT + if (!dataOffer) + return nullptr; + +- 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-20 12:04:43.735787356 +0100 +@@ -32,6 +32,7 @@ public: + 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); + +-private: ++ 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(); ++ + virtual ~WaylandDataOffer(); ++private: + bool RequestDataTransfer(const char* aMimeType, int fd) override; + + 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) {}; + +-private: + virtual ~PrimaryDataOffer(); ++private: + bool RequestDataTransfer(const char* aMimeType, int fd) override; + + gtk_primary_selection_offer* mPrimaryDataOffer; + }; + ++class nsWaylandDragContext : public nsISupports ++{ ++ NS_DECL_ISUPPORTS ++ ++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 SetDragStatus(GdkDragAction action); ++ GdkDragAction GetSelectedDragAction(); ++ ++ GtkWidget* GetWidget() { return mGtkWidget; } ++ GList* GetTargets(); ++ char* GetData(const char* aMimeType, uint32_t* aContentLength); ++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; + +- 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 ClearDataOffers(); ++ void ClearDragAndDropDataOffer(); + +- 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; + + int mClipboardRequestNumber; + char* mClipboardData; +diff -up thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp.wayland thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp +--- thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp 2018-11-20 12:04:43.735787356 +0100 +@@ -33,6 +33,9 @@ + #include + #include + ++// To check if we need to use flatpak portal for printing ++#include "nsIGIOService.h" ++ + using namespace mozilla; + + using mozilla::gfx::IntSize; +@@ -355,6 +358,20 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::En + // If you're not familiar with umasks, they contain the bits of what NOT to set in the permissions + // (thats because files and directories have different numbers of bits for their permissions) + destFile->SetPermissions(0666 & ~(mask)); ++ ++ // Notify flatpak printing portal that file is completely written ++ nsCOMPtr giovfs = ++ do_GetService(NS_GIOSERVICE_CONTRACTID); ++ bool shouldUsePortal; ++ if (giovfs) { ++ giovfs->ShouldUseFlatpakPortal(&shouldUsePortal); ++ if (shouldUsePortal) { ++ // Use the name of the file for printing to match with nsFlatpakPrintPortal ++ nsCOMPtr os = mozilla::services::GetObserverService(); ++ // Pass filename to be sure that observer process the right data ++ os->NotifyObservers(nullptr, "print-to-file-finished", targetPath.get()); ++ } ++ } + } + return NS_OK; + } +@@ -421,7 +438,7 @@ nsPrinterEnumeratorGTK::InitPrintSetting + } + + if (path) { +- CopyUTF8toUTF16(path, filename); ++ CopyUTF8toUTF16(MakeStringSpan(path), filename); + filename.AppendLiteral("/mozilla.pdf"); + } else { + filename.AssignLiteral("mozilla.pdf"); +diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60.3.0/widget/gtk/nsDragService.cpp +--- thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsDragService.cpp 2018-11-20 12:04:43.736787353 +0100 +@@ -34,7 +34,6 @@ + #include "nsPresContext.h" + #include "nsIContent.h" + #include "nsIDocument.h" +-#include "nsISelection.h" + #include "nsViewManager.h" + #include "nsIFrame.h" + #include "nsGtkUtils.h" +@@ -43,6 +42,9 @@ + #include "gfxPlatform.h" + #include "ScreenHelperGTK.h" + #include "nsArrayUtils.h" ++#ifdef MOZ_WAYLAND ++#include "nsClipboardWayland.h" ++#endif + + 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. +@@ -179,7 +185,7 @@ nsDragService::Observe(nsISupports *aSub + } + TargetResetData(); + } else { +- NS_NOTREACHED("unexpected topic"); ++ MOZ_ASSERT_UNREACHABLE("unexpected topic"); + return NS_ERROR_UNEXPECTED; + } + +@@ -269,13 +275,12 @@ OnSourceGrabEventAfter(GtkWidget *widget + } + + static GtkWindow* +-GetGtkWindow(nsIDOMDocument *aDocument) ++GetGtkWindow(nsIDocument *aDocument) + { +- nsCOMPtr doc = do_QueryInterface(aDocument); +- if (!doc) ++ if (!aDocument) + return nullptr; + +- nsCOMPtr presShell = doc->GetShell(); ++ nsCOMPtr presShell = aDocument->GetShell(); + if (!presShell) + return nullptr; + +@@ -304,10 +309,9 @@ GetGtkWindow(nsIDOMDocument *aDocument) + // nsIDragService + + NS_IMETHODIMP +-nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, ++nsDragService::InvokeDragSession(nsINode *aDOMNode, + const nsACString& aPrincipalURISpec, + nsIArray * aArrayTransferables, +- nsIScriptableRegion * aRegion, + uint32_t aActionType, + nsContentPolicyType aContentPolicyType = + nsIContentPolicy::TYPE_OTHER) +@@ -323,14 +327,14 @@ nsDragService::InvokeDragSession(nsIDOMN + + return nsBaseDragService::InvokeDragSession(aDOMNode, aPrincipalURISpec, + aArrayTransferables, +- aRegion, aActionType, ++ aActionType, + aContentPolicyType); + } + + // nsBaseDragService + nsresult + nsDragService::InvokeDragSessionImpl(nsIArray* aArrayTransferables, +- nsIScriptableRegion* aRegion, ++ const Maybe& aRegion, + uint32_t aActionType) + { + // make sure that we have an array of transferables to use +@@ -346,9 +350,6 @@ nsDragService::InvokeDragSessionImpl(nsI + if (!sourceList) + return NS_OK; + +- // stored temporarily until the drag-begin signal has been received +- mSourceRegion = aRegion; +- + // save our action type + GdkDragAction action = GDK_ACTION_DEFAULT; + +@@ -391,8 +392,6 @@ nsDragService::InvokeDragSessionImpl(nsI + 1, + &event); + +- mSourceRegion = nullptr; +- + nsresult rv; + if (context) { + StartDragSession(); +@@ -516,6 +515,9 @@ nsDragService::EndDragSession(bool aDone + + // We're done with the drag context. + mTargetDragContextForRemote = nullptr; ++#ifdef MOZ_WAYLAND ++ mTargetWaylandDragContextForRemote = nullptr; ++#endif + + return nsBaseDragService::EndDragSession(aDoneDrag, aKeyModifiers); + } +@@ -636,6 +638,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 ++ + bool isList = IsTargetContextList(); + if (isList) + mSourceDataItems->GetLength(aNumItems); +@@ -1027,9 +1037,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; +@@ -1074,6 +1093,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 +1133,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)); ++ ++ 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); ++} ++#endif ++ + void + nsDragService::TargetDataReceived(GtkWidget *aWidget, + GdkDragContext *aContext, +@@ -1136,6 +1194,12 @@ nsDragService::IsTargetContextList(void) + { + bool retval = false; + ++#ifdef MOZ_WAYLAND ++ // 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 +1238,28 @@ nsDragService::GetTargetDragData(GdkAtom + 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(); ++ } ++ } ++#ifdef MOZ_WAYLAND ++ else { ++ mTargetDragData = ++ mTargetWaylandDragContext->GetData(gdk_atom_name(aFlavor), ++ &mTargetDragDataLen); ++ mTargetDragDataReceived = true; + } ++#endif + MOZ_LOG(sDragLm, LogLevel::Debug, ("finished inner iteration\n")); + } + +@@ -1435,7 +1510,7 @@ nsDragService::SourceEndDragSession(GdkD + } + + // Schedule the appropriate drag end dom events. +- Schedule(eDragTaskSourceEnd, nullptr, nullptr, LayoutDeviceIntPoint(), 0); ++ Schedule(eDragTaskSourceEnd, nullptr, nullptr, nullptr, LayoutDeviceIntPoint(), 0); + } + + static void +@@ -1642,8 +1717,8 @@ void nsDragService::SetDragIcon(GdkDragC + LayoutDeviceIntRect dragRect; + nsPresContext* pc; + RefPtr surface; +- DrawDrag(mSourceNode, mSourceRegion, mScreenPosition, +- &dragRect, &surface, &pc); ++ DrawDrag(mSourceNode, mRegion, ++ mScreenPosition, &dragRect, &surface, &pc); + if (!pc) + return; + +@@ -1785,9 +1860,10 @@ invisibleSourceDragEnd(GtkWidget + 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 +1874,7 @@ nsDragService::ScheduleMotionEvent(nsWin + + // 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); + } + +@@ -1808,7 +1884,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"); + } + } +@@ -1816,10 +1893,11 @@ nsDragService::ScheduleLeaveEvent() + gboolean + nsDragService::ScheduleDropEvent(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 +1911,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 +1930,9 @@ nsDragService::Schedule(DragTask aTask, + mScheduledTask = aTask; + mPendingWindow = aWindow; + mPendingDragContext = aDragContext; ++#ifdef MOZ_WAYLAND ++ mPendingWaylandDragContext = aWaylandDragContext; ++#endif + mPendingWindowPoint = aWindowPoint; + mPendingTime = aTime; + +@@ -1927,6 +2009,9 @@ nsDragService::RunScheduledTask() + // succeeed. + mTargetWidget = mTargetWindow->GetMozContainerWidget(); + mTargetDragContext.steal(mPendingDragContext); ++#ifdef MOZ_WAYLAND ++ mTargetWaylandDragContext = mPendingWaylandDragContext.forget(); ++#endif + mTargetTime = mPendingTime; + + // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model +@@ -1958,10 +2043,20 @@ nsDragService::RunScheduledTask() + if (task == eDragTaskMotion) { + if (TakeDragEventDispatchedToChildProcess()) { + mTargetDragContextForRemote = mTargetDragContext; ++#ifdef MOZ_WAYLAND ++ 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 +2067,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); ++ if (mTargetDragContext) { ++ gtk_drag_finish(mTargetDragContext, success, ++ /* del = */ FALSE, mTargetTime); ++ } + + // This drag is over, so clear out our reference to the previous + // window. +@@ -1986,6 +2083,9 @@ nsDragService::RunScheduledTask() + // We're done with the drag context. + mTargetWidget = nullptr; + mTargetDragContext = nullptr; ++#ifdef MOZ_WAYLAND ++ mTargetWaylandDragContext = nullptr; ++#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 +2115,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; ++ 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) +@@ -2044,6 +2153,12 @@ nsDragService::UpdateDragEffect() + ReplyToDragMotion(mTargetDragContextForRemote); + mTargetDragContextForRemote = nullptr; + } ++#ifdef MOZ_WAYLAND ++ else if (mTargetWaylandDragContextForRemote) { ++ ReplyToDragMotion(mTargetWaylandDragContextForRemote); ++ mTargetWaylandDragContextForRemote = nullptr; ++ } ++#endif + 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-20 12:04:43.736787353 +0100 +@@ -14,6 +14,7 @@ + #include + + class nsWindow; ++class nsWaylandDragContext; + + namespace mozilla { + namespace gfx { +@@ -60,13 +61,12 @@ public: + + // nsBaseDragService + virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables, +- nsIScriptableRegion* aRegion, ++ const mozilla::Maybe& aRegion, + uint32_t aActionType) override; + // nsIDragService +- NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, ++ NS_IMETHOD InvokeDragSession (nsINode *aDOMNode, + const nsACString& aPrincipalURISpec, + nsIArray * anArrayTransferables, +- nsIScriptableRegion * aRegion, + uint32_t aActionType, + nsContentPolicyType aContentPolicyType) override; + NS_IMETHOD StartDragSession() override; +@@ -98,11 +98,13 @@ public: + + 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 +160,9 @@ private: + RefPtr mPendingWindow; + mozilla::LayoutDeviceIntPoint mPendingWindowPoint; + nsCountedRef mPendingDragContext; ++#ifdef MOZ_WAYLAND ++ RefPtr mPendingWaylandDragContext; ++#endif + guint mPendingTime; + + // mTargetWindow and mTargetWindowPoint record the position of the last +@@ -169,9 +174,15 @@ private: + // motion or drop events. mTime records the corresponding timestamp. + nsCountedRef mTargetWidget; + nsCountedRef mTargetDragContext; ++#ifdef MOZ_WAYLAND ++ RefPtr mTargetWaylandDragContext; ++#endif + // mTargetDragContextForRemote is set while waiting for a reply from + // a child process. + nsCountedRef mTargetDragContextForRemote; ++#ifdef MOZ_WAYLAND ++ RefPtr mTargetWaylandDragContextForRemote; ++#endif + guint mTargetTime; + + // is it OK to drop on us? +@@ -197,8 +208,6 @@ private: + // our source data items + nsCOMPtr mSourceDataItems; + +- nsCOMPtr mSourceRegion; +- + // get a list of the sources in gtk's format + GtkTargetList *GetSourceList(void); + +@@ -212,6 +221,7 @@ private: + + 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 +230,11 @@ private: + void UpdateDragAction(); + void DispatchMotionEvents(); + void ReplyToDragMotion(GdkDragContext* aDragContext); ++#ifdef MOZ_WAYLAND ++ void ReplyToDragMotion(nsWaylandDragContext* aDragContext); ++#endif + gboolean DispatchDropEvent(); + static uint32_t GetCurrentModifiers(); + }; + + #endif // nsDragService_h__ +- +diff -up thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp.wayland thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp +--- thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp 2018-11-20 12:04:43.736787353 +0100 +@@ -346,7 +346,7 @@ nsFilePicker::GetFiles(nsISimpleEnumerat + NS_ENSURE_ARG_POINTER(aFiles); + + if (mMode == nsIFilePicker::modeOpenMultiple) { +- return NS_NewArrayEnumerator(aFiles, mFiles); ++ return NS_NewArrayEnumerator(aFiles, mFiles, NS_GET_IID(nsIFile)); + } + + return NS_ERROR_FAILURE; +diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp +--- thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp 2018-11-20 12:04:43.736787353 +0100 +@@ -28,6 +28,10 @@ + #include "mozilla/MouseEvents.h" + #include "mozilla/TextEvents.h" + ++#ifdef MOZ_WAYLAND ++#include ++#endif ++ + namespace mozilla { + namespace widget { + +@@ -195,7 +199,11 @@ KeymapWrapper::Init() + memset(mModifierMasks, 0, sizeof(mModifierMasks)); + + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) +- InitBySystemSettings(); ++ InitBySystemSettingsX11(); ++#ifdef MOZ_WAYLAND ++ else ++ InitBySystemSettingsWayland(); ++#endif + + gdk_window_add_filter(nullptr, FilterEvents, this); + +@@ -275,10 +283,10 @@ KeymapWrapper::InitXKBExtension() + } + + void +-KeymapWrapper::InitBySystemSettings() ++KeymapWrapper::InitBySystemSettingsX11() + { + MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, +- ("%p InitBySystemSettings, mGdkKeymap=%p", ++ ("%p InitBySystemSettingsX11, mGdkKeymap=%p", + this, mGdkKeymap)); + + Display* display = +@@ -439,6 +447,208 @@ 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"); ++ ++ 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(); ++ ++ // 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"); ++ ++ 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); ++ 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 const struct wl_keyboard_listener keyboard_listener = { ++ 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; ++ ++ 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; ++ } ++} ++ ++static const struct wl_seat_listener seat_listener = { ++ 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_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 ++}; ++ ++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); ++} ++#endif ++ + KeymapWrapper::~KeymapWrapper() + { + gdk_window_remove_filter(nullptr, FilterEvents, this); +@@ -931,14 +1141,19 @@ KeymapWrapper::ComputeDOMCodeNameIndex(c + + /* static */ void + KeymapWrapper::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, +- GdkEventKey* aGdkKeyEvent) ++ GdkEventKey* aGdkKeyEvent, ++ bool aIsProcessedByIME) + { ++ MOZ_ASSERT(!aIsProcessedByIME || aKeyEvent.mMessage != eKeyPress, ++ "If the key event is handled by IME, keypress event shouldn't be fired"); ++ + KeymapWrapper* keymapWrapper = GetInstance(); + + aKeyEvent.mCodeNameIndex = ComputeDOMCodeNameIndex(aGdkKeyEvent); + MOZ_ASSERT(aKeyEvent.mCodeNameIndex != CODE_NAME_INDEX_USE_STRING); + aKeyEvent.mKeyNameIndex = +- keymapWrapper->ComputeDOMKeyNameIndex(aGdkKeyEvent); ++ aIsProcessedByIME ? KEY_NAME_INDEX_Process : ++ keymapWrapper->ComputeDOMKeyNameIndex(aGdkKeyEvent); + if (aKeyEvent.mKeyNameIndex == KEY_NAME_INDEX_Unidentified) { + uint32_t charCode = GetCharCodeFor(aGdkKeyEvent); + if (!charCode) { +@@ -951,10 +1166,11 @@ KeymapWrapper::InitKeyEvent(WidgetKeyboa + AppendUCS4ToUTF16(charCode, aKeyEvent.mKeyValue); + } + } +- aKeyEvent.mKeyCode = ComputeDOMKeyCode(aGdkKeyEvent); + +- if (aKeyEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING || +- aKeyEvent.mMessage != eKeyPress) { ++ if (aIsProcessedByIME) { ++ aKeyEvent.mKeyCode = NS_VK_PROCESSKEY; ++ } else if (aKeyEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING || ++ aKeyEvent.mMessage != eKeyPress) { + aKeyEvent.mKeyCode = ComputeDOMKeyCode(aGdkKeyEvent); + } else { + aKeyEvent.mKeyCode = 0; +@@ -1405,6 +1621,14 @@ void + 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-20 12:04:43.737787350 +0100 +@@ -13,6 +13,10 @@ + + #include + #include ++#ifdef MOZ_WAYLAND ++#include ++#include ++#endif + + namespace mozilla { + namespace widget { +@@ -131,9 +135,11 @@ public: + * @param aKeyEvent It's an WidgetKeyboardEvent which needs to be + * initialized. + * @param aGdkKeyEvent A native GDK key event. ++ * @param aIsProcessedByIME true if aGdkKeyEvent is handled by IME. + */ + static void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, +- GdkEventKey* aGdkKeyEvent); ++ GdkEventKey* aGdkKeyEvent, ++ bool aIsProcessedByIME); + + /** + * WillDispatchKeyboardEvent() is called via +@@ -148,6 +154,14 @@ public: + 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); ++#endif ++ + /** + * Destroys the singleton KeymapWrapper instance, if it exists. + */ +@@ -172,7 +186,10 @@ protected: + */ + void Init(); + void InitXKBExtension(); +- void InitBySystemSettings(); ++ void InitBySystemSettingsX11(); ++#ifdef MOZ_WAYLAND ++ void InitBySystemSettingsWayland(); ++#endif + + /** + * mModifierKeys stores each hardware key information. +@@ -374,6 +391,15 @@ protected: + */ + void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent, + GdkEventKey* aGdkKeyEvent); ++ ++#ifdef MOZ_WAYLAND ++ /** ++ * Utility function to set Xkb modifier key mask. ++ */ ++ void SetModifierMask(xkb_keymap *aKeymap, ++ ModifierIndex aModifierIndex, ++ const char* aModifierName); ++#endif + }; + + } // namespace widget +diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp +--- thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp 2018-11-20 12:04:43.737787350 +0100 +@@ -18,6 +18,7 @@ + + #include + #include "gfxPlatformGtk.h" ++#include "mozilla/FontPropertyTypes.h" + #include "ScreenHelperGTK.h" + + #include "gtkdrawing.h" +@@ -31,7 +32,9 @@ + #include + #include "WidgetStyleCache.h" + #include "prenv.h" ++#include "nsCSSColorUtils.h" + ++using namespace mozilla; + using mozilla::LookAndFeel; + + #define GDK_COLOR_TO_NS_RGB(c) \ +@@ -182,7 +185,7 @@ GetBorderColors(GtkStyleContext* aContex + // GTK has an initial value of zero for border-widths, and so themes + // need to explicitly set border-widths to make borders visible. + GtkBorder border; +- gtk_style_context_get_border(aContext, GTK_STATE_FLAG_NORMAL, &border); ++ gtk_style_context_get_border(aContext, state, &border); + visible = border.top != 0 || border.right != 0 || + border.bottom != 0 || border.left != 0; + } +@@ -213,6 +216,58 @@ GetBorderColors(GtkStyleContext* aContex + return ret; + } + ++// Finds ideal cell highlight colors used for unfocused+selected cells distinct ++// from both Highlight, used as focused+selected background, and the listbox ++// background which is assumed to be similar to -moz-field ++nsresult ++nsLookAndFeel::InitCellHighlightColors() { ++ // NS_SUFFICIENT_LUMINOSITY_DIFFERENCE is the a11y standard for text ++ // on a background. Use 20% of that standard since we have a background ++ // on top of another background ++ int32_t minLuminosityDifference = NS_SUFFICIENT_LUMINOSITY_DIFFERENCE / 5; ++ int32_t backLuminosityDifference = NS_LUMINOSITY_DIFFERENCE( ++ mMozWindowBackground, mMozFieldBackground); ++ if (backLuminosityDifference >= minLuminosityDifference) { ++ mMozCellHighlightBackground = mMozWindowBackground; ++ mMozCellHighlightText = mMozWindowText; ++ return NS_OK; ++ } ++ ++ uint16_t hue, sat, luminance; ++ uint8_t alpha; ++ mMozCellHighlightBackground = mMozFieldBackground; ++ mMozCellHighlightText = mMozFieldText; ++ ++ NS_RGB2HSV(mMozCellHighlightBackground, hue, sat, luminance, alpha); ++ ++ uint16_t step = 30; ++ // Lighten the color if the color is very dark ++ if (luminance <= step) { ++ luminance += step; ++ } ++ // Darken it if it is very light ++ else if (luminance >= 255 - step) { ++ luminance -= step; ++ } ++ // Otherwise, compute what works best depending on the text luminance. ++ else { ++ uint16_t textHue, textSat, textLuminance; ++ uint8_t textAlpha; ++ NS_RGB2HSV(mMozCellHighlightText, textHue, textSat, textLuminance, ++ textAlpha); ++ // Text is darker than background, use a lighter shade ++ if (textLuminance < luminance) { ++ luminance += step; ++ } ++ // Otherwise, use a darker shade ++ else { ++ luminance -= step; ++ } ++ } ++ NS_HSV2RGB(mMozCellHighlightBackground, hue, sat, luminance, alpha); ++ return NS_OK; ++} ++ + void + nsLookAndFeel::NativeInit() + { +@@ -269,7 +324,6 @@ nsLookAndFeel::NativeGetColor(ColorID aI + case eColorID_IMESelectedRawTextBackground: + case eColorID_IMESelectedConvertedTextBackground: + case eColorID__moz_dragtargetzone: +- case eColorID__moz_cellhighlight: + case eColorID__moz_html_cellhighlight: + case eColorID_highlight: // preference selected item, + aColor = mTextSelectedBackground; +@@ -279,10 +333,15 @@ nsLookAndFeel::NativeGetColor(ColorID aI + case eColorID_IMESelectedRawTextForeground: + case eColorID_IMESelectedConvertedTextForeground: + case eColorID_highlighttext: +- case eColorID__moz_cellhighlighttext: + case eColorID__moz_html_cellhighlighttext: + aColor = mTextSelectedText; + break; ++ case eColorID__moz_cellhighlight: ++ aColor = mMozCellHighlightBackground; ++ break; ++ case eColorID__moz_cellhighlighttext: ++ aColor = mMozCellHighlightText; ++ break; + case eColorID_Widget3DHighlight: + aColor = NS_RGB(0xa0,0xa0,0xa0); + break; +@@ -668,6 +727,17 @@ nsLookAndFeel::GetIntImpl(IntID aID, int + EnsureInit(); + aResult = mCSDCloseButton; + break; ++ case eIntID_PrefersReducedMotion: { ++ GtkSettings *settings; ++ gboolean enableAnimations; ++ ++ settings = gtk_settings_get_default(); ++ g_object_get(settings, ++ "gtk-enable-animations", ++ &enableAnimations, nullptr); ++ aResult = enableAnimations ? 0 : 1; ++ break; ++ } + default: + aResult = 0; + res = NS_ERROR_FAILURE; +@@ -708,7 +778,7 @@ GetSystemFontInfo(GtkStyleContext *aStyl + nsString *aFontName, + gfxFontStyle *aFontStyle) + { +- aFontStyle->style = NS_FONT_STYLE_NORMAL; ++ aFontStyle->style = FontSlantStyle::Normal(); + + // As in + // https://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?h=3.22.19#n10333 +@@ -722,10 +792,10 @@ GetSystemFontInfo(GtkStyleContext *aStyl + NS_ConvertUTF8toUTF16 family(pango_font_description_get_family(desc)); + *aFontName = quote + family + quote; + +- aFontStyle->weight = pango_font_description_get_weight(desc); ++ aFontStyle->weight = FontWeight(pango_font_description_get_weight(desc)); + + // FIXME: Set aFontStyle->stretch correctly! +- aFontStyle->stretch = NS_FONT_STRETCH_NORMAL; ++ aFontStyle->stretch = FontStretch::Normal(); + + float size = float(pango_font_description_get_size(desc)) / PANGO_SCALE; + +@@ -1009,6 +1079,9 @@ nsLookAndFeel::EnsureInit() + mOddCellBackground = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); + ++ // Compute cell highlight colors ++ InitCellHighlightColors(); ++ + // GtkFrame has a "border" subnode on which Adwaita draws the border. + // Some themes do not draw on this node but draw a border on the widget + // root node, so check the root node if no border is found on the border +diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h.wayland thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h +--- thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h 2018-11-20 12:04:43.737787350 +0100 +@@ -77,6 +77,8 @@ protected: + nscolor mMozWindowActiveBorder; + nscolor mMozWindowInactiveBorder; + nscolor mMozWindowInactiveCaption; ++ nscolor mMozCellHighlightBackground; ++ nscolor mMozCellHighlightText; + nscolor mTextSelectedText; + nscolor mTextSelectedBackground; + nscolor mMozScrollbar; +@@ -91,6 +93,9 @@ protected: + bool mInitialized; + + void EnsureInit(); ++ ++private: ++ nsresult InitCellHighlightColors(); + }; + + #endif +diff -up thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp.wayland thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp +--- thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp 2018-11-20 12:04:43.738787347 +0100 +@@ -4,7 +4,7 @@ + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #include "nsNativeThemeGTK.h" +-#include "nsThemeConstants.h" ++#include "nsStyleConsts.h" + #include "gtkdrawing.h" + #include "ScreenHelperGTK.h" + +@@ -39,6 +39,8 @@ + #include "mozilla/gfx/HelpersCairo.h" + #include "mozilla/gfx/PathHelpers.h" + #include "mozilla/Preferences.h" ++#include "mozilla/layers/StackingContextHelper.h" ++#include "mozilla/StaticPrefs.h" + + #ifdef MOZ_X11 + # ifdef CAIRO_HAS_XLIB_SURFACE +@@ -119,7 +121,7 @@ nsNativeThemeGTK::Observe(nsISupports *a + if (!nsCRT::strcmp(aTopic, "xpcom-shutdown")) { + moz_gtk_shutdown(); + } else { +- NS_NOTREACHED("unexpected topic"); ++ MOZ_ASSERT_UNREACHABLE("unexpected topic"); + return NS_ERROR_UNEXPECTED; + } + +@@ -149,41 +151,43 @@ static bool IsFrameContentNodeInNamespac + return content->IsInNamespace(aNamespace); + } + +-static bool IsWidgetTypeDisabled(uint8_t* aDisabledVector, uint8_t aWidgetType) { +- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); +- return (aDisabledVector[aWidgetType >> 3] & (1 << (aWidgetType & 7))) != 0; ++static bool IsWidgetTypeDisabled(uint8_t* aDisabledVector, StyleAppearance aWidgetType) { ++ auto type = static_cast(aWidgetType); ++ MOZ_ASSERT(type < static_cast(mozilla::StyleAppearance::Count)); ++ return (aDisabledVector[type >> 3] & (1 << (type & 7))) != 0; + } + +-static void SetWidgetTypeDisabled(uint8_t* aDisabledVector, uint8_t aWidgetType) { +- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); +- aDisabledVector[aWidgetType >> 3] |= (1 << (aWidgetType & 7)); ++static void SetWidgetTypeDisabled(uint8_t* aDisabledVector, StyleAppearance aWidgetType) { ++ auto type = static_cast(aWidgetType); ++ MOZ_ASSERT(type < static_cast(mozilla::StyleAppearance::Count)); ++ aDisabledVector[type >> 3] |= (1 << (type & 7)); + } + + static inline uint16_t +-GetWidgetStateKey(uint8_t aWidgetType, GtkWidgetState *aWidgetState) ++GetWidgetStateKey(StyleAppearance aWidgetType, GtkWidgetState *aWidgetState) + { + return (aWidgetState->active | + aWidgetState->focused << 1 | + aWidgetState->inHover << 2 | + aWidgetState->disabled << 3 | + aWidgetState->isDefault << 4 | +- aWidgetType << 5); ++ static_cast(aWidgetType) << 5); + } + + static bool IsWidgetStateSafe(uint8_t* aSafeVector, +- uint8_t aWidgetType, +- GtkWidgetState *aWidgetState) ++ StyleAppearance aWidgetType, ++ GtkWidgetState *aWidgetState) + { +- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); ++ MOZ_ASSERT(static_cast(aWidgetType) < static_cast(mozilla::StyleAppearance::Count)); + uint16_t key = GetWidgetStateKey(aWidgetType, aWidgetState); + return (aSafeVector[key >> 3] & (1 << (key & 7))) != 0; + } + + static void SetWidgetStateSafe(uint8_t *aSafeVector, +- uint8_t aWidgetType, ++ StyleAppearance aWidgetType, + GtkWidgetState *aWidgetState) + { +- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); ++ MOZ_ASSERT(static_cast(aWidgetType) < static_cast(mozilla::StyleAppearance::Count)); + uint16_t key = GetWidgetStateKey(aWidgetType, aWidgetState); + aSafeVector[key >> 3] |= (1 << (key & 7)); + } +@@ -213,33 +217,38 @@ nsNativeThemeGTK::GetTabMarginPixels(nsI + } + + static bool ShouldScrollbarButtonBeDisabled(int32_t aCurpos, int32_t aMaxpos, +- uint8_t aWidgetType) ++ StyleAppearance aWidgetType) + { +- return ((aCurpos == 0 && (aWidgetType == NS_THEME_SCROLLBARBUTTON_UP || +- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT)) +- || (aCurpos == aMaxpos && (aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN || +- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT))); ++ return ((aCurpos == 0 && (aWidgetType == StyleAppearance::ScrollbarbuttonUp || ++ aWidgetType == StyleAppearance::ScrollbarbuttonLeft)) ++ || (aCurpos == aMaxpos && (aWidgetType == StyleAppearance::ScrollbarbuttonDown || ++ aWidgetType == StyleAppearance::ScrollbarbuttonRight))); + } + + bool +-nsNativeThemeGTK::GetGtkWidgetAndState(uint8_t aWidgetType, nsIFrame* aFrame, ++nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aWidgetType, nsIFrame* aFrame, + WidgetNodeType& aGtkWidgetType, + GtkWidgetState* aState, + gint* aWidgetFlags) + { ++ if (aWidgetType == StyleAppearance::MenulistButton && ++ StaticPrefs::layout_css_webkit_appearance_enabled()) { ++ aWidgetType = StyleAppearance::Menulist; ++ } ++ + if (aState) { + // For XUL checkboxes and radio buttons, the state of the parent + // determines our state. + nsIFrame *stateFrame = aFrame; +- if (aFrame && ((aWidgetFlags && (aWidgetType == NS_THEME_CHECKBOX || +- aWidgetType == NS_THEME_RADIO)) || +- aWidgetType == NS_THEME_CHECKBOX_LABEL || +- aWidgetType == NS_THEME_RADIO_LABEL)) { ++ if (aFrame && ((aWidgetFlags && (aWidgetType == StyleAppearance::Checkbox || ++ aWidgetType == StyleAppearance::Radio)) || ++ aWidgetType == StyleAppearance::CheckboxLabel || ++ aWidgetType == StyleAppearance::RadioLabel)) { + + nsAtom* atom = nullptr; + if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) { +- if (aWidgetType == NS_THEME_CHECKBOX_LABEL || +- aWidgetType == NS_THEME_RADIO_LABEL) { ++ if (aWidgetType == StyleAppearance::CheckboxLabel || ++ aWidgetType == StyleAppearance::RadioLabel) { + // Adjust stateFrame so GetContentState finds the correct state. + stateFrame = aFrame = aFrame->GetParent()->GetParent(); + } else { +@@ -249,8 +258,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + } + if (aWidgetFlags) { + if (!atom) { +- atom = (aWidgetType == NS_THEME_CHECKBOX || +- aWidgetType == NS_THEME_CHECKBOX_LABEL) ? nsGkAtoms::checked ++ atom = (aWidgetType == StyleAppearance::Checkbox || ++ aWidgetType == StyleAppearance::CheckboxLabel) ? nsGkAtoms::checked + : nsGkAtoms::selected; + } + *aWidgetFlags = CheckBooleanAttr(aFrame, atom); +@@ -258,7 +267,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + } else { + if (aWidgetFlags) { + *aWidgetFlags = 0; +- HTMLInputElement* inputElt = HTMLInputElement::FromContent(aFrame->GetContent()); ++ HTMLInputElement* inputElt = HTMLInputElement::FromNode(aFrame->GetContent()); + if (inputElt && inputElt->Checked()) + *aWidgetFlags |= MOZ_GTK_WIDGET_CHECKED; + +@@ -266,12 +275,12 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + *aWidgetFlags |= MOZ_GTK_WIDGET_INCONSISTENT; + } + } +- } else if (aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN || +- aWidgetType == NS_THEME_TREEHEADERSORTARROW || +- aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS || +- aWidgetType == NS_THEME_BUTTON_ARROW_NEXT || +- aWidgetType == NS_THEME_BUTTON_ARROW_UP || +- aWidgetType == NS_THEME_BUTTON_ARROW_DOWN) { ++ } else if (aWidgetType == StyleAppearance::ToolbarbuttonDropdown || ++ aWidgetType == StyleAppearance::Treeheadersortarrow || ++ aWidgetType == StyleAppearance::ButtonArrowPrevious || ++ aWidgetType == StyleAppearance::ButtonArrowNext || ++ aWidgetType == StyleAppearance::ButtonArrowUp || ++ aWidgetType == StyleAppearance::ButtonArrowDown) { + // The state of an arrow comes from its parent. + stateFrame = aFrame = aFrame->GetParent(); + } +@@ -287,7 +296,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + aState->canDefault = FALSE; // XXX fix me + aState->depressed = FALSE; + +- if (aWidgetType == NS_THEME_FOCUS_OUTLINE) { ++ if (aWidgetType == StyleAppearance::FocusOutline) { + aState->disabled = FALSE; + aState->active = FALSE; + aState->inHover = FALSE; +@@ -296,15 +305,16 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + + aState->focused = TRUE; + aState->depressed = TRUE; // see moz_gtk_entry_paint() +- } else if (aWidgetType == NS_THEME_BUTTON || +- aWidgetType == NS_THEME_TOOLBARBUTTON || +- aWidgetType == NS_THEME_DUALBUTTON || +- aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN || +- aWidgetType == NS_THEME_MENULIST || +- aWidgetType == NS_THEME_MENULIST_BUTTON) { ++ } else if (aWidgetType == StyleAppearance::Button || ++ aWidgetType == StyleAppearance::Toolbarbutton || ++ aWidgetType == StyleAppearance::Dualbutton || ++ aWidgetType == StyleAppearance::ToolbarbuttonDropdown || ++ aWidgetType == StyleAppearance::Menulist || ++ aWidgetType == StyleAppearance::MenulistButton || ++ aWidgetType == StyleAppearance::MozMenulistButton) { + aState->active &= aState->inHover; +- } else if (aWidgetType == NS_THEME_TREETWISTY || +- aWidgetType == NS_THEME_TREETWISTYOPEN) { ++ } else if (aWidgetType == StyleAppearance::Treetwisty || ++ aWidgetType == StyleAppearance::Treetwistyopen) { + nsTreeBodyFrame *treeBodyFrame = do_QueryFrame(aFrame); + if (treeBodyFrame) { + const mozilla::AtomArray& atoms = +@@ -318,22 +328,22 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + // For these widget types, some element (either a child or parent) + // actually has element focus, so we check the focused attribute + // to see whether to draw in the focused state. +- if (aWidgetType == NS_THEME_NUMBER_INPUT || +- aWidgetType == NS_THEME_TEXTFIELD || +- aWidgetType == NS_THEME_TEXTFIELD_MULTILINE || +- aWidgetType == NS_THEME_MENULIST_TEXTFIELD || +- aWidgetType == NS_THEME_SPINNER_TEXTFIELD || +- aWidgetType == NS_THEME_RADIO_CONTAINER || +- aWidgetType == NS_THEME_RADIO_LABEL) { ++ if (aWidgetType == StyleAppearance::NumberInput || ++ aWidgetType == StyleAppearance::Textfield || ++ aWidgetType == StyleAppearance::TextfieldMultiline || ++ aWidgetType == StyleAppearance::MenulistTextfield || ++ aWidgetType == StyleAppearance::SpinnerTextfield || ++ aWidgetType == StyleAppearance::RadioContainer || ++ aWidgetType == StyleAppearance::RadioLabel) { + aState->focused = IsFocused(aFrame); +- } else if (aWidgetType == NS_THEME_RADIO || +- aWidgetType == NS_THEME_CHECKBOX) { ++ } else if (aWidgetType == StyleAppearance::Radio || ++ aWidgetType == StyleAppearance::Checkbox) { + // In XUL, checkboxes and radios shouldn't have focus rings, their labels do + aState->focused = FALSE; + } + +- if (aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL || +- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL) { ++ if (aWidgetType == StyleAppearance::ScrollbarthumbVertical || ++ aWidgetType == StyleAppearance::ScrollbarthumbHorizontal) { + // for scrollbars we need to go up two to go from the thumb to + // the slider to the actual scrollbar object + nsIFrame *tmpFrame = aFrame->GetParent()->GetParent(); +@@ -348,10 +358,10 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + } + } + +- if (aWidgetType == NS_THEME_SCROLLBARBUTTON_UP || +- aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN || +- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT || +- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) { ++ if (aWidgetType == StyleAppearance::ScrollbarbuttonUp || ++ aWidgetType == StyleAppearance::ScrollbarbuttonDown || ++ aWidgetType == StyleAppearance::ScrollbarbuttonLeft || ++ aWidgetType == StyleAppearance::ScrollbarbuttonRight) { + // set the state to disabled when the scrollbar is scrolled to + // the beginning or the end, depending on the button type. + int32_t curpos = CheckIntAttr(aFrame, nsGkAtoms::curpos, 0); +@@ -369,7 +379,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + + if (aWidgetFlags) { + *aWidgetFlags = GetScrollbarButtonType(aFrame); +- if (aWidgetType - NS_THEME_SCROLLBARBUTTON_UP < 2) ++ if (static_cast(aWidgetType) - ++ static_cast(StyleAppearance::ScrollbarbuttonUp) < 2) + *aWidgetFlags |= MOZ_GTK_STEPPER_VERTICAL; + } + } +@@ -379,11 +390,11 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + // menus which are children of a menu bar are only marked as prelight + // if they are open, not on normal hover. + +- if (aWidgetType == NS_THEME_MENUITEM || +- aWidgetType == NS_THEME_CHECKMENUITEM || +- aWidgetType == NS_THEME_RADIOMENUITEM || +- aWidgetType == NS_THEME_MENUSEPARATOR || +- aWidgetType == NS_THEME_MENUARROW) { ++ if (aWidgetType == StyleAppearance::Menuitem || ++ aWidgetType == StyleAppearance::Checkmenuitem || ++ aWidgetType == StyleAppearance::Radiomenuitem || ++ aWidgetType == StyleAppearance::Menuseparator || ++ aWidgetType == StyleAppearance::Menuarrow) { + bool isTopLevel = false; + nsMenuFrame *menuFrame = do_QueryFrame(aFrame); + if (menuFrame) { +@@ -398,8 +409,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + + aState->active = FALSE; + +- if (aWidgetType == NS_THEME_CHECKMENUITEM || +- aWidgetType == NS_THEME_RADIOMENUITEM) { ++ if (aWidgetType == StyleAppearance::Checkmenuitem || ++ aWidgetType == StyleAppearance::Radiomenuitem) { + *aWidgetFlags = 0; + if (aFrame && aFrame->GetContent() && + aFrame->GetContent()->IsElement()) { +@@ -412,12 +423,13 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + + // A button with drop down menu open or an activated toggle button + // should always appear depressed. +- if (aWidgetType == NS_THEME_BUTTON || +- aWidgetType == NS_THEME_TOOLBARBUTTON || +- aWidgetType == NS_THEME_DUALBUTTON || +- aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN || +- aWidgetType == NS_THEME_MENULIST || +- aWidgetType == NS_THEME_MENULIST_BUTTON) { ++ if (aWidgetType == StyleAppearance::Button || ++ aWidgetType == StyleAppearance::Toolbarbutton || ++ aWidgetType == StyleAppearance::Dualbutton || ++ aWidgetType == StyleAppearance::ToolbarbuttonDropdown || ++ aWidgetType == StyleAppearance::Menulist || ++ aWidgetType == StyleAppearance::MenulistButton || ++ aWidgetType == StyleAppearance::MozMenulistButton) { + bool menuOpen = IsOpenButton(aFrame); + aState->depressed = IsCheckedButton(aFrame) || menuOpen; + // we must not highlight buttons with open drop down menus on hover. +@@ -426,79 +438,81 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + + // When the input field of the drop down button has focus, some themes + // should draw focus for the drop down button as well. +- if (aWidgetType == NS_THEME_MENULIST_BUTTON && aWidgetFlags) { ++ if ((aWidgetType == StyleAppearance::MenulistButton || ++ aWidgetType == StyleAppearance::MozMenulistButton) && ++ aWidgetFlags) { + *aWidgetFlags = CheckBooleanAttr(aFrame, nsGkAtoms::parentfocused); + } + } + } + + switch (aWidgetType) { +- case NS_THEME_BUTTON: ++ case StyleAppearance::Button: + if (aWidgetFlags) + *aWidgetFlags = GTK_RELIEF_NORMAL; + aGtkWidgetType = MOZ_GTK_BUTTON; + break; +- case NS_THEME_TOOLBARBUTTON: +- case NS_THEME_DUALBUTTON: ++ case StyleAppearance::Toolbarbutton: ++ case StyleAppearance::Dualbutton: + if (aWidgetFlags) + *aWidgetFlags = GTK_RELIEF_NONE; + aGtkWidgetType = MOZ_GTK_TOOLBAR_BUTTON; + break; +- case NS_THEME_FOCUS_OUTLINE: ++ case StyleAppearance::FocusOutline: + aGtkWidgetType = MOZ_GTK_ENTRY; + break; +- case NS_THEME_CHECKBOX: +- case NS_THEME_RADIO: +- aGtkWidgetType = (aWidgetType == NS_THEME_RADIO) ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON; +- break; +- case NS_THEME_SCROLLBARBUTTON_UP: +- case NS_THEME_SCROLLBARBUTTON_DOWN: +- case NS_THEME_SCROLLBARBUTTON_LEFT: +- case NS_THEME_SCROLLBARBUTTON_RIGHT: ++ case StyleAppearance::Checkbox: ++ case StyleAppearance::Radio: ++ aGtkWidgetType = (aWidgetType == StyleAppearance::Radio) ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON; ++ break; ++ case StyleAppearance::ScrollbarbuttonUp: ++ case StyleAppearance::ScrollbarbuttonDown: ++ case StyleAppearance::ScrollbarbuttonLeft: ++ case StyleAppearance::ScrollbarbuttonRight: + aGtkWidgetType = MOZ_GTK_SCROLLBAR_BUTTON; + break; +- case NS_THEME_SCROLLBAR_VERTICAL: ++ case StyleAppearance::ScrollbarVertical: + aGtkWidgetType = MOZ_GTK_SCROLLBAR_VERTICAL; + if (GetWidgetTransparency(aFrame, aWidgetType) == eOpaque) + *aWidgetFlags = MOZ_GTK_TRACK_OPAQUE; + else + *aWidgetFlags = 0; + break; +- case NS_THEME_SCROLLBAR_HORIZONTAL: ++ case StyleAppearance::ScrollbarHorizontal: + aGtkWidgetType = MOZ_GTK_SCROLLBAR_HORIZONTAL; + if (GetWidgetTransparency(aFrame, aWidgetType) == eOpaque) + *aWidgetFlags = MOZ_GTK_TRACK_OPAQUE; + else + *aWidgetFlags = 0; + break; +- case NS_THEME_SCROLLBARTRACK_HORIZONTAL: ++ case StyleAppearance::ScrollbartrackHorizontal: + aGtkWidgetType = MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL; + break; +- case NS_THEME_SCROLLBARTRACK_VERTICAL: ++ case StyleAppearance::ScrollbartrackVertical: + aGtkWidgetType = MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL; + break; +- case NS_THEME_SCROLLBARTHUMB_VERTICAL: ++ case StyleAppearance::ScrollbarthumbVertical: + aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL; + break; +- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: ++ case StyleAppearance::ScrollbarthumbHorizontal: + aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; + break; +- case NS_THEME_INNER_SPIN_BUTTON: ++ case StyleAppearance::InnerSpinButton: + aGtkWidgetType = MOZ_GTK_INNER_SPIN_BUTTON; + break; +- case NS_THEME_SPINNER: ++ case StyleAppearance::Spinner: + aGtkWidgetType = MOZ_GTK_SPINBUTTON; + break; +- case NS_THEME_SPINNER_UPBUTTON: ++ case StyleAppearance::SpinnerUpbutton: + aGtkWidgetType = MOZ_GTK_SPINBUTTON_UP; + break; +- case NS_THEME_SPINNER_DOWNBUTTON: ++ case StyleAppearance::SpinnerDownbutton: + aGtkWidgetType = MOZ_GTK_SPINBUTTON_DOWN; + break; +- case NS_THEME_SPINNER_TEXTFIELD: ++ case StyleAppearance::SpinnerTextfield: + aGtkWidgetType = MOZ_GTK_SPINBUTTON_ENTRY; + break; +- case NS_THEME_RANGE: ++ case StyleAppearance::Range: + { + if (IsRangeHorizontal(aFrame)) { + if (aWidgetFlags) +@@ -511,7 +525,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + } + break; + } +- case NS_THEME_RANGE_THUMB: ++ case StyleAppearance::RangeThumb: + { + if (IsRangeHorizontal(aFrame)) { + if (aWidgetFlags) +@@ -524,51 +538,51 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + } + break; + } +- case NS_THEME_SCALE_HORIZONTAL: ++ case StyleAppearance::ScaleHorizontal: + if (aWidgetFlags) + *aWidgetFlags = GTK_ORIENTATION_HORIZONTAL; + aGtkWidgetType = MOZ_GTK_SCALE_HORIZONTAL; + break; +- case NS_THEME_SCALETHUMB_HORIZONTAL: ++ case StyleAppearance::ScalethumbHorizontal: + if (aWidgetFlags) + *aWidgetFlags = GTK_ORIENTATION_HORIZONTAL; + aGtkWidgetType = MOZ_GTK_SCALE_THUMB_HORIZONTAL; + break; +- case NS_THEME_SCALE_VERTICAL: ++ case StyleAppearance::ScaleVertical: + if (aWidgetFlags) + *aWidgetFlags = GTK_ORIENTATION_VERTICAL; + aGtkWidgetType = MOZ_GTK_SCALE_VERTICAL; + break; +- case NS_THEME_SEPARATOR: ++ case StyleAppearance::Separator: + aGtkWidgetType = MOZ_GTK_TOOLBAR_SEPARATOR; + break; +- case NS_THEME_SCALETHUMB_VERTICAL: ++ case StyleAppearance::ScalethumbVertical: + if (aWidgetFlags) + *aWidgetFlags = GTK_ORIENTATION_VERTICAL; + aGtkWidgetType = MOZ_GTK_SCALE_THUMB_VERTICAL; + break; +- case NS_THEME_TOOLBARGRIPPER: ++ case StyleAppearance::Toolbargripper: + aGtkWidgetType = MOZ_GTK_GRIPPER; + break; +- case NS_THEME_RESIZER: ++ case StyleAppearance::Resizer: + aGtkWidgetType = MOZ_GTK_RESIZER; + break; +- case NS_THEME_NUMBER_INPUT: +- case NS_THEME_TEXTFIELD: ++ case StyleAppearance::NumberInput: ++ case StyleAppearance::Textfield: + aGtkWidgetType = MOZ_GTK_ENTRY; + break; +- case NS_THEME_TEXTFIELD_MULTILINE: ++ case StyleAppearance::TextfieldMultiline: + #ifdef MOZ_WIDGET_GTK + aGtkWidgetType = MOZ_GTK_TEXT_VIEW; + #else + aGtkWidgetType = MOZ_GTK_ENTRY; + #endif + break; +- case NS_THEME_LISTBOX: +- case NS_THEME_TREEVIEW: ++ case StyleAppearance::Listbox: ++ case StyleAppearance::Treeview: + aGtkWidgetType = MOZ_GTK_TREEVIEW; + break; +- case NS_THEME_TREEHEADERCELL: ++ case StyleAppearance::Treeheadercell: + if (aWidgetFlags) { + // In this case, the flag denotes whether the header is the sorted one or not + if (GetTreeSortDirection(aFrame) == eTreeSortDirection_Natural) +@@ -578,7 +592,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + } + aGtkWidgetType = MOZ_GTK_TREE_HEADER_CELL; + break; +- case NS_THEME_TREEHEADERSORTARROW: ++ case StyleAppearance::Treeheadersortarrow: + if (aWidgetFlags) { + switch (GetTreeSortDirection(aFrame)) { + case eTreeSortDirection_Ascending: +@@ -598,74 +612,75 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + } + aGtkWidgetType = MOZ_GTK_TREE_HEADER_SORTARROW; + break; +- case NS_THEME_TREETWISTY: ++ case StyleAppearance::Treetwisty: + aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER; + if (aWidgetFlags) + *aWidgetFlags = GTK_EXPANDER_COLLAPSED; + break; +- case NS_THEME_TREETWISTYOPEN: ++ case StyleAppearance::Treetwistyopen: + aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER; + if (aWidgetFlags) + *aWidgetFlags = GTK_EXPANDER_EXPANDED; + break; +- case NS_THEME_MENULIST: ++ case StyleAppearance::Menulist: + aGtkWidgetType = MOZ_GTK_DROPDOWN; + if (aWidgetFlags) + *aWidgetFlags = IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XHTML); + break; +- case NS_THEME_MENULIST_TEXT: ++ case StyleAppearance::MenulistText: + return false; // nothing to do, but prevents the bg from being drawn +- case NS_THEME_MENULIST_TEXTFIELD: ++ case StyleAppearance::MenulistTextfield: + aGtkWidgetType = MOZ_GTK_DROPDOWN_ENTRY; + break; +- case NS_THEME_MENULIST_BUTTON: ++ case StyleAppearance::MenulistButton: ++ case StyleAppearance::MozMenulistButton: + aGtkWidgetType = MOZ_GTK_DROPDOWN_ARROW; + break; +- case NS_THEME_TOOLBARBUTTON_DROPDOWN: +- case NS_THEME_BUTTON_ARROW_DOWN: +- case NS_THEME_BUTTON_ARROW_UP: +- case NS_THEME_BUTTON_ARROW_NEXT: +- case NS_THEME_BUTTON_ARROW_PREVIOUS: ++ case StyleAppearance::ToolbarbuttonDropdown: ++ case StyleAppearance::ButtonArrowDown: ++ case StyleAppearance::ButtonArrowUp: ++ case StyleAppearance::ButtonArrowNext: ++ case StyleAppearance::ButtonArrowPrevious: + aGtkWidgetType = MOZ_GTK_TOOLBARBUTTON_ARROW; + if (aWidgetFlags) { + *aWidgetFlags = GTK_ARROW_DOWN; + +- if (aWidgetType == NS_THEME_BUTTON_ARROW_UP) ++ if (aWidgetType == StyleAppearance::ButtonArrowUp) + *aWidgetFlags = GTK_ARROW_UP; +- else if (aWidgetType == NS_THEME_BUTTON_ARROW_NEXT) ++ else if (aWidgetType == StyleAppearance::ButtonArrowNext) + *aWidgetFlags = GTK_ARROW_RIGHT; +- else if (aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS) ++ else if (aWidgetType == StyleAppearance::ButtonArrowPrevious) + *aWidgetFlags = GTK_ARROW_LEFT; + } + break; +- case NS_THEME_CHECKBOX_CONTAINER: ++ case StyleAppearance::CheckboxContainer: + aGtkWidgetType = MOZ_GTK_CHECKBUTTON_CONTAINER; + break; +- case NS_THEME_RADIO_CONTAINER: ++ case StyleAppearance::RadioContainer: + aGtkWidgetType = MOZ_GTK_RADIOBUTTON_CONTAINER; + break; +- case NS_THEME_CHECKBOX_LABEL: ++ case StyleAppearance::CheckboxLabel: + aGtkWidgetType = MOZ_GTK_CHECKBUTTON_LABEL; + break; +- case NS_THEME_RADIO_LABEL: ++ case StyleAppearance::RadioLabel: + aGtkWidgetType = MOZ_GTK_RADIOBUTTON_LABEL; + break; +- case NS_THEME_TOOLBAR: ++ case StyleAppearance::Toolbar: + aGtkWidgetType = MOZ_GTK_TOOLBAR; + break; +- case NS_THEME_TOOLTIP: ++ case StyleAppearance::Tooltip: + aGtkWidgetType = MOZ_GTK_TOOLTIP; + break; +- case NS_THEME_STATUSBARPANEL: +- case NS_THEME_RESIZERPANEL: ++ case StyleAppearance::Statusbarpanel: ++ case StyleAppearance::Resizerpanel: + aGtkWidgetType = MOZ_GTK_FRAME; + break; +- case NS_THEME_PROGRESSBAR: +- case NS_THEME_PROGRESSBAR_VERTICAL: ++ case StyleAppearance::Progressbar: ++ case StyleAppearance::ProgressbarVertical: + aGtkWidgetType = MOZ_GTK_PROGRESSBAR; + break; +- case NS_THEME_PROGRESSCHUNK: +- case NS_THEME_PROGRESSCHUNK_VERTICAL: ++ case StyleAppearance::Progresschunk: ++ case StyleAppearance::ProgresschunkVertical: + { + nsIFrame* stateFrame = aFrame->GetParent(); + EventStates eventStates = GetContentState(stateFrame, aWidgetType); +@@ -677,17 +692,17 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + : MOZ_GTK_PROGRESS_CHUNK; + } + break; +- case NS_THEME_TAB_SCROLL_ARROW_BACK: +- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: ++ case StyleAppearance::TabScrollArrowBack: ++ case StyleAppearance::TabScrollArrowForward: + if (aWidgetFlags) +- *aWidgetFlags = aWidgetType == NS_THEME_TAB_SCROLL_ARROW_BACK ? ++ *aWidgetFlags = aWidgetType == StyleAppearance::TabScrollArrowBack ? + GTK_ARROW_LEFT : GTK_ARROW_RIGHT; + aGtkWidgetType = MOZ_GTK_TAB_SCROLLARROW; + break; +- case NS_THEME_TABPANELS: ++ case StyleAppearance::Tabpanels: + aGtkWidgetType = MOZ_GTK_TABPANELS; + break; +- case NS_THEME_TAB: ++ case StyleAppearance::Tab: + { + if (IsBottomTab(aFrame)) { + aGtkWidgetType = MOZ_GTK_TAB_BOTTOM; +@@ -709,19 +724,19 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + } + } + break; +- case NS_THEME_SPLITTER: ++ case StyleAppearance::Splitter: + if (IsHorizontal(aFrame)) + aGtkWidgetType = MOZ_GTK_SPLITTER_VERTICAL; + else + aGtkWidgetType = MOZ_GTK_SPLITTER_HORIZONTAL; + break; +- case NS_THEME_MENUBAR: ++ case StyleAppearance::Menubar: + aGtkWidgetType = MOZ_GTK_MENUBAR; + break; +- case NS_THEME_MENUPOPUP: ++ case StyleAppearance::Menupopup: + aGtkWidgetType = MOZ_GTK_MENUPOPUP; + break; +- case NS_THEME_MENUITEM: ++ case StyleAppearance::Menuitem: + { + nsMenuFrame *menuFrame = do_QueryFrame(aFrame); + if (menuFrame && menuFrame->IsOnMenuBar()) { +@@ -731,41 +746,41 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + } + aGtkWidgetType = MOZ_GTK_MENUITEM; + break; +- case NS_THEME_MENUSEPARATOR: ++ case StyleAppearance::Menuseparator: + aGtkWidgetType = MOZ_GTK_MENUSEPARATOR; + break; +- case NS_THEME_MENUARROW: ++ case StyleAppearance::Menuarrow: + aGtkWidgetType = MOZ_GTK_MENUARROW; + break; +- case NS_THEME_CHECKMENUITEM: ++ case StyleAppearance::Checkmenuitem: + aGtkWidgetType = MOZ_GTK_CHECKMENUITEM; + break; +- case NS_THEME_RADIOMENUITEM: ++ case StyleAppearance::Radiomenuitem: + aGtkWidgetType = MOZ_GTK_RADIOMENUITEM; + break; +- case NS_THEME_WINDOW: +- case NS_THEME_DIALOG: ++ case StyleAppearance::Window: ++ case StyleAppearance::Dialog: + aGtkWidgetType = MOZ_GTK_WINDOW; + break; +- case NS_THEME_GTK_INFO_BAR: ++ case StyleAppearance::MozGtkInfoBar: + aGtkWidgetType = MOZ_GTK_INFO_BAR; + break; +- case NS_THEME_WINDOW_TITLEBAR: ++ case StyleAppearance::MozWindowTitlebar: + aGtkWidgetType = MOZ_GTK_HEADER_BAR; + break; +- case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED: ++ case StyleAppearance::MozWindowTitlebarMaximized: + aGtkWidgetType = MOZ_GTK_HEADER_BAR_MAXIMIZED; + break; +- case NS_THEME_WINDOW_BUTTON_CLOSE: ++ case StyleAppearance::MozWindowButtonClose: + aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_CLOSE; + break; +- case NS_THEME_WINDOW_BUTTON_MINIMIZE: ++ case StyleAppearance::MozWindowButtonMinimize: + aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE; + break; +- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: ++ case StyleAppearance::MozWindowButtonMaximize: + aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE; + break; +- case NS_THEME_WINDOW_BUTTON_RESTORE: ++ case StyleAppearance::MozWindowButtonRestore: + aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE; + break; + default: +@@ -1025,7 +1040,8 @@ DrawThemeWithCairo(gfxContext* aContext, + } + + bool +-nsNativeThemeGTK::GetExtraSizeForWidget(nsIFrame* aFrame, uint8_t aWidgetType, ++nsNativeThemeGTK::GetExtraSizeForWidget(nsIFrame* aFrame, ++ StyleAppearance aWidgetType, + nsIntMargin* aExtra) + { + *aExtra = nsIntMargin(0,0,0,0); +@@ -1033,14 +1049,14 @@ nsNativeThemeGTK::GetExtraSizeForWidget( + // GTK2 themes (Ximian Industrial, Bluecurve, Misty, at least); + // We modify the frame's overflow area. See bug 297508. + switch (aWidgetType) { +- case NS_THEME_SCROLLBARTHUMB_VERTICAL: ++ case StyleAppearance::ScrollbarthumbVertical: + aExtra->top = aExtra->bottom = 1; + break; +- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: ++ case StyleAppearance::ScrollbarthumbHorizontal: + aExtra->left = aExtra->right = 1; + break; + +- case NS_THEME_BUTTON : ++ case StyleAppearance::Button : + { + if (IsDefaultButton(aFrame)) { + // Some themes draw a default indicator outside the widget, +@@ -1055,14 +1071,14 @@ nsNativeThemeGTK::GetExtraSizeForWidget( + } + return false; + } +- case NS_THEME_FOCUS_OUTLINE: ++ case StyleAppearance::FocusOutline: + { + moz_gtk_get_focus_outline_size(&aExtra->left, &aExtra->top); + aExtra->right = aExtra->left; + aExtra->bottom = aExtra->top; + break; + } +- case NS_THEME_TAB : ++ case StyleAppearance::Tab : + { + if (!IsSelectedTab(aFrame)) + return false; +@@ -1097,7 +1113,7 @@ nsNativeThemeGTK::GetExtraSizeForWidget( + NS_IMETHODIMP + nsNativeThemeGTK::DrawWidgetBackground(gfxContext* aContext, + nsIFrame* aFrame, +- uint8_t aWidgetType, ++ StyleAppearance aWidgetType, + const nsRect& aRect, + const nsRect& aDirtyRect) + { +@@ -1191,8 +1207,8 @@ nsNativeThemeGTK::DrawWidgetBackground(g + #ifdef DEBUG + printf("GTK theme failed for widget type %d, error was %d, state was " + "[active=%d,focused=%d,inHover=%d,disabled=%d]\n", +- aWidgetType, gLastGdkError, state.active, state.focused, +- state.inHover, state.disabled); ++ static_cast(aWidgetType), gLastGdkError, state.active, ++ state.focused, state.inHover, state.disabled); + #endif + NS_WARNING("GTK theme failed; disabling unsafe widget"); + SetWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType); +@@ -1221,16 +1237,16 @@ nsNativeThemeGTK::CreateWebRenderCommand + const mozilla::layers::StackingContextHelper& aSc, + mozilla::layers::WebRenderLayerManager* aManager, + nsIFrame* aFrame, +- uint8_t aWidgetType, ++ StyleAppearance aWidgetType, + const nsRect& aRect) + { + nsPresContext* presContext = aFrame->PresContext(); +- wr::LayoutRect bounds = aSc.ToRelativeLayoutRect( ++ wr::LayoutRect bounds = wr::ToRoundedLayoutRect( + LayoutDeviceRect::FromAppUnits(aRect, presContext->AppUnitsPerDevPixel())); + + switch (aWidgetType) { +- case NS_THEME_WINDOW: +- case NS_THEME_DIALOG: ++ case StyleAppearance::Window: ++ case StyleAppearance::Dialog: + aBuilder.PushRect(bounds, bounds, true, + wr::ToColorF(Color::FromABGR( + LookAndFeel::GetColor(LookAndFeel::eColorID_WindowBackground, +@@ -1243,7 +1259,7 @@ nsNativeThemeGTK::CreateWebRenderCommand + } + + WidgetNodeType +-nsNativeThemeGTK::NativeThemeToGtkTheme(uint8_t aWidgetType, nsIFrame* aFrame) ++nsNativeThemeGTK::NativeThemeToGtkTheme(StyleAppearance aWidgetType, nsIFrame* aFrame) + { + WidgetNodeType gtkWidgetType; + gint unusedFlags; +@@ -1258,9 +1274,10 @@ nsNativeThemeGTK::NativeThemeToGtkTheme( + } + + void +-nsNativeThemeGTK::GetCachedWidgetBorder(nsIFrame* aFrame, uint8_t aWidgetType, ++nsNativeThemeGTK::GetCachedWidgetBorder(nsIFrame* aFrame, ++ StyleAppearance aWidgetType, + GtkTextDirection aDirection, +- nsIntMargin* aResult) ++ LayoutDeviceIntMargin* aResult) + { + aResult->SizeTo(0, 0, 0, 0); + +@@ -1277,7 +1294,7 @@ nsNativeThemeGTK::GetCachedWidgetBorder( + } else { + moz_gtk_get_widget_border(gtkWidgetType, &aResult->left, &aResult->top, + &aResult->right, &aResult->bottom, aDirection); +- if (aWidgetType != MOZ_GTK_DROPDOWN) { // depends on aDirection ++ if (gtkWidgetType != MOZ_GTK_DROPDOWN) { // depends on aDirection + mBorderCacheValid[cacheIndex] |= cacheBit; + mBorderCache[gtkWidgetType] = *aResult; + } +@@ -1285,49 +1302,52 @@ nsNativeThemeGTK::GetCachedWidgetBorder( + } + } + +-NS_IMETHODIMP +-nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, +- uint8_t aWidgetType, nsIntMargin* aResult) ++LayoutDeviceIntMargin ++nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, ++ nsIFrame* aFrame, ++ StyleAppearance aWidgetType) + { ++ LayoutDeviceIntMargin result; + GtkTextDirection direction = GetTextDirection(aFrame); +- aResult->top = aResult->left = aResult->right = aResult->bottom = 0; + switch (aWidgetType) { +- case NS_THEME_SCROLLBAR_HORIZONTAL: +- case NS_THEME_SCROLLBAR_VERTICAL: ++ case StyleAppearance::ScrollbarHorizontal: ++ case StyleAppearance::ScrollbarVertical: + { + GtkOrientation orientation = +- aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? ++ aWidgetType == StyleAppearance::ScrollbarHorizontal ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; +- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); ++ const ScrollbarGTKMetrics* metrics = ++ GetActiveScrollbarMetrics(orientation); + + const GtkBorder& border = metrics->border.scrollbar; +- aResult->top = border.top; +- aResult->right = border.right; +- aResult->bottom = border.bottom; +- aResult->left = border.left; ++ result.top = border.top; ++ result.right = border.right; ++ result.bottom = border.bottom; ++ result.left = border.left; + } + break; +- case NS_THEME_SCROLLBARTRACK_HORIZONTAL: +- case NS_THEME_SCROLLBARTRACK_VERTICAL: ++ case StyleAppearance::ScrollbartrackHorizontal: ++ case StyleAppearance::ScrollbartrackVertical: + { + GtkOrientation orientation = +- aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL ? ++ aWidgetType == StyleAppearance::ScrollbartrackHorizontal ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; +- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); ++ const ScrollbarGTKMetrics* metrics = ++ GetActiveScrollbarMetrics(orientation); + + const GtkBorder& border = metrics->border.track; +- aResult->top = border.top; +- aResult->right = border.right; +- aResult->bottom = border.bottom; +- aResult->left = border.left; ++ result.top = border.top; ++ result.right = border.right; ++ result.bottom = border.bottom; ++ result.left = border.left; + } + break; +- case NS_THEME_TOOLBOX: ++ case StyleAppearance::Toolbox: + // gtk has no toolbox equivalent. So, although we map toolbox to + // gtk's 'toolbar' for purposes of painting the widget background, + // we don't use the toolbar border for toolbox. + break; +- case NS_THEME_DUALBUTTON: ++ case StyleAppearance::Dualbutton: + // TOOLBAR_DUAL_BUTTON is an interesting case. We want a border to draw + // around the entire button + dropdown, and also an inner border if you're + // over the button part. But, we want the inner button to be right up +@@ -1335,23 +1355,23 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi + // To make this happen, we draw a button border for the outer button, + // but don't reserve any space for it. + break; +- case NS_THEME_TAB: ++ case StyleAppearance::Tab: + { + WidgetNodeType gtkWidgetType; + gint flags; + + if (!GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nullptr, +- &flags)) +- return NS_OK; +- +- moz_gtk_get_tab_border(&aResult->left, &aResult->top, +- &aResult->right, &aResult->bottom, direction, ++ &flags)) { ++ return result; ++ } ++ moz_gtk_get_tab_border(&result.left, &result.top, ++ &result.right, &result.bottom, direction, + (GtkTabFlags)flags, gtkWidgetType); + } + break; +- case NS_THEME_MENUITEM: +- case NS_THEME_CHECKMENUITEM: +- case NS_THEME_RADIOMENUITEM: ++ case StyleAppearance::Menuitem: ++ case StyleAppearance::Checkmenuitem: ++ case StyleAppearance::Radiomenuitem: + // For regular menuitems, we will be using GetWidgetPadding instead of + // GetWidgetBorder to pad up the widget's internals; other menuitems + // will need to fall through and use the default case as before. +@@ -1360,50 +1380,57 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi + MOZ_FALLTHROUGH; + default: + { +- GetCachedWidgetBorder(aFrame, aWidgetType, direction, aResult); ++ GetCachedWidgetBorder(aFrame, aWidgetType, direction, &result); + } + } + + gint scale = GetMonitorScaleFactor(aFrame); +- aResult->top *= scale; +- aResult->right *= scale; +- aResult->bottom *= scale; +- aResult->left *= scale; +- return NS_OK; ++ result.top *= scale; ++ result.right *= scale; ++ result.bottom *= scale; ++ result.left *= scale; ++ return result; + } + + bool + nsNativeThemeGTK::GetWidgetPadding(nsDeviceContext* aContext, +- nsIFrame* aFrame, uint8_t aWidgetType, +- nsIntMargin* aResult) +-{ ++ nsIFrame* aFrame, ++ StyleAppearance aWidgetType, ++ LayoutDeviceIntMargin* aResult) ++{ ++ if (aWidgetType == StyleAppearance::MenulistButton && ++ StaticPrefs::layout_css_webkit_appearance_enabled()) { ++ aWidgetType = StyleAppearance::Menulist; ++ } ++ + switch (aWidgetType) { +- case NS_THEME_BUTTON_FOCUS: +- case NS_THEME_TOOLBARBUTTON: +- case NS_THEME_WINDOW_BUTTON_CLOSE: +- case NS_THEME_WINDOW_BUTTON_MINIMIZE: +- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: +- case NS_THEME_WINDOW_BUTTON_RESTORE: +- case NS_THEME_DUALBUTTON: +- case NS_THEME_TAB_SCROLL_ARROW_BACK: +- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: +- case NS_THEME_MENULIST_BUTTON: +- case NS_THEME_TOOLBARBUTTON_DROPDOWN: +- case NS_THEME_BUTTON_ARROW_UP: +- case NS_THEME_BUTTON_ARROW_DOWN: +- case NS_THEME_BUTTON_ARROW_NEXT: +- case NS_THEME_BUTTON_ARROW_PREVIOUS: +- case NS_THEME_RANGE_THUMB: ++ case StyleAppearance::ButtonFocus: ++ case StyleAppearance::Toolbarbutton: ++ case StyleAppearance::MozWindowButtonClose: ++ case StyleAppearance::MozWindowButtonMinimize: ++ case StyleAppearance::MozWindowButtonMaximize: ++ case StyleAppearance::MozWindowButtonRestore: ++ case StyleAppearance::Dualbutton: ++ case StyleAppearance::TabScrollArrowBack: ++ case StyleAppearance::TabScrollArrowForward: ++ case StyleAppearance::MenulistButton: ++ case StyleAppearance::MozMenulistButton: ++ case StyleAppearance::ToolbarbuttonDropdown: ++ case StyleAppearance::ButtonArrowUp: ++ case StyleAppearance::ButtonArrowDown: ++ case StyleAppearance::ButtonArrowNext: ++ case StyleAppearance::ButtonArrowPrevious: ++ case StyleAppearance::RangeThumb: + // Radios and checkboxes return a fixed size in GetMinimumWidgetSize + // and have a meaningful baseline, so they can't have + // author-specified padding. +- case NS_THEME_CHECKBOX: +- case NS_THEME_RADIO: ++ case StyleAppearance::Checkbox: ++ case StyleAppearance::Radio: + aResult->SizeTo(0, 0, 0, 0); + return true; +- case NS_THEME_MENUITEM: +- case NS_THEME_CHECKMENUITEM: +- case NS_THEME_RADIOMENUITEM: ++ case StyleAppearance::Menuitem: ++ case StyleAppearance::Checkmenuitem: ++ case StyleAppearance::Radiomenuitem: + { + // Menubar and menulist have their padding specified in CSS. + if (!IsRegularMenuItem(aFrame)) +@@ -1413,8 +1440,7 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev + aResult); + + gint horizontal_padding; +- +- if (aWidgetType == NS_THEME_MENUITEM) ++ if (aWidgetType == StyleAppearance::Menuitem) + moz_gtk_menuitem_get_horizontal_padding(&horizontal_padding); + else + moz_gtk_checkmenuitem_get_horizontal_padding(&horizontal_padding); +@@ -1430,6 +1456,8 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev + + return true; + } ++ default: ++ break; + } + + return false; +@@ -1437,7 +1465,8 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev + + bool + nsNativeThemeGTK::GetWidgetOverflow(nsDeviceContext* aContext, +- nsIFrame* aFrame, uint8_t aWidgetType, ++ nsIFrame* aFrame, ++ StyleAppearance aWidgetType, + nsRect* aOverflowRect) + { + nsIntMargin extraSize; +@@ -1456,37 +1485,43 @@ nsNativeThemeGTK::GetWidgetOverflow(nsDe + + NS_IMETHODIMP + nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, +- nsIFrame* aFrame, uint8_t aWidgetType, ++ nsIFrame* aFrame, ++ StyleAppearance aWidgetType, + LayoutDeviceIntSize* aResult, + bool* aIsOverridable) + { + aResult->width = aResult->height = 0; + *aIsOverridable = true; + ++ if (aWidgetType == StyleAppearance::MenulistButton && ++ StaticPrefs::layout_css_webkit_appearance_enabled()) { ++ aWidgetType = StyleAppearance::Menulist; ++ } ++ + switch (aWidgetType) { +- case NS_THEME_SCROLLBARBUTTON_UP: +- case NS_THEME_SCROLLBARBUTTON_DOWN: ++ case StyleAppearance::ScrollbarbuttonUp: ++ case StyleAppearance::ScrollbarbuttonDown: + { + const ScrollbarGTKMetrics* metrics = +- GetScrollbarMetrics(GTK_ORIENTATION_VERTICAL, true); ++ GetActiveScrollbarMetrics(GTK_ORIENTATION_VERTICAL); + + aResult->width = metrics->size.button.width; + aResult->height = metrics->size.button.height; + *aIsOverridable = false; + } + break; +- case NS_THEME_SCROLLBARBUTTON_LEFT: +- case NS_THEME_SCROLLBARBUTTON_RIGHT: ++ case StyleAppearance::ScrollbarbuttonLeft: ++ case StyleAppearance::ScrollbarbuttonRight: + { + const ScrollbarGTKMetrics* metrics = +- GetScrollbarMetrics(GTK_ORIENTATION_HORIZONTAL, true); ++ GetActiveScrollbarMetrics(GTK_ORIENTATION_HORIZONTAL); + + aResult->width = metrics->size.button.width; + aResult->height = metrics->size.button.height; + *aIsOverridable = false; + } + break; +- case NS_THEME_SPLITTER: ++ case StyleAppearance::Splitter: + { + gint metrics; + if (IsHorizontal(aFrame)) { +@@ -1501,8 +1536,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + *aIsOverridable = false; + } + break; +- case NS_THEME_SCROLLBAR_HORIZONTAL: +- case NS_THEME_SCROLLBAR_VERTICAL: ++ case StyleAppearance::ScrollbarHorizontal: ++ case StyleAppearance::ScrollbarVertical: + { + /* While we enforce a minimum size for the thumb, this is ignored + * for the some scrollbars if buttons are hidden (bug 513006) because +@@ -1510,28 +1545,30 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + * or track. So add a minimum size to the track as well to prevent a + * 0-width scrollbar. */ + GtkOrientation orientation = +- aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? ++ aWidgetType == StyleAppearance::ScrollbarHorizontal ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; +- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); ++ const ScrollbarGTKMetrics* metrics = ++ GetActiveScrollbarMetrics(orientation); + + aResult->width = metrics->size.scrollbar.width; + aResult->height = metrics->size.scrollbar.height; + } + break; +- case NS_THEME_SCROLLBARTHUMB_VERTICAL: +- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: ++ case StyleAppearance::ScrollbarthumbVertical: ++ case StyleAppearance::ScrollbarthumbHorizontal: + { + GtkOrientation orientation = +- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL ? ++ aWidgetType == StyleAppearance::ScrollbarthumbHorizontal ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; +- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); ++ const ScrollbarGTKMetrics* metrics = ++ GetActiveScrollbarMetrics(orientation); + + aResult->width = metrics->size.thumb.width; + aResult->height = metrics->size.thumb.height; + *aIsOverridable = false; + } + break; +- case NS_THEME_RANGE_THUMB: ++ case StyleAppearance::RangeThumb: + { + gint thumb_length, thumb_height; + +@@ -1546,7 +1583,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + *aIsOverridable = false; + } + break; +- case NS_THEME_RANGE: ++ case StyleAppearance::Range: + { + gint scale_width, scale_height; + +@@ -1559,12 +1596,12 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + *aIsOverridable = true; + } + break; +- case NS_THEME_SCALETHUMB_HORIZONTAL: +- case NS_THEME_SCALETHUMB_VERTICAL: ++ case StyleAppearance::ScalethumbHorizontal: ++ case StyleAppearance::ScalethumbVertical: + { + gint thumb_length, thumb_height; + +- if (aWidgetType == NS_THEME_SCALETHUMB_VERTICAL) { ++ if (aWidgetType == StyleAppearance::ScalethumbVertical) { + moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_length, &thumb_height); + aResult->width = thumb_height; + aResult->height = thumb_length; +@@ -1577,21 +1614,22 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + *aIsOverridable = false; + } + break; +- case NS_THEME_TAB_SCROLL_ARROW_BACK: +- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: ++ case StyleAppearance::TabScrollArrowBack: ++ case StyleAppearance::TabScrollArrowForward: + { + moz_gtk_get_tab_scroll_arrow_size(&aResult->width, &aResult->height); + *aIsOverridable = false; + } + break; +- case NS_THEME_MENULIST_BUTTON: ++ case StyleAppearance::MenulistButton: ++ case StyleAppearance::MozMenulistButton: + { + moz_gtk_get_combo_box_entry_button_size(&aResult->width, + &aResult->height); + *aIsOverridable = false; + } + break; +- case NS_THEME_MENUSEPARATOR: ++ case StyleAppearance::Menuseparator: + { + gint separator_height; + +@@ -1601,26 +1639,26 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + *aIsOverridable = false; + } + break; +- case NS_THEME_CHECKBOX: +- case NS_THEME_RADIO: ++ case StyleAppearance::Checkbox: ++ case StyleAppearance::Radio: + { +- const ToggleGTKMetrics* metrics = GetToggleMetrics(aWidgetType == NS_THEME_RADIO); ++ const ToggleGTKMetrics* metrics = GetToggleMetrics(aWidgetType == StyleAppearance::Radio); + aResult->width = metrics->minSizeWithBorder.width; + aResult->height = metrics->minSizeWithBorder.height; + } + break; +- case NS_THEME_TOOLBARBUTTON_DROPDOWN: +- case NS_THEME_BUTTON_ARROW_UP: +- case NS_THEME_BUTTON_ARROW_DOWN: +- case NS_THEME_BUTTON_ARROW_NEXT: +- case NS_THEME_BUTTON_ARROW_PREVIOUS: ++ case StyleAppearance::ToolbarbuttonDropdown: ++ case StyleAppearance::ButtonArrowUp: ++ case StyleAppearance::ButtonArrowDown: ++ case StyleAppearance::ButtonArrowNext: ++ case StyleAppearance::ButtonArrowPrevious: + { + moz_gtk_get_arrow_size(MOZ_GTK_TOOLBARBUTTON_ARROW, + &aResult->width, &aResult->height); + *aIsOverridable = false; + } + break; +- case NS_THEME_WINDOW_BUTTON_CLOSE: ++ case StyleAppearance::MozWindowButtonClose: + { + const ToolbarButtonGTKMetrics* metrics = + GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_CLOSE); +@@ -1628,7 +1666,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + aResult->height = metrics->minSizeWithBorderMargin.height; + break; + } +- case NS_THEME_WINDOW_BUTTON_MINIMIZE: ++ case StyleAppearance::MozWindowButtonMinimize: + { + const ToolbarButtonGTKMetrics* metrics = + GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE); +@@ -1636,8 +1674,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + aResult->height = metrics->minSizeWithBorderMargin.height; + break; + } +- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: +- case NS_THEME_WINDOW_BUTTON_RESTORE: ++ case StyleAppearance::MozWindowButtonMaximize: ++ case StyleAppearance::MozWindowButtonRestore: + { + const ToolbarButtonGTKMetrics* metrics = + GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE); +@@ -1645,16 +1683,16 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + aResult->height = metrics->minSizeWithBorderMargin.height; + break; + } +- case NS_THEME_CHECKBOX_CONTAINER: +- case NS_THEME_RADIO_CONTAINER: +- case NS_THEME_CHECKBOX_LABEL: +- case NS_THEME_RADIO_LABEL: +- case NS_THEME_BUTTON: +- case NS_THEME_MENULIST: +- case NS_THEME_TOOLBARBUTTON: +- case NS_THEME_TREEHEADERCELL: ++ case StyleAppearance::CheckboxContainer: ++ case StyleAppearance::RadioContainer: ++ case StyleAppearance::CheckboxLabel: ++ case StyleAppearance::RadioLabel: ++ case StyleAppearance::Button: ++ case StyleAppearance::Menulist: ++ case StyleAppearance::Toolbarbutton: ++ case StyleAppearance::Treeheadercell: + { +- if (aWidgetType == NS_THEME_MENULIST) { ++ if (aWidgetType == StyleAppearance::Menulist) { + // Include the arrow size. + moz_gtk_get_arrow_size(MOZ_GTK_DROPDOWN, + &aResult->width, &aResult->height); +@@ -1663,21 +1701,21 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + // descendants; the value returned here will not be helpful, but the + // box model may consider border and padding with child minimum sizes. + +- nsIntMargin border; ++ LayoutDeviceIntMargin border; + GetCachedWidgetBorder(aFrame, aWidgetType, GetTextDirection(aFrame), &border); + aResult->width += border.left + border.right; + aResult->height += border.top + border.bottom; + } + break; + #ifdef MOZ_WIDGET_GTK +- case NS_THEME_NUMBER_INPUT: +- case NS_THEME_TEXTFIELD: ++ case StyleAppearance::NumberInput: ++ case StyleAppearance::Textfield: + { + moz_gtk_get_entry_min_height(&aResult->height); + } + break; + #endif +- case NS_THEME_SEPARATOR: ++ case StyleAppearance::Separator: + { + gint separator_width; + +@@ -1686,26 +1724,26 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + aResult->width = separator_width; + } + break; +- case NS_THEME_INNER_SPIN_BUTTON: +- case NS_THEME_SPINNER: ++ case StyleAppearance::InnerSpinButton: ++ case StyleAppearance::Spinner: + // hard code these sizes + aResult->width = 14; + aResult->height = 26; + break; +- case NS_THEME_TREEHEADERSORTARROW: +- case NS_THEME_SPINNER_UPBUTTON: +- case NS_THEME_SPINNER_DOWNBUTTON: ++ case StyleAppearance::Treeheadersortarrow: ++ case StyleAppearance::SpinnerUpbutton: ++ case StyleAppearance::SpinnerDownbutton: + // hard code these sizes + aResult->width = 14; + aResult->height = 13; + break; +- case NS_THEME_RESIZER: ++ case StyleAppearance::Resizer: + // same as Windows to make our lives easier + aResult->width = aResult->height = 15; + *aIsOverridable = false; + break; +- case NS_THEME_TREETWISTY: +- case NS_THEME_TREETWISTYOPEN: ++ case StyleAppearance::Treetwisty: ++ case StyleAppearance::Treetwistyopen: + { + gint expander_size; + +@@ -1714,6 +1752,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + *aIsOverridable = false; + } + break; ++ default: ++ break; + } + + *aResult = *aResult * GetMonitorScaleFactor(aFrame); +@@ -1722,41 +1762,42 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n + } + + NS_IMETHODIMP +-nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, ++nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, ++ StyleAppearance aWidgetType, + nsAtom* aAttribute, bool* aShouldRepaint, + const nsAttrValue* aOldValue) + { + // Some widget types just never change state. +- if (aWidgetType == NS_THEME_TOOLBOX || +- aWidgetType == NS_THEME_TOOLBAR || +- aWidgetType == NS_THEME_STATUSBAR || +- aWidgetType == NS_THEME_STATUSBARPANEL || +- aWidgetType == NS_THEME_RESIZERPANEL || +- aWidgetType == NS_THEME_PROGRESSCHUNK || +- aWidgetType == NS_THEME_PROGRESSCHUNK_VERTICAL || +- aWidgetType == NS_THEME_PROGRESSBAR || +- aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL || +- aWidgetType == NS_THEME_MENUBAR || +- aWidgetType == NS_THEME_MENUPOPUP || +- aWidgetType == NS_THEME_TOOLTIP || +- aWidgetType == NS_THEME_MENUSEPARATOR || +- aWidgetType == NS_THEME_WINDOW || +- aWidgetType == NS_THEME_DIALOG) { ++ if (aWidgetType == StyleAppearance::Toolbox || ++ aWidgetType == StyleAppearance::Toolbar || ++ aWidgetType == StyleAppearance::Statusbar || ++ aWidgetType == StyleAppearance::Statusbarpanel || ++ aWidgetType == StyleAppearance::Resizerpanel || ++ aWidgetType == StyleAppearance::Progresschunk || ++ aWidgetType == StyleAppearance::ProgresschunkVertical || ++ aWidgetType == StyleAppearance::Progressbar || ++ aWidgetType == StyleAppearance::ProgressbarVertical || ++ aWidgetType == StyleAppearance::Menubar || ++ aWidgetType == StyleAppearance::Menupopup || ++ aWidgetType == StyleAppearance::Tooltip || ++ aWidgetType == StyleAppearance::Menuseparator || ++ aWidgetType == StyleAppearance::Window || ++ aWidgetType == StyleAppearance::Dialog) { + *aShouldRepaint = false; + return NS_OK; + } + +- if ((aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL || +- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL) && ++ if ((aWidgetType == StyleAppearance::ScrollbarthumbVertical || ++ aWidgetType == StyleAppearance::ScrollbarthumbHorizontal) && + aAttribute == nsGkAtoms::active) { + *aShouldRepaint = true; + return NS_OK; + } + +- if ((aWidgetType == NS_THEME_SCROLLBARBUTTON_UP || +- aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN || +- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT || +- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) && ++ if ((aWidgetType == StyleAppearance::ScrollbarbuttonUp || ++ aWidgetType == StyleAppearance::ScrollbarbuttonDown || ++ aWidgetType == StyleAppearance::ScrollbarbuttonLeft || ++ aWidgetType == StyleAppearance::ScrollbarbuttonRight) && + (aAttribute == nsGkAtoms::curpos || + aAttribute == nsGkAtoms::maxpos)) { + // If 'curpos' has changed and we are passed its old value, we can +@@ -1820,120 +1861,135 @@ nsNativeThemeGTK::ThemeChanged() + NS_IMETHODIMP_(bool) + nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext, + nsIFrame* aFrame, +- uint8_t aWidgetType) ++ StyleAppearance aWidgetType) + { + if (IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType)) + return false; + ++ if (IsWidgetScrollbarPart(aWidgetType)) { ++ ComputedStyle* cs = nsLayoutUtils::StyleForScrollbar(aFrame); ++ if (cs->StyleUI()->HasCustomScrollbars() || ++ // We cannot handle thin scrollbar on GTK+ widget directly as well. ++ cs->StyleUIReset()->mScrollbarWidth == StyleScrollbarWidth::Thin) { ++ return false; ++ } ++ } ++ ++ if (aWidgetType == StyleAppearance::MenulistButton && ++ StaticPrefs::layout_css_webkit_appearance_enabled()) { ++ aWidgetType = StyleAppearance::Menulist; ++ } ++ + switch (aWidgetType) { + // Combobox dropdowns don't support native theming in vertical mode. +- case NS_THEME_MENULIST: +- case NS_THEME_MENULIST_TEXT: +- case NS_THEME_MENULIST_TEXTFIELD: ++ case StyleAppearance::Menulist: ++ case StyleAppearance::MenulistText: ++ case StyleAppearance::MenulistTextfield: + if (aFrame && aFrame->GetWritingMode().IsVertical()) { + return false; + } + MOZ_FALLTHROUGH; + +- case NS_THEME_BUTTON: +- case NS_THEME_BUTTON_FOCUS: +- case NS_THEME_RADIO: +- case NS_THEME_CHECKBOX: +- case NS_THEME_TOOLBOX: // N/A +- case NS_THEME_TOOLBAR: +- case NS_THEME_TOOLBARBUTTON: +- case NS_THEME_DUALBUTTON: // so we can override the border with 0 +- case NS_THEME_TOOLBARBUTTON_DROPDOWN: +- case NS_THEME_BUTTON_ARROW_UP: +- case NS_THEME_BUTTON_ARROW_DOWN: +- case NS_THEME_BUTTON_ARROW_NEXT: +- case NS_THEME_BUTTON_ARROW_PREVIOUS: +- case NS_THEME_SEPARATOR: +- case NS_THEME_TOOLBARGRIPPER: +- case NS_THEME_STATUSBAR: +- case NS_THEME_STATUSBARPANEL: +- case NS_THEME_RESIZERPANEL: +- case NS_THEME_RESIZER: +- case NS_THEME_LISTBOX: +- // case NS_THEME_LISTITEM: +- case NS_THEME_TREEVIEW: +- // case NS_THEME_TREEITEM: +- case NS_THEME_TREETWISTY: +- // case NS_THEME_TREELINE: +- // case NS_THEME_TREEHEADER: +- case NS_THEME_TREEHEADERCELL: +- case NS_THEME_TREEHEADERSORTARROW: +- case NS_THEME_TREETWISTYOPEN: +- case NS_THEME_PROGRESSBAR: +- case NS_THEME_PROGRESSCHUNK: +- case NS_THEME_PROGRESSBAR_VERTICAL: +- case NS_THEME_PROGRESSCHUNK_VERTICAL: +- case NS_THEME_TAB: +- // case NS_THEME_TABPANEL: +- case NS_THEME_TABPANELS: +- case NS_THEME_TAB_SCROLL_ARROW_BACK: +- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: +- case NS_THEME_TOOLTIP: +- case NS_THEME_INNER_SPIN_BUTTON: +- case NS_THEME_SPINNER: +- case NS_THEME_SPINNER_UPBUTTON: +- case NS_THEME_SPINNER_DOWNBUTTON: +- case NS_THEME_SPINNER_TEXTFIELD: +- // case NS_THEME_SCROLLBAR: (n/a for gtk) +- // case NS_THEME_SCROLLBAR_SMALL: (n/a for gtk) +- case NS_THEME_SCROLLBARBUTTON_UP: +- case NS_THEME_SCROLLBARBUTTON_DOWN: +- case NS_THEME_SCROLLBARBUTTON_LEFT: +- case NS_THEME_SCROLLBARBUTTON_RIGHT: +- case NS_THEME_SCROLLBAR_HORIZONTAL: +- case NS_THEME_SCROLLBAR_VERTICAL: +- case NS_THEME_SCROLLBARTRACK_HORIZONTAL: +- case NS_THEME_SCROLLBARTRACK_VERTICAL: +- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: +- case NS_THEME_SCROLLBARTHUMB_VERTICAL: +- case NS_THEME_NUMBER_INPUT: +- case NS_THEME_TEXTFIELD: +- case NS_THEME_TEXTFIELD_MULTILINE: +- case NS_THEME_RANGE: +- case NS_THEME_RANGE_THUMB: +- case NS_THEME_SCALE_HORIZONTAL: +- case NS_THEME_SCALETHUMB_HORIZONTAL: +- case NS_THEME_SCALE_VERTICAL: +- case NS_THEME_SCALETHUMB_VERTICAL: +- // case NS_THEME_SCALETHUMBSTART: +- // case NS_THEME_SCALETHUMBEND: +- // case NS_THEME_SCALETHUMBTICK: +- case NS_THEME_CHECKBOX_CONTAINER: +- case NS_THEME_RADIO_CONTAINER: +- case NS_THEME_CHECKBOX_LABEL: +- case NS_THEME_RADIO_LABEL: +- case NS_THEME_MENUBAR: +- case NS_THEME_MENUPOPUP: +- case NS_THEME_MENUITEM: +- case NS_THEME_MENUARROW: +- case NS_THEME_MENUSEPARATOR: +- case NS_THEME_CHECKMENUITEM: +- case NS_THEME_RADIOMENUITEM: +- case NS_THEME_SPLITTER: +- case NS_THEME_WINDOW: +- case NS_THEME_DIALOG: ++ case StyleAppearance::Button: ++ case StyleAppearance::ButtonFocus: ++ case StyleAppearance::Radio: ++ case StyleAppearance::Checkbox: ++ case StyleAppearance::Toolbox: // N/A ++ case StyleAppearance::Toolbar: ++ case StyleAppearance::Toolbarbutton: ++ case StyleAppearance::Dualbutton: // so we can override the border with 0 ++ case StyleAppearance::ToolbarbuttonDropdown: ++ case StyleAppearance::ButtonArrowUp: ++ case StyleAppearance::ButtonArrowDown: ++ case StyleAppearance::ButtonArrowNext: ++ case StyleAppearance::ButtonArrowPrevious: ++ case StyleAppearance::Separator: ++ case StyleAppearance::Toolbargripper: ++ case StyleAppearance::Statusbar: ++ case StyleAppearance::Statusbarpanel: ++ case StyleAppearance::Resizerpanel: ++ case StyleAppearance::Resizer: ++ case StyleAppearance::Listbox: ++ // case StyleAppearance::Listitem: ++ case StyleAppearance::Treeview: ++ // case StyleAppearance::Treeitem: ++ case StyleAppearance::Treetwisty: ++ // case StyleAppearance::Treeline: ++ // case StyleAppearance::Treeheader: ++ case StyleAppearance::Treeheadercell: ++ case StyleAppearance::Treeheadersortarrow: ++ case StyleAppearance::Treetwistyopen: ++ case StyleAppearance::Progressbar: ++ case StyleAppearance::Progresschunk: ++ case StyleAppearance::ProgressbarVertical: ++ case StyleAppearance::ProgresschunkVertical: ++ case StyleAppearance::Tab: ++ // case StyleAppearance::Tabpanel: ++ case StyleAppearance::Tabpanels: ++ case StyleAppearance::TabScrollArrowBack: ++ case StyleAppearance::TabScrollArrowForward: ++ case StyleAppearance::Tooltip: ++ case StyleAppearance::InnerSpinButton: ++ case StyleAppearance::Spinner: ++ case StyleAppearance::SpinnerUpbutton: ++ case StyleAppearance::SpinnerDownbutton: ++ case StyleAppearance::SpinnerTextfield: ++ // case StyleAppearance::Scrollbar: (n/a for gtk) ++ // case StyleAppearance::ScrollbarSmall: (n/a for gtk) ++ case StyleAppearance::ScrollbarbuttonUp: ++ case StyleAppearance::ScrollbarbuttonDown: ++ case StyleAppearance::ScrollbarbuttonLeft: ++ case StyleAppearance::ScrollbarbuttonRight: ++ case StyleAppearance::ScrollbarHorizontal: ++ case StyleAppearance::ScrollbarVertical: ++ case StyleAppearance::ScrollbartrackHorizontal: ++ case StyleAppearance::ScrollbartrackVertical: ++ case StyleAppearance::ScrollbarthumbHorizontal: ++ case StyleAppearance::ScrollbarthumbVertical: ++ case StyleAppearance::NumberInput: ++ case StyleAppearance::Textfield: ++ case StyleAppearance::TextfieldMultiline: ++ case StyleAppearance::Range: ++ case StyleAppearance::RangeThumb: ++ case StyleAppearance::ScaleHorizontal: ++ case StyleAppearance::ScalethumbHorizontal: ++ case StyleAppearance::ScaleVertical: ++ case StyleAppearance::ScalethumbVertical: ++ // case StyleAppearance::Scalethumbstart: ++ // case StyleAppearance::Scalethumbend: ++ // case StyleAppearance::Scalethumbtick: ++ case StyleAppearance::CheckboxContainer: ++ case StyleAppearance::RadioContainer: ++ case StyleAppearance::CheckboxLabel: ++ case StyleAppearance::RadioLabel: ++ case StyleAppearance::Menubar: ++ case StyleAppearance::Menupopup: ++ case StyleAppearance::Menuitem: ++ case StyleAppearance::Menuarrow: ++ case StyleAppearance::Menuseparator: ++ case StyleAppearance::Checkmenuitem: ++ case StyleAppearance::Radiomenuitem: ++ case StyleAppearance::Splitter: ++ case StyleAppearance::Window: ++ case StyleAppearance::Dialog: + #ifdef MOZ_WIDGET_GTK +- case NS_THEME_GTK_INFO_BAR: ++ case StyleAppearance::MozGtkInfoBar: + #endif + return !IsWidgetStyled(aPresContext, aFrame, aWidgetType); + +- case NS_THEME_WINDOW_BUTTON_CLOSE: +- case NS_THEME_WINDOW_BUTTON_MINIMIZE: +- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: +- case NS_THEME_WINDOW_BUTTON_RESTORE: +- case NS_THEME_WINDOW_TITLEBAR: +- case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED: ++ case StyleAppearance::MozWindowButtonClose: ++ case StyleAppearance::MozWindowButtonMinimize: ++ case StyleAppearance::MozWindowButtonMaximize: ++ case StyleAppearance::MozWindowButtonRestore: ++ case StyleAppearance::MozWindowTitlebar: ++ case StyleAppearance::MozWindowTitlebarMaximized: + // GtkHeaderBar is available on GTK 3.10+, which is used for styling + // title bars and title buttons. + return gtk_check_version(3, 10, 0) == nullptr && + !IsWidgetStyled(aPresContext, aFrame, aWidgetType); + +- case NS_THEME_MENULIST_BUTTON: ++ case StyleAppearance::MenulistButton: ++ case StyleAppearance::MozMenulistButton: + if (aFrame && aFrame->GetWritingMode().IsVertical()) { + return false; + } +@@ -1942,37 +1998,50 @@ nsNativeThemeGTK::ThemeSupportsWidget(ns + return (!aFrame || IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) && + !IsWidgetStyled(aPresContext, aFrame, aWidgetType); + +- case NS_THEME_FOCUS_OUTLINE: ++ case StyleAppearance::FocusOutline: + return true; ++ default: ++ break; + } + + return false; + } + + NS_IMETHODIMP_(bool) +-nsNativeThemeGTK::WidgetIsContainer(uint8_t aWidgetType) ++nsNativeThemeGTK::WidgetIsContainer(StyleAppearance aWidgetType) + { ++ if (aWidgetType == StyleAppearance::MenulistButton && ++ StaticPrefs::layout_css_webkit_appearance_enabled()) { ++ aWidgetType = StyleAppearance::Menulist; ++ } ++ + // XXXdwh At some point flesh all of this out. +- if (aWidgetType == NS_THEME_MENULIST_BUTTON || +- aWidgetType == NS_THEME_RADIO || +- aWidgetType == NS_THEME_RANGE_THUMB || +- aWidgetType == NS_THEME_CHECKBOX || +- aWidgetType == NS_THEME_TAB_SCROLL_ARROW_BACK || +- aWidgetType == NS_THEME_TAB_SCROLL_ARROW_FORWARD || +- aWidgetType == NS_THEME_BUTTON_ARROW_UP || +- aWidgetType == NS_THEME_BUTTON_ARROW_DOWN || +- aWidgetType == NS_THEME_BUTTON_ARROW_NEXT || +- aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS) ++ if (aWidgetType == StyleAppearance::MenulistButton || ++ aWidgetType == StyleAppearance::MozMenulistButton || ++ aWidgetType == StyleAppearance::Radio || ++ aWidgetType == StyleAppearance::RangeThumb || ++ aWidgetType == StyleAppearance::Checkbox || ++ aWidgetType == StyleAppearance::TabScrollArrowBack || ++ aWidgetType == StyleAppearance::TabScrollArrowForward || ++ aWidgetType == StyleAppearance::ButtonArrowUp || ++ aWidgetType == StyleAppearance::ButtonArrowDown || ++ aWidgetType == StyleAppearance::ButtonArrowNext || ++ aWidgetType == StyleAppearance::ButtonArrowPrevious) + return false; + return true; + } + + bool +-nsNativeThemeGTK::ThemeDrawsFocusForWidget(uint8_t aWidgetType) ++nsNativeThemeGTK::ThemeDrawsFocusForWidget(StyleAppearance aWidgetType) + { +- if (aWidgetType == NS_THEME_MENULIST || +- aWidgetType == NS_THEME_BUTTON || +- aWidgetType == NS_THEME_TREEHEADERCELL) ++ if (aWidgetType == StyleAppearance::MenulistButton && ++ StaticPrefs::layout_css_webkit_appearance_enabled()) { ++ aWidgetType = StyleAppearance::Menulist; ++ } ++ ++ if (aWidgetType == StyleAppearance::Menulist || ++ aWidgetType == StyleAppearance::Button || ++ aWidgetType == StyleAppearance::Treeheadercell) + return true; + + return false; +@@ -1985,16 +2054,17 @@ nsNativeThemeGTK::ThemeNeedsComboboxDrop + } + + nsITheme::Transparency +-nsNativeThemeGTK::GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) ++nsNativeThemeGTK::GetWidgetTransparency(nsIFrame* aFrame, ++ StyleAppearance aWidgetType) + { + switch (aWidgetType) { + // These widgets always draw a default background. +- case NS_THEME_MENUPOPUP: +- case NS_THEME_WINDOW: +- case NS_THEME_DIALOG: ++ case StyleAppearance::Menupopup: ++ case StyleAppearance::Window: ++ case StyleAppearance::Dialog: + return eOpaque; +- case NS_THEME_SCROLLBAR_VERTICAL: +- case NS_THEME_SCROLLBAR_HORIZONTAL: ++ case StyleAppearance::ScrollbarVertical: ++ case StyleAppearance::ScrollbarHorizontal: + #ifdef MOZ_WIDGET_GTK + // Make scrollbar tracks opaque on the window's scroll frame to prevent + // leaf layers from overlapping. See bug 1179780. +@@ -2006,9 +2076,10 @@ nsNativeThemeGTK::GetWidgetTransparency( + return eOpaque; + // Tooltips use gtk_paint_flat_box() on Gtk2 + // but are shaped on Gtk3 +- case NS_THEME_TOOLTIP: ++ case StyleAppearance::Tooltip: + return eTransparent; ++ default: ++ return eUnknownTransparency; + } + +- return eUnknownTransparency; + } +diff -up thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h.wayland thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h +--- thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h.wayland 2018-10-30 12:45:37.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h 2018-11-20 12:04:43.739787343 +0100 +@@ -11,7 +11,7 @@ + #include "nsAtom.h" + #include "nsIObserver.h" + #include "nsNativeTheme.h" +-#include "nsThemeConstants.h" ++#include "nsStyleConsts.h" + + #include + #include "gtkdrawing.h" +@@ -26,7 +26,7 @@ public: + + // The nsITheme interface. + NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, +- nsIFrame* aFrame, uint8_t aWidgetType, ++ nsIFrame* aFrame, WidgetType aWidgetType, + const nsRect& aRect, + const nsRect& aDirtyRect) override; + +@@ -35,29 +35,29 @@ public: + const mozilla::layers::StackingContextHelper& aSc, + mozilla::layers::WebRenderLayerManager* aManager, + nsIFrame* aFrame, +- uint8_t aWidgetType, ++ WidgetType aWidgetType, + const nsRect& aRect) override; + +- NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, +- uint8_t aWidgetType, +- nsIntMargin* aResult) override; +- +- virtual bool GetWidgetPadding(nsDeviceContext* aContext, +- nsIFrame* aFrame, +- uint8_t aWidgetType, +- nsIntMargin* aResult) override; ++ MOZ_MUST_USE LayoutDeviceIntMargin GetWidgetBorder(nsDeviceContext* aContext, ++ nsIFrame* aFrame, ++ WidgetType aWidgetType) override; ++ ++ bool GetWidgetPadding(nsDeviceContext* aContext, ++ nsIFrame* aFrame, ++ WidgetType aWidgetType, ++ LayoutDeviceIntMargin* aResult) override; + + virtual bool GetWidgetOverflow(nsDeviceContext* aContext, + nsIFrame* aFrame, +- uint8_t aWidgetType, ++ WidgetType aWidgetType, + nsRect* aOverflowRect) override; + + NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, +- nsIFrame* aFrame, uint8_t aWidgetType, ++ nsIFrame* aFrame, WidgetType aWidgetType, + mozilla::LayoutDeviceIntSize* aResult, + bool* aIsOverridable) override; + +- NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, ++ NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, WidgetType aWidgetType, + nsAtom* aAttribute, + bool* aShouldRepaint, + const nsAttrValue* aOldValue) override; +@@ -66,16 +66,16 @@ public: + + NS_IMETHOD_(bool) ThemeSupportsWidget(nsPresContext* aPresContext, + nsIFrame* aFrame, +- uint8_t aWidgetType) override; ++ WidgetType aWidgetType) override; + +- NS_IMETHOD_(bool) WidgetIsContainer(uint8_t aWidgetType) override; ++ NS_IMETHOD_(bool) WidgetIsContainer(WidgetType aWidgetType) override; + +- NS_IMETHOD_(bool) ThemeDrawsFocusForWidget(uint8_t aWidgetType) override; ++ NS_IMETHOD_(bool) ThemeDrawsFocusForWidget(WidgetType aWidgetType) override; + + virtual bool ThemeNeedsComboboxDropmarker() override; + + virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, +- uint8_t aWidgetType) override; ++ WidgetType aWidgetType) override; + nsNativeThemeGTK(); + + protected: +@@ -84,26 +84,27 @@ protected: + private: + GtkTextDirection GetTextDirection(nsIFrame* aFrame); + gint GetTabMarginPixels(nsIFrame* aFrame); +- bool GetGtkWidgetAndState(uint8_t aWidgetType, nsIFrame* aFrame, ++ bool GetGtkWidgetAndState(WidgetType aWidgetType, nsIFrame* aFrame, + WidgetNodeType& aGtkWidgetType, + GtkWidgetState* aState, gint* aWidgetFlags); +- bool GetExtraSizeForWidget(nsIFrame* aFrame, uint8_t aWidgetType, ++ bool GetExtraSizeForWidget(nsIFrame* aFrame, WidgetType aWidgetType, + nsIntMargin* aExtra); + + void RefreshWidgetWindow(nsIFrame* aFrame); +- WidgetNodeType NativeThemeToGtkTheme(uint8_t aWidgetType, nsIFrame* aFrame); ++ WidgetNodeType NativeThemeToGtkTheme(WidgetType aWidgetType, nsIFrame* aFrame); + +- uint8_t mDisabledWidgetTypes[(ThemeWidgetType_COUNT + 7) / 8]; +- uint8_t mSafeWidgetStates[ThemeWidgetType_COUNT * 4]; // 32 bits per widget ++ uint8_t mDisabledWidgetTypes[(static_cast(mozilla::StyleAppearance::Count) + 7) / 8]; ++ uint8_t mSafeWidgetStates[static_cast(mozilla::StyleAppearance::Count) * 4]; // 32 bits per widget + static const char* sDisabledEngines[]; + + // Because moz_gtk_get_widget_border can be slow, we cache its results + // by widget type. Each bit in mBorderCacheValid says whether the + // corresponding entry in mBorderCache is valid. +- void GetCachedWidgetBorder(nsIFrame* aFrame, uint8_t aWidgetType, +- GtkTextDirection aDirection, nsIntMargin* aResult); ++ void GetCachedWidgetBorder(nsIFrame* aFrame, WidgetType aWidgetType, ++ GtkTextDirection aDirection, ++ LayoutDeviceIntMargin* aResult); + uint8_t mBorderCacheValid[(MOZ_GTK_WIDGET_NODE_COUNT + 7) / 8]; +- nsIntMargin mBorderCache[MOZ_GTK_WIDGET_NODE_COUNT]; ++ LayoutDeviceIntMargin mBorderCache[MOZ_GTK_WIDGET_NODE_COUNT]; + }; + + #endif +diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp +--- thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp 2018-11-20 12:04:43.739787343 +0100 +@@ -24,7 +24,20 @@ + #include "nsIBaseWindow.h" + #include "nsIDocShellTreeItem.h" + #include "nsIDocShell.h" ++#include "nsIGIOService.h" + #include "WidgetUtils.h" ++#include "nsIObserverService.h" ++ ++// for gdk_x11_window_get_xid ++#include ++#include ++#include ++#include ++#include ++ ++// 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,522 @@ 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); ++ ++typedef void (*GtkWindowHandleExported) (GtkWindow *window, ++ const char *handle, ++ gpointer user_data); ++#ifdef MOZ_WAYLAND ++typedef struct { ++ GtkWindow *window; ++ WindowHandleExported callback; ++ gpointer user_data; ++} WaylandWindowHandleExportedData; ++ ++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; ++ ++ handle_str = g_strdup_printf ("wayland:%s", wayland_handle_str); ++ data->callback (data->window, handle_str, data->user_data); ++ g_free (handle_str); ++} ++#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); ++ ++ handle_str = g_strdup_printf("x11:%x", xid); ++ callback(window, handle_str, user_data); ++ g_free(handle_str); ++ 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"); ++ ++ 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. ++ */ ++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; ++}; ++ ++NS_IMPL_ISUPPORTS(nsFlatpakPrintPortal, nsIObserver) ++ ++nsFlatpakPrintPortal::nsFlatpakPrintPortal(nsPrintSettingsGTK* aPrintSettings): ++ mPrintAndPageSettings(aPrintSettings), ++ mProxy(nullptr), ++ mLoop(nullptr), ++ mResponseSignalId(0), ++ mParentWindow(nullptr) ++{ ++} ++ ++/** ++ * 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; ++ giovfs->ShouldUseFlatpakPortal(&shouldUsePortal); ++ 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 +1075,8 @@ NS_IMETHODIMP + nsPrintDialogServiceGTK::ShowPageSetup(nsPIDOMWindowOuter *aParent, + nsIPrintSettings *aNSSettings) + { +- NS_PRECONDITION(aParent, "aParent must not be null"); +- NS_PRECONDITION(aNSSettings, "aSettings must not be null"); ++ MOZ_ASSERT(aParent, "aParent must not be null"); ++ MOZ_ASSERT(aNSSettings, "aSettings must not be null"); + NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); + + nsCOMPtr widget = WidgetUtils::DOMWindowToWidget(aParent); +diff -up thunderbird-60.3.0/widget/gtk/nsSound.cpp.wayland thunderbird-60.3.0/widget/gtk/nsSound.cpp +--- thunderbird-60.3.0/widget/gtk/nsSound.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsSound.cpp 2018-11-20 12:04:43.739787343 +0100 +@@ -417,43 +417,3 @@ NS_IMETHODIMP nsSound::PlayEventSound(ui + } + return NS_OK; + } +- +-NS_IMETHODIMP nsSound::PlaySystemSound(const nsAString &aSoundAlias) +-{ +- if (NS_IsMozAliasSound(aSoundAlias)) { +- NS_WARNING("nsISound::playSystemSound is called with \"_moz_\" events, they are obsolete, use nsISound::playEventSound instead"); +- uint32_t eventId; +- if (aSoundAlias.Equals(NS_SYSSOUND_ALERT_DIALOG)) +- eventId = EVENT_ALERT_DIALOG_OPEN; +- else if (aSoundAlias.Equals(NS_SYSSOUND_CONFIRM_DIALOG)) +- eventId = EVENT_CONFIRM_DIALOG_OPEN; +- else if (aSoundAlias.Equals(NS_SYSSOUND_MAIL_BEEP)) +- eventId = EVENT_NEW_MAIL_RECEIVED; +- else if (aSoundAlias.Equals(NS_SYSSOUND_MENU_EXECUTE)) +- eventId = EVENT_MENU_EXECUTE; +- else if (aSoundAlias.Equals(NS_SYSSOUND_MENU_POPUP)) +- eventId = EVENT_MENU_POPUP; +- else +- return NS_OK; +- return PlayEventSound(eventId); +- } +- +- nsresult rv; +- nsCOMPtr fileURI; +- +- // create a nsIFile and then a nsIFileURL from that +- nsCOMPtr soundFile; +- rv = NS_NewLocalFile(aSoundAlias, true, +- getter_AddRefs(soundFile)); +- NS_ENSURE_SUCCESS(rv,rv); +- +- rv = NS_NewFileURI(getter_AddRefs(fileURI), soundFile); +- NS_ENSURE_SUCCESS(rv,rv); +- +- nsCOMPtr fileURL = do_QueryInterface(fileURI,&rv); +- NS_ENSURE_SUCCESS(rv,rv); +- +- rv = Play(fileURL); +- +- return rv; +-} +diff -up thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp.wayland thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp +--- thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp 2018-11-20 12:04:43.739787343 +0100 +@@ -27,6 +27,7 @@ + #ifdef MOZ_WIDGET_GTK + #include "nsApplicationChooser.h" + #endif ++#include "TaskbarProgress.h" + #include "nsColorPicker.h" + #include "nsFilePicker.h" + #include "nsSound.h" +@@ -60,7 +61,6 @@ + using namespace mozilla; + using namespace mozilla::widget; + +-NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) + NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) + NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard) + NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) +@@ -72,6 +72,7 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR + NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISound, nsSound::GetInstance) + NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton) + NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToPixbuf) ++NS_GENERIC_FACTORY_CONSTRUCTOR(TaskbarProgress) + + + // from nsWindow.cpp +@@ -196,14 +197,13 @@ nsClipboardConstructor(nsISupports *aOut + return inst->QueryInterface(aIID, aResult); + } + +-NS_DEFINE_NAMED_CID(NS_WINDOW_CID); +-NS_DEFINE_NAMED_CID(NS_CHILD_CID); + NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); + NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID); + NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); + #ifdef MOZ_WIDGET_GTK + NS_DEFINE_NAMED_CID(NS_APPLICATIONCHOOSER_CID); + #endif ++NS_DEFINE_NAMED_CID(NS_GTK_TASKBARPROGRESS_CID); + NS_DEFINE_NAMED_CID(NS_SOUND_CID); + NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID); + #ifdef MOZ_X11 +@@ -230,14 +230,13 @@ NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); + + + static const mozilla::Module::CIDEntry kWidgetCIDs[] = { +- { &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor }, +- { &kNS_CHILD_CID, false, nullptr, nsWindowConstructor }, + { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor, Module::ALLOW_IN_GPU_PROCESS }, + { &kNS_COLORPICKER_CID, false, nullptr, nsColorPickerConstructor, Module::MAIN_PROCESS_ONLY }, + { &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerConstructor, Module::MAIN_PROCESS_ONLY }, + #ifdef MOZ_WIDGET_GTK + { &kNS_APPLICATIONCHOOSER_CID, false, nullptr, nsApplicationChooserConstructor, Module::MAIN_PROCESS_ONLY }, + #endif ++ { &kNS_GTK_TASKBARPROGRESS_CID, false, nullptr, TaskbarProgressConstructor}, + { &kNS_SOUND_CID, false, nullptr, nsISoundConstructor, Module::MAIN_PROCESS_ONLY }, + { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor }, + #ifdef MOZ_X11 +@@ -266,14 +265,13 @@ static const mozilla::Module::CIDEntry k + }; + + static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { +- { "@mozilla.org/widget/window/gtk;1", &kNS_WINDOW_CID }, +- { "@mozilla.org/widgets/child_window/gtk;1", &kNS_CHILD_CID }, + { "@mozilla.org/widget/appshell/gtk;1", &kNS_APPSHELL_CID, Module::ALLOW_IN_GPU_PROCESS }, + { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::MAIN_PROCESS_ONLY }, + { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::MAIN_PROCESS_ONLY }, + #ifdef MOZ_WIDGET_GTK + { "@mozilla.org/applicationchooser;1", &kNS_APPLICATIONCHOOSER_CID, Module::MAIN_PROCESS_ONLY }, + #endif ++ { "@mozilla.org/widget/taskbarprogress/gtk;1", &kNS_GTK_TASKBARPROGRESS_CID }, + { "@mozilla.org/sound;1", &kNS_SOUND_CID, Module::MAIN_PROCESS_ONLY }, + { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID }, + #ifdef MOZ_X11 +diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/widget/gtk/nsWindow.cpp +--- thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsWindow.cpp 2018-11-20 12:04:43.741787337 +0100 +@@ -18,6 +18,7 @@ + #include "mozilla/TouchEvents.h" + #include "mozilla/UniquePtrExtensions.h" + #include "mozilla/WidgetUtils.h" ++#include "mozilla/dom/WheelEventBinding.h" + #include + + #include "GeckoProfiler.h" +@@ -25,7 +26,7 @@ + #include "prlink.h" + #include "nsGTKToolkit.h" + #include "nsIRollupListener.h" +-#include "nsIDOMNode.h" ++#include "nsINode.h" + + #include "nsWidgetsCID.h" + #include "nsDragService.h" +@@ -56,6 +57,7 @@ + + #if defined(MOZ_WAYLAND) + #include ++#include "nsView.h" + #endif + + #include "nsGkAtoms.h" +@@ -116,6 +118,7 @@ using namespace mozilla::widget; + #include "mozilla/layers/CompositorThread.h" + + #ifdef MOZ_X11 ++#include "GLContextGLX.h" // for GLContextGLX::FindVisual() + #include "GtkCompositorWidget.h" + #include "gfxXlibSurface.h" + #include "WindowSurfaceX11Image.h" +@@ -129,8 +132,6 @@ using namespace mozilla::widget; + #include "nsShmImage.h" + #include "gtkdrawing.h" + +-#include "nsIDOMWheelEvent.h" +- + #include "NativeKeyBindings.h" + + #include +@@ -140,6 +141,7 @@ using namespace mozilla::gfx; + using namespace mozilla::widget; + using namespace mozilla::layers; + using mozilla::gl::GLContext; ++using mozilla::gl::GLContextGLX; + + // 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 | + #endif + GDK_SCROLL_MASK | + GDK_POINTER_MOTION_MASK | +- GDK_PROPERTY_CHANGE_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; + } + + nsWindow::~nsWindow() +@@ -630,7 +635,7 @@ EnsureInvisibleContainer() + 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(); + + g_signal_handlers_disconnect_by_func(gtk_settings_get_default(), +- FuncToGpointer(theme_changed_cb), ++ FuncToGpointer(settings_changed_cb), + this); + + nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); +@@ -838,11 +843,48 @@ nsWindow::GetDesktopToDeviceScale() + return DesktopToLayoutDeviceScale(1.0); + } + ++DesktopToLayoutDeviceScale ++nsWindow::GetDesktopToDeviceScaleByScreen() ++{ ++#ifdef MOZ_WAYLAND ++ GdkDisplay* gdkDisplay = gdk_display_get_default(); ++ // In Wayland there's no way to get absolute position of the window and use it to ++ // determine the screen factor of the monitor on which the window is placed. ++ // The window is notified of the current scale factor but not at this point, ++ // so the GdkScaleFactor can return wrong value which can lead to wrong popup ++ // placement. ++ // We need to use parent's window scale factor for the new one. ++ if (GDK_IS_WAYLAND_DISPLAY(gdkDisplay)) { ++ nsView* view = nsView::GetViewFor(this); ++ if (view) { ++ nsView* parentView = view->GetParent(); ++ if (parentView) { ++ nsIWidget* parentWidget = parentView->GetNearestWidget(nullptr); ++ if (parentWidget) { ++ return DesktopToLayoutDeviceScale(parentWidget->RoundsWidgetCoordinatesTo()); ++ } else { ++ NS_WARNING("Widget has no parent"); ++ } ++ } ++ } else { ++ NS_WARNING("Cannot find widget view"); ++ } ++ } ++#endif ++ return nsBaseWidget::GetDesktopToDeviceScale(); ++} ++ + 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; + } + +@@ -886,7 +928,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, ""); + +@@ -1517,7 +1559,7 @@ nsWindow::GetClientBounds() + 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) { +@@ -1738,6 +1780,15 @@ nsWindow::GetNativeData(uint32_t aDataTy + case NS_NATIVE_COMPOSITOR_DISPLAY: + return gfxPlatformGtk::GetPlatform()->GetCompositorDisplay(); + #endif // MOZ_X11 ++ case NS_NATIVE_EGL_WINDOW: { ++ if (mIsX11Display) ++ return mGdkWindow ? (void*)GDK_WINDOW_XID(mGdkWindow) : nullptr; ++#ifdef MOZ_WAYLAND ++ if (mContainer) ++ return moz_container_get_wl_egl_window(mContainer); ++#endif ++ return nullptr; ++ } + default: + NS_WARNING("nsWindow::GetNativeData called with bad value"); + return nullptr; +@@ -2057,6 +2108,12 @@ nsWindow::OnExposeEvent(cairo_t *cr) + if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel) + return FALSE; + ++#ifdef MOZ_WAYLAND ++ // Window does not have visible wl_surface yet. ++ if (!mIsX11Display && !GetWaylandSurface()) ++ return FALSE; ++#endif ++ + nsIWidgetListener *listener = GetListener(); + if (!listener) + return FALSE; +@@ -2112,10 +2169,7 @@ nsWindow::OnExposeEvent(cairo_t *cr) + + bool shaped = false; + if (eTransparencyTransparent == GetTransparencyMode()) { +- GdkScreen *screen = gdk_window_get_screen(mGdkWindow); +- if (gdk_screen_is_composited(screen) && +- gdk_window_get_visual(mGdkWindow) == +- gdk_screen_get_rgba_visual(screen)) { ++ if (mHasAlphaVisual) { + // Remove possible shape mask from when window manger was not + // previously compositing. + static_cast(GetTopLevelWidget())-> +@@ -2216,12 +2270,9 @@ nsWindow::OnExposeEvent(cairo_t *cr) + bool painted = false; + { + if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { +- GdkScreen *screen = gdk_window_get_screen(mGdkWindow); + if (GetTransparencyMode() == eTransparencyTransparent && + layerBuffering == BufferMode::BUFFER_NONE && +- gdk_screen_is_composited(screen) && +- gdk_window_get_visual(mGdkWindow) == +- gdk_screen_get_rgba_visual(screen)) { ++ mHasAlphaVisual) { + // If our draw target is unbuffered and we use an alpha channel, + // clear the image beforehand to ensure we don't get artifacts from a + // reused SHM image. See bug 1258086. +@@ -2354,7 +2405,7 @@ nsWindow::OnConfigureEvent(GtkWidget *aW + // + // These windows should not be moved by the window manager, and so any + // change in position is a result of our direction. mBounds has +- // already been set in Move() or Resize(), and that is more ++ // already been set in std::move() or Resize(), and that is more + // up-to-date than the position in the ConfigureNotify event if the + // event is from an earlier window move. + // +@@ -2888,7 +2939,7 @@ nsWindow::OnContainerFocusOutEvent(GdkEv + bool shouldRollup = !dragSession; + if (!shouldRollup) { + // we also roll up when a drag is from a different application +- nsCOMPtr sourceNode; ++ nsCOMPtr sourceNode; + dragSession->GetSourceNode(getter_AddRefs(sourceNode)); + shouldRollup = (sourceNode == nullptr); + } +@@ -2915,8 +2966,8 @@ bool + nsWindow::DispatchCommandEvent(nsAtom* aCommand) + { + nsEventStatus status; +- WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, aCommand, this); +- DispatchEvent(&event, status); ++ WidgetCommandEvent appCommandEvent(true, aCommand, this); ++ DispatchEvent(&appCommandEvent, status); + return TRUE; + } + +@@ -2938,30 +2989,44 @@ IsCtrlAltTab(GdkEventKey *aEvent) + } + + bool +-nsWindow::DispatchKeyDownEvent(GdkEventKey *aEvent, bool *aCancelled) ++nsWindow::DispatchKeyDownOrKeyUpEvent(GdkEventKey* aEvent, ++ bool aIsProcessedByIME, ++ bool* aIsCancelled) + { +- NS_PRECONDITION(aCancelled, "aCancelled must not be null"); ++ MOZ_ASSERT(aIsCancelled, "aIsCancelled must not be nullptr"); + +- *aCancelled = false; ++ *aIsCancelled = false; + +- if (IsCtrlAltTab(aEvent)) { ++ if (aEvent->type == GDK_KEY_PRESS && IsCtrlAltTab(aEvent)) { + return false; + } + ++ EventMessage message = ++ aEvent->type == GDK_KEY_PRESS ? eKeyDown : eKeyUp; ++ WidgetKeyboardEvent keyEvent(true, message, this); ++ KeymapWrapper::InitKeyEvent(keyEvent, aEvent, aIsProcessedByIME); ++ return DispatchKeyDownOrKeyUpEvent(keyEvent, aIsCancelled); ++} ++bool ++nsWindow::DispatchKeyDownOrKeyUpEvent(WidgetKeyboardEvent& aKeyboardEvent, ++ bool* aIsCancelled) ++{ ++ MOZ_ASSERT(aIsCancelled, "aIsCancelled must not be nullptr"); ++ ++ *aIsCancelled = false; ++ + RefPtr dispatcher = GetTextEventDispatcher(); + nsresult rv = dispatcher->BeginNativeInputTransaction(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return FALSE; + } + +- WidgetKeyboardEvent keydownEvent(true, eKeyDown, this); +- KeymapWrapper::InitKeyEvent(keydownEvent, aEvent); + nsEventStatus status = nsEventStatus_eIgnore; + bool dispatched = +- dispatcher->DispatchKeyboardEvent(eKeyDown, keydownEvent, +- status, aEvent); +- *aCancelled = (status == nsEventStatus_eConsumeNoDefault); +- return dispatched ? TRUE : FALSE; ++ dispatcher->DispatchKeyboardEvent(aKeyboardEvent.mMessage, ++ aKeyboardEvent, status, nullptr); ++ *aIsCancelled = (status == nsEventStatus_eConsumeNoDefault); ++ return dispatched; + } + + WidgetEventTime +@@ -3046,7 +3111,7 @@ nsWindow::OnKeyPressEvent(GdkEventKey *a + // KEYDOWN -> KEYPRESS -> KEYUP -> KEYDOWN -> KEYPRESS -> KEYUP... + + bool isKeyDownCancelled = false; +- if (DispatchKeyDownEvent(aEvent, &isKeyDownCancelled) && ++ if (DispatchKeyDownOrKeyUpEvent(aEvent, false, &isKeyDownCancelled) && + (MOZ_UNLIKELY(mIsDestroyed) || isKeyDownCancelled)) { + return TRUE; + } +@@ -3095,7 +3160,7 @@ nsWindow::OnKeyPressEvent(GdkEventKey *a + } + + WidgetKeyboardEvent keypressEvent(true, eKeyPress, this); +- KeymapWrapper::InitKeyEvent(keypressEvent, aEvent); ++ KeymapWrapper::InitKeyEvent(keypressEvent, aEvent, false); + + // before we dispatch a key, check if it's the context menu key. + // If so, send a context menu key event instead. +@@ -3179,7 +3244,7 @@ nsWindow::MaybeDispatchContextMenuEvent( + } + + gboolean +-nsWindow::OnKeyReleaseEvent(GdkEventKey *aEvent) ++nsWindow::OnKeyReleaseEvent(GdkEventKey* aEvent) + { + LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this)); + +@@ -3187,17 +3252,11 @@ nsWindow::OnKeyReleaseEvent(GdkEventKey + return TRUE; + } + +- RefPtr dispatcher = GetTextEventDispatcher(); +- nsresult rv = dispatcher->BeginNativeInputTransaction(); +- if (NS_WARN_IF(NS_FAILED(rv))) { +- return false; ++ bool isCancelled = false; ++ if (NS_WARN_IF(!DispatchKeyDownOrKeyUpEvent(aEvent, false, &isCancelled))) { ++ return FALSE; + } + +- WidgetKeyboardEvent keyupEvent(true, eKeyUp, this); +- KeymapWrapper::InitKeyEvent(keyupEvent, aEvent); +- nsEventStatus status = nsEventStatus_eIgnore; +- dispatcher->DispatchKeyboardEvent(eKeyUp, keyupEvent, status, aEvent); +- + return TRUE; + } + +@@ -3214,7 +3273,7 @@ nsWindow::OnScrollEvent(GdkEventScroll * + return; + #endif + WidgetWheelEvent wheelEvent(true, eWheel, this); +- wheelEvent.mDeltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE; ++ wheelEvent.mDeltaMode = dom::WheelEvent_Binding::DOM_DELTA_LINE; + switch (aEvent->direction) { + #if GTK_CHECK_VERSION(3,4,0) + case GDK_SCROLL_SMOOTH: +@@ -3318,6 +3377,33 @@ nsWindow::OnWindowStateEvent(GtkWidget * + } + // 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 +3490,7 @@ nsWindow::OnDPIChanged() + // Update menu's font size etc + presShell->ThemeChanged(); + } ++ mWidgetListener->UIResolutionChanged(); + } + } + +@@ -3611,6 +3698,8 @@ nsWindow::Create(nsIWidget* aParent, + nsWindow *parentnsWindow = nullptr; + GtkWidget *eventWidget = nullptr; + bool drawToContainer = false; ++ bool needsAlphaVisual = (mWindowType == eWindowType_popup && ++ aInitData->mSupportTranslucency); + + if (aParent) { + parentnsWindow = static_cast(aParent); +@@ -3661,23 +3750,47 @@ nsWindow::Create(nsIWidget* aParent, + } + mShell = gtk_window_new(type); + +- bool useAlphaVisual = (mWindowType == eWindowType_popup && +- aInitData->mSupportTranslucency); +- +- // mozilla.widget.use-argb-visuals is a hidden pref defaulting to false +- // to allow experimentation +- if (Preferences::GetBool("mozilla.widget.use-argb-visuals", false)) +- useAlphaVisual = true; +- +- // We need to select an ARGB visual here instead of in +- // SetTransparencyMode() because it has to be done before the +- // widget is realized. An ARGB visual is only useful if we +- // are on a compositing window manager. +- if (useAlphaVisual) { +- GdkScreen *screen = gtk_widget_get_screen(mShell); +- if (gdk_screen_is_composited(screen)) { +- GdkVisual *visual = gdk_screen_get_rgba_visual(screen); +- gtk_widget_set_visual(mShell, visual); ++#ifdef MOZ_X11 ++ // Ensure gfxPlatform is initialized, since that is what initializes ++ // gfxVars, used below. ++ Unused << gfxPlatform::GetPlatform(); ++ ++ bool useWebRender = gfx::gfxVars::UseWebRender() && ++ AllowWebRenderForThisWindow(); ++ ++ // If using WebRender on X11, we need to select a visual with a depth buffer, ++ // as well as an alpha channel if transparency is requested. This must be done ++ // before the widget is realized. ++ if (mIsX11Display && useWebRender) { ++ auto display = ++ GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(mShell)); ++ auto screen = gtk_widget_get_screen(mShell); ++ int screenNumber = GDK_SCREEN_XNUMBER(screen); ++ int visualId = 0; ++ if (GLContextGLX::FindVisual(display, screenNumber, ++ useWebRender, needsAlphaVisual, ++ &visualId)) { ++ // If we're using CSD, rendering will go through mContainer, but ++ // it will inherit this visual as it is a child of mShell. ++ gtk_widget_set_visual(mShell, ++ gdk_x11_screen_lookup_visual(screen, ++ visualId)); ++ mHasAlphaVisual = needsAlphaVisual; ++ } else { ++ NS_WARNING("We're missing X11 Visual for WebRender!"); ++ } ++ } else ++#endif // MOZ_X11 ++ { ++ if (needsAlphaVisual) { ++ GdkScreen *screen = gtk_widget_get_screen(mShell); ++ if (gdk_screen_is_composited(screen)) { ++ GdkVisual *visual = gdk_screen_get_rgba_visual(screen); ++ if (visual) { ++ gtk_widget_set_visual(mShell, visual); ++ mHasAlphaVisual = true; ++ } ++ } + } + } + +@@ -3784,7 +3897,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 +3972,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 +4052,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) { +@@ -4070,8 +4176,10 @@ nsWindow::Create(nsIWidget* aParent, + GdkVisual* gdkVisual = gdk_window_get_visual(mGdkWindow); + mXVisual = gdk_x11_visual_get_xvisual(gdkVisual); + mXDepth = gdk_visual_get_depth(gdkVisual); ++ bool shaped = needsAlphaVisual && !mHasAlphaVisual; + +- mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth); ++ mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth, ++ shaped); + } + #ifdef MOZ_WAYLAND + else if (!mIsX11Display) { +@@ -4083,60 +4191,70 @@ nsWindow::Create(nsIWidget* aParent, + } + + 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; ++#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); ++ } ++#endif /* MOZ_X11 */ ++} + +- const char *role = nullptr; ++void ++nsWindow::SetWindowClass(const nsAString &xulWinType) ++{ ++ if (!mShell) ++ 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; + +- 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); +- } +-#endif /* MOZ_X11 */ ++ mGtkWindowTypeName = res_name; ++ mGtkWindowRoleName = role; ++ free(res_name); + +- free(res_name); ++ RefreshWindowClass(); + } + + void +@@ -4162,6 +4280,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 +4327,8 @@ nsWindow::NativeMoveResize() + NativeShow(false); + } + NativeMove(); ++ ++ return; + } + + GdkRectangle size = DevicePixelsToGdkSizeRoundUp(mBounds.Size()); +@@ -4219,6 +4341,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 +4395,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 +5080,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 +6087,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 +6168,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 +6199,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 +6249,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 +6289,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 +6718,6 @@ nsWindow::GetLayerManager(PLayerTransact + return mLayerManager; + } + +- if (!mLayerManager && !IsComposited() && +- eTransparencyTransparent == GetTransparencyMode()) +- { +- mLayerManager = CreateBasicLayerManager(); +- } +- + return nsBaseWidget::GetLayerManager(aShadowManager, aBackendHint, aPersistence); + } + +@@ -6601,6 +6759,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; ++ } ++ + // _NET_FRAME_EXTENTS is not set on client decorated windows, + // so we need to read offset between mContainer and toplevel mShell + // window. +@@ -6692,6 +6857,15 @@ nsWindow::SetDrawsInTitlebar(bool aState + 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. +@@ -6998,6 +7172,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 +7190,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 { + // Release or beta builds are not supposed to be broken + // so disable titlebar rendering on untested/unknown systems. +@@ -7066,26 +7244,19 @@ nsWindow::RoundsWidgetCoordinatesTo() + + 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) { ++ XFlush(mXDisplay); ++ } ++ + *aInitData = mozilla::widget::GtkCompositorWidgetInitData( + (mXWindow != X11None) ? mXWindow : (uintptr_t)nullptr, + mXDisplay ? nsCString(XDisplayString(mXDisplay)) : nsCString(), ++ mIsTransparent && !mHasAlphaVisual, + GetClientSize()); + } + +-bool +-nsWindow::IsComposited() const +-{ +- if (!mGdkWindow) { +- NS_WARNING("nsWindow::HasARGBVisual called before realization!"); +- return false; +- } +- +- GdkScreen* gdkScreen = gdk_screen_get_default(); +- return gdk_screen_is_composited(gdkScreen) && +- (gdk_window_get_visual(mGdkWindow) +- == gdk_screen_get_rgba_visual(gdkScreen)); +-} +- + #ifdef MOZ_WAYLAND + wl_display* + nsWindow::GetWaylandDisplay() +@@ -7110,3 +7281,120 @@ nsWindow::GetWaylandSurface() + return nullptr; + } + #endif ++ ++#ifdef MOZ_X11 ++/* XApp progress support currently works by setting a property ++ * on a window with this Atom name. A supporting window manager ++ * will notice this and pass it along to whatever handling has ++ * been implemented on that end (e.g. passing it on to a taskbar ++ * widget.) There is no issue if WM support is lacking, this is ++ * simply ignored in that case. ++ * ++ * See https://github.com/linuxmint/xapps/blob/master/libxapp/xapp-gtk-window.c ++ * for further details. ++ */ ++ ++#define PROGRESS_HINT "_NET_WM_XAPP_PROGRESS" ++ ++static void ++set_window_hint_cardinal (Window xid, ++ const gchar *atom_name, ++ gulong cardinal) ++{ ++ GdkDisplay *display; ++ ++ 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)); ++ } ++} ++#endif // MOZ_X11 ++ ++void ++nsWindow::SetProgress(unsigned long progressPercent) ++{ ++#ifdef MOZ_X11 ++ ++ if (!mIsX11Display) { ++ return; ++ } ++ ++ if (!mShell) { ++ return; ++ } ++ ++ progressPercent = MIN(progressPercent, 100); ++ ++ set_window_hint_cardinal(GDK_WINDOW_XID(gtk_widget_get_window(mShell)), ++ 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); ++ } ++} ++#endif ++ ++nsresult ++nsWindow::SetSystemFont(const nsCString& aFontName) ++{ ++ GtkSettings* settings = gtk_settings_get_default(); ++ g_object_set(settings, "gtk-font-name", aFontName.get(), nullptr); ++ return NS_OK; ++} ++ ++nsresult ++nsWindow::GetSystemFont(nsCString& aFontName) ++{ ++ GtkSettings* settings = gtk_settings_get_default(); ++ gchar* fontName = nullptr; ++ g_object_get(settings, ++ "gtk-font-name", &fontName, ++ nullptr); ++ if (fontName) { ++ aFontName.Assign(fontName); ++ g_free(fontName); ++ } ++ return NS_OK; ++} ++ ++already_AddRefed ++nsIWidget::CreateTopLevelWindow() ++{ ++ nsCOMPtr window = new nsWindow(); ++ return window.forget(); ++} ++ ++already_AddRefed ++nsIWidget::CreateChildWindow() ++{ ++ nsCOMPtr window = new nsWindow(); ++ return window.forget(); ++} +diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/widget/gtk/nsWindow.h +--- thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsWindow.h 2018-11-20 12:04:43.741787337 +0100 +@@ -66,6 +66,21 @@ 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); ++#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; + + nsWindow(); +@@ -108,6 +124,7 @@ public: + virtual float GetDPI() override; + virtual double GetDefaultScaleInternal() override; + mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override; ++ mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScaleByScreen() override; + virtual void SetParent(nsIWidget* aNewParent) override; + virtual void SetModal(bool aModal) override; + virtual bool IsVisible() const override; +@@ -115,8 +132,7 @@ public: + 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 +244,8 @@ public: + virtual void EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget, + LayoutDeviceIntRegion& aInvalidRegion) override; + ++ void SetProgress(unsigned long progressPercent); ++ + private: + void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface, nsIntRect aBoundsRect); + +@@ -278,10 +296,32 @@ public: + guint aTime); + static void UpdateDragStatus (GdkDragContext *aDragContext, + nsIDragService *aDragService); +- // If this dispatched the keydown event actually, this returns TRUE, +- // otherwise, FALSE. +- bool DispatchKeyDownEvent(GdkEventKey *aEvent, +- bool *aIsCancelled); ++ /** ++ * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event. ++ * ++ * @param aEvent A native GDK_KEY_PRESS or GDK_KEY_RELEASE ++ * event. ++ * @param aProcessedByIME true if the event is handled by IME. ++ * @param aIsCancelled [Out] true if the default is prevented. ++ * @return true if eKeyDown event is actually dispatched. ++ * Otherwise, false. ++ */ ++ bool DispatchKeyDownOrKeyUpEvent(GdkEventKey* aEvent, ++ bool aProcessedByIME, ++ bool* aIsCancelled); ++ ++ /** ++ * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event. ++ * ++ * @param aEvent An eKeyDown or eKeyUp event. This will be ++ * dispatched as is. ++ * @param aIsCancelled [Out] true if the default is prevented. ++ * @return true if eKeyDown event is actually dispatched. ++ * Otherwise, false. ++ */ ++ bool DispatchKeyDownOrKeyUpEvent(WidgetKeyboardEvent& aEvent, ++ bool* aIsCancelled); ++ + WidgetEventTime GetWidgetEventTime(guint32 aEventTime); + mozilla::TimeStamp GetEventTimeStamp(guint32 aEventTime); + mozilla::CurrentX11TimeGetter* GetCurrentTimeGetter(); +@@ -375,6 +415,9 @@ public: + + virtual bool WidgetTypeSupportsAcceleration() override; + ++ nsresult SetSystemFont(const nsCString& aFontName) override; ++ nsresult GetSystemFont(nsCString& aFontName) override; ++ + typedef enum { CSD_SUPPORT_SYSTEM, // CSD including shadows + CSD_SUPPORT_CLIENT, // CSD without shadows + CSD_SUPPORT_NONE, // WM does not support CSD at all +@@ -452,13 +495,24 @@ private: + gint* aRootX, gint* aRootY); + void ClearCachedResources(); + nsIWidgetListener* GetListener(); +- bool IsComposited() const; + + void UpdateClientOffsetForCSDWindow(); + + 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; ++ ++ void SetCompositorHint(WindowComposeRequest aState); ++#endif ++ nsCString mGtkWindowTypeName; ++ nsCString mGtkWindowRoleName; ++ void RefreshWindowClass(); ++ + GtkWidget *mShell; + MozContainer *mContainer; + GdkWindow *mGdkWindow; +@@ -558,6 +612,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/PlatformWidgetTypes.ipdlh.wayland thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh +--- thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh 2018-11-20 12:04:43.741787337 +0100 +@@ -15,6 +15,7 @@ struct GtkCompositorWidgetInitData + { + uintptr_t XWindow; + nsCString XDisplayString; ++ bool Shaped; + + LayoutDeviceIntSize InitialClientSize; + }; +diff -up thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp.wayland thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp +--- thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp 2018-11-20 12:04:43.741787337 +0100 +@@ -197,7 +197,7 @@ ScreenHelperGTK::RefreshScreens() + } + + ScreenManager& screenManager = ScreenManager::GetSingleton(); +- screenManager.Refresh(Move(screenList)); ++ screenManager.Refresh(std::move(screenList)); + } + + } // namespace widget +diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp +--- thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp 2018-11-20 12:04:43.741787337 +0100 +@@ -31,6 +31,7 @@ WindowSurfaceProvider::WindowSurfaceProv + #ifdef MOZ_WAYLAND + , mWidget(nullptr) + #endif ++ , mIsShaped(false) + { + } + +@@ -38,7 +39,8 @@ void WindowSurfaceProvider::Initialize( + Display* aDisplay, + Window aWindow, + Visual* aVisual, +- int aDepth) ++ int aDepth, ++ bool aIsShaped) + { + // We should not be initialized + MOZ_ASSERT(!mXDisplay); +@@ -50,6 +52,7 @@ void WindowSurfaceProvider::Initialize( + mXWindow = aWindow; + mXVisual = aVisual; + mXDepth = aDepth; ++ mIsShaped = aIsShaped; + mIsX11Display = true; + } + +@@ -88,21 +91,22 @@ WindowSurfaceProvider::CreateWindowSurfa + // 3. XPutImage + + #ifdef MOZ_WIDGET_GTK +- if (gfxVars::UseXRender()) { ++ if (!mIsShaped && gfxVars::UseXRender()) { + LOGDRAW(("Drawing to nsWindow %p using XRender\n", (void*)this)); + return MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); + } + #endif // MOZ_WIDGET_GTK + + #ifdef MOZ_HAVE_SHMIMAGE +- if (nsShmImage::UseShm()) { ++ if (!mIsShaped && nsShmImage::UseShm()) { + LOGDRAW(("Drawing to nsWindow %p using MIT-SHM\n", (void*)this)); + return MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); + } + #endif // MOZ_HAVE_SHMIMAGE + + LOGDRAW(("Drawing to nsWindow %p using XPutImage\n", (void*)this)); +- return MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); ++ return MakeUnique(mXDisplay, mXWindow, mXVisual, ++ mXDepth, mIsShaped); + } + + already_AddRefed +@@ -125,7 +129,7 @@ WindowSurfaceProvider::StartRemoteDrawin + // We can't use WindowSurfaceX11Image fallback on Wayland but + // Lock() call on WindowSurfaceWayland should never fail. + gfxWarningOnce() << "Failed to lock WindowSurface, falling back to XPutImage backend."; +- mWindowSurface = MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); ++ mWindowSurface = MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth, mIsShaped); + dt = mWindowSurface->Lock(aInvalidRegion); + } + return dt.forget(); +diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h +--- thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h.wayland 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h 2018-11-20 12:04:43.742787334 +0100 +@@ -17,6 +17,7 @@ + #include + #endif + #include // for Window, Display, Visual, etc. ++#include "X11UndefineNone.h" + + class nsWindow; + +@@ -43,7 +44,8 @@ public: + Display* aDisplay, + Window aWindow, + Visual* aVisual, +- int aDepth); ++ int aDepth, ++ bool aIsShaped); + + #ifdef MOZ_WAYLAND + void Initialize(nsWindow *aWidget); +@@ -75,6 +77,7 @@ private: + #ifdef MOZ_WAYLAND + nsWindow* mWidget; + #endif ++ bool mIsShaped; + }; + + } // namespace widget +diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp +--- thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp 2018-11-20 12:04:43.742787334 +0100 +@@ -151,8 +151,9 @@ static nsWaylandDisplay* WaylandDisplayG + 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) + + // 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() + } + + bool +-WindowBackBuffer::SetImageDataFromBackBuffer( ++WindowBackBuffer::SetImageDataFromBuffer( + class WindowBackBuffer* aSourceBuffer) + { + if (!IsMatchingSize(aSourceBuffer)) { +@@ -535,11 +537,9 @@ WindowBackBuffer::SetImageDataFromBackBu + } + + already_AddRefed +-WindowBackBuffer::Lock(const LayoutDeviceIntRegion& aRegion) ++WindowBackBuffer::Lock() + { +- gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); +- gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); +- ++ gfx::IntSize lockSize(mWidth, mHeight); + return gfxPlatform::CreateDrawTargetForData(static_cast(mShmPool.GetImageData()), + lockSize, + BUFFER_BPP * mWidth, +@@ -551,6 +551,8 @@ frame_callback_handler(void *data, struc + { + auto surface = reinterpret_cast(data); + surface->FrameCallbackHandler(); ++ ++ gfxPlatformGtk::GetPlatform()->SetWaylandLastVsync(time); + } + + static const struct wl_callback_listener frame_listener = { +@@ -560,26 +562,40 @@ static const struct wl_callback_listener + 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) + { + } + + WindowSurfaceWayland::~WindowSurfaceWayland() + { +- delete mFrontBuffer; +- delete mBackBuffer; ++ if (mPendingCommit) { ++ NS_WARNING("Deleted WindowSurfaceWayland with a pending commit!"); ++ } ++ ++ if (mDelayedCommitHandle) { ++ // Delete reference to this to prevent WaylandBufferDelayCommitHandler() ++ // operate on released this. mDelayedCommitHandle itself will ++ // be released at WaylandBufferDelayCommitHandler(). ++ *mDelayedCommitHandle = nullptr; ++ } + + if (mFrameCallback) { + wl_callback_destroy(mFrameCallback); + } + ++ delete mWaylandBuffer; ++ delete mBackupBuffer; ++ + if (!mIsMainThread) { + // We can be destroyed from main thread even though we was created/used + // in compositor thread. We have to unref/delete WaylandDisplay in compositor +@@ -593,162 +609,309 @@ WindowSurfaceWayland::~WindowSurfaceWayl + } + } + +-void +-WindowSurfaceWayland::UpdateScaleFactor() +-{ +- wl_surface* waylandSurface = mWindow->GetWaylandSurface(); +- if (waylandSurface) { +- wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor()); +- } +-} +- + WindowBackBuffer* +-WindowSurfaceWayland::GetBufferToDraw(int aWidth, int aHeight) ++WindowSurfaceWayland::GetWaylandBufferToDraw(int aWidth, int aHeight) + { +- if (!mFrontBuffer) { +- mFrontBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); +- mBackBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); +- return mFrontBuffer; ++ if (!mWaylandBuffer) { ++ mWaylandBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); ++ mBackupBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); ++ return mWaylandBuffer; + } + +- if (!mFrontBuffer->IsAttached()) { +- if (!mFrontBuffer->IsMatchingSize(aWidth, aHeight)) { +- mFrontBuffer->Resize(aWidth, aHeight); ++ if (!mWaylandBuffer->IsAttached()) { ++ if (!mWaylandBuffer->IsMatchingSize(aWidth, aHeight)) { ++ mWaylandBuffer->Resize(aWidth, aHeight); + // There's a chance that scale factor has been changed + // when buffer size changed +- UpdateScaleFactor(); ++ mNeedScaleFactorUpdate = true; + } +- return mFrontBuffer; ++ return mWaylandBuffer; + } + + // Front buffer is used by compositor, draw to back buffer +- if (mBackBuffer->IsAttached()) { ++ if (mBackupBuffer->IsAttached()) { + NS_WARNING("No drawing buffer available"); + return nullptr; + } + +- MOZ_ASSERT(!mDelayedCommit, ++ MOZ_ASSERT(!mPendingCommit, + "Uncommitted buffer switch, screen artifacts ahead."); + +- WindowBackBuffer *tmp = mFrontBuffer; +- mFrontBuffer = mBackBuffer; +- mBackBuffer = tmp; ++ WindowBackBuffer *tmp = mWaylandBuffer; ++ mWaylandBuffer = mBackupBuffer; ++ mBackupBuffer = tmp; + +- if (mBackBuffer->IsMatchingSize(aWidth, aHeight)) { ++ if (mBackupBuffer->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); + // When buffer switches we need to damage whole screen + // (https://bugzilla.redhat.com/show_bug.cgi?id=1418260) +- mFullScreenDamage = true; ++ mWaylandBufferFullScreenDamage = true; + } else { + // Former buffer has different size from the new request. Only resize + // 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(); ++ } ++ ++ NS_WARNING("WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); ++ return nullptr; ++} ++ ++already_AddRefed ++WindowSurfaceWayland::LockImageSurface(const gfx::IntSize& aLockSize) ++{ ++ if (!mImageSurface || mImageSurface->CairoStatus() || ++ !(aLockSize <= mImageSurface->GetSize())) { ++ mImageSurface = new gfxImageSurface(aLockSize, ++ SurfaceFormatToImageFormat(mWaylandDisplay->GetSurfaceFormat())); ++ if (mImageSurface->CairoStatus()) { ++ return nullptr; ++ } + } + +- return mFrontBuffer; ++ return gfxPlatform::CreateDrawTargetForData(mImageSurface->Data(), ++ mImageSurface->GetSize(), ++ mImageSurface->Stride(), ++ mWaylandDisplay->GetSurfaceFormat()); + } + ++/* ++ There are some situations which can happen here: ++ ++ A) Lock() is called to whole surface. In that case we don't need ++ to clip/buffer the drawing and we can return wl_buffer directly ++ for drawing. ++ - mWaylandBuffer is available - that's an ideal situation. ++ - mWaylandBuffer is locked by compositor - flip buffers and draw. ++ - if we can't flip buffers - go B) ++ ++ 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) + { + 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; ++ 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); ++ ++ if (mDrawToWaylandBufferDirectly) { ++ RefPtr dt = LockWaylandBuffer(screenRect.width, ++ screenRect.height); ++ if (dt) { ++ return dt.forget(); ++ } ++ ++ // We don't have any front buffer available. Try indirect drawing ++ // to mImageSurface which is mirrored to front buffer at commit. ++ mDrawToWaylandBufferDirectly = false; + } + +- return buffer->Lock(aRegion); ++ return LockImageSurface(lockSize); ++} ++ ++bool ++WindowSurfaceWayland::CommitImageSurfaceToWaylandBuffer(const LayoutDeviceIntRegion& aRegion) ++{ ++ MOZ_ASSERT(!mDrawToWaylandBufferDirectly); ++ ++ LayoutDeviceIntRect screenRect = mWindow->GetBounds(); ++ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); ++ ++ gfx::Rect rect(bounds); ++ if (rect.IsEmpty()) { ++ return false; ++ } ++ ++ RefPtr dt = LockWaylandBuffer(screenRect.width, ++ screenRect.height); ++ RefPtr surf = ++ gfx::Factory::CreateSourceSurfaceForCairoSurface(mImageSurface->CairoSurface(), ++ mImageSurface->GetSize(), ++ mImageSurface->Format()); ++ if (!dt || !surf) { ++ return false; ++ } ++ ++ uint32_t numRects = aRegion.GetNumRects(); ++ if (numRects != 1) { ++ AutoTArray rects; ++ rects.SetCapacity(numRects); ++ for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { ++ rects.AppendElement(iter.Get().ToUnknownRect()); ++ } ++ dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); ++ } ++ ++ dt->DrawSurface(surf, rect, rect); ++ ++ if (numRects != 1) { ++ dt->PopClip(); ++ } ++ ++ return true; ++} ++ ++static void ++WaylandBufferDelayCommitHandler(WindowSurfaceWayland **aSurface) ++{ ++ if (*aSurface) { ++ (*aSurface)->DelayedCommitHandler(); ++ } else { ++ // Referenced WindowSurfaceWayland is already deleted. ++ // Do nothing but just release the mDelayedCommitHandle allocated at ++ // WindowSurfaceWayland::CommitWaylandBuffer(). ++ free(aSurface); ++ } + } + + void +-WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion) ++WindowSurfaceWayland::CommitWaylandBuffer() + { +- MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); ++ MOZ_ASSERT(mPendingCommit, "Committing empty surface!"); + + 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!"); ++ ++ // Do nothing if there's already mDelayedCommitHandle pending. ++ if (!mDelayedCommitHandle) { ++ mDelayedCommitHandle = static_cast( ++ moz_xmalloc(sizeof(*mDelayedCommitHandle))); ++ *mDelayedCommitHandle = this; ++ ++ MessageLoop::current()->PostDelayedTask( ++ NewRunnableFunction("WaylandBackBufferCommit", ++ &WaylandBufferDelayCommitHandler, ++ mDelayedCommitHandle), ++ EVENT_LOOP_DELAY); ++ } + return; + } + wl_proxy_set_queue((struct wl_proxy *)waylandSurface, + mWaylandDisplay->GetEventQueue()); + +- if (mFullScreenDamage) { ++ // We have an active frame callback request so handle it. ++ if (mFrameCallback) { ++ if (waylandSurface == mLastCommittedSurface) { ++ // We have an active frame callback pending from our recent surface. ++ // It means we should defer the commit to FrameCallbackHandler(). ++ return; ++ } ++ // If our stored wl_surface does not match the actual one it means the frame ++ // callback is no longer active and we should release it. ++ wl_callback_destroy(mFrameCallback); ++ mFrameCallback = nullptr; ++ mLastCommittedSurface = nullptr; ++ } ++ ++ if (mWaylandBufferFullScreenDamage) { + LayoutDeviceIntRect rect = mWindow->GetBounds(); + wl_surface_damage(waylandSurface, 0, 0, rect.width, rect.height); +- mFullScreenDamage = false; ++ 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(); +- wl_surface_damage(waylandSurface, r.x, r.y, r.width, r.height); ++ // 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); + } + } + +- // Frame callback is always connected to actual wl_surface. When the surface +- // is unmapped/deleted the frame callback is never called. Unfortunatelly +- // we don't know if the frame callback is not going to be called. +- // But our mozcontainer code deletes wl_surface when the GdkWindow is hidden +- // creates a new one when is visible. +- if (mFrameCallback && mFrameCallbackSurface == waylandSurface) { +- // Do nothing here - we have a valid wl_surface and the buffer will be +- // commited to compositor in next frame callback event. +- mDelayedCommit = true; +- return; +- } else { +- if (mFrameCallback) { +- // Delete frame callback connected to obsoleted wl_surface. +- wl_callback_destroy(mFrameCallback); +- } ++ // Clear all back buffer damage as we're committing ++ // all requested regions. ++ mWaylandBufferDamage.SetEmpty(); + +- mFrameCallback = wl_surface_frame(waylandSurface); +- wl_callback_add_listener(mFrameCallback, &frame_listener, this); +- mFrameCallbackSurface = waylandSurface; +- +- // There's no pending frame callback so we can draw immediately +- // and create frame callback for possible subsequent drawing. +- mFrontBuffer->Attach(waylandSurface); +- mDelayedCommit = false; ++ mFrameCallback = wl_surface_frame(waylandSurface); ++ wl_callback_add_listener(mFrameCallback, &frame_listener, this); ++ ++ if (mNeedScaleFactorUpdate || mLastCommittedSurface != waylandSurface) { ++ wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor()); ++ mNeedScaleFactorUpdate = false; ++ } ++ ++ mWaylandBuffer->Attach(waylandSurface); ++ mLastCommittedSurface = waylandSurface; ++ ++ // There's no pending commit, all changes are sent to compositor. ++ mPendingCommit = false; ++} ++ ++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) { ++ mWaylandBufferDamage.OrWith(aInvalidRegion); ++ } ++ ++ // We're ready to commit. ++ mPendingCommit = true; ++ CommitWaylandBuffer(); + } + + void + WindowSurfaceWayland::FrameCallbackHandler() + { + MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); ++ MOZ_ASSERT(mFrameCallback != nullptr, ++ "FrameCallbackHandler() called without valid frame callback!"); ++ MOZ_ASSERT(mLastCommittedSurface != nullptr, ++ "FrameCallbackHandler() called without valid wl_surface!"); + +- if (mFrameCallback) { +- wl_callback_destroy(mFrameCallback); +- mFrameCallback = nullptr; +- mFrameCallbackSurface = nullptr; ++ wl_callback_destroy(mFrameCallback); ++ mFrameCallback = nullptr; ++ ++ if (mPendingCommit) { ++ CommitWaylandBuffer(); + } ++} + +- if (mDelayedCommit) { +- wl_surface* waylandSurface = mWindow->GetWaylandSurface(); +- if (!waylandSurface) { +- // Target window is already destroyed - don't bother to render there. +- NS_WARNING("No drawing buffer available"); +- return; +- } +- wl_proxy_set_queue((struct wl_proxy *)waylandSurface, +- mWaylandDisplay->GetEventQueue()); ++void ++WindowSurfaceWayland::DelayedCommitHandler() ++{ ++ MOZ_ASSERT(mDelayedCommitHandle != nullptr, "Missing mDelayedCommitHandle!"); + +- // Send pending surface to compositor and register frame callback +- // for possible subsequent drawing. +- mFrameCallback = wl_surface_frame(waylandSurface); +- wl_callback_add_listener(mFrameCallback, &frame_listener, this); +- mFrameCallbackSurface = waylandSurface; ++ *mDelayedCommitHandle = nullptr; ++ free(mDelayedCommitHandle); ++ mDelayedCommitHandle = nullptr; + +- mFrontBuffer->Attach(waylandSurface); +- mDelayedCommit = false; ++ if (mPendingCommit) { ++ CommitWaylandBuffer(); + } + } + +diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h +--- thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h 2018-11-20 12:04:43.742787334 +0100 +@@ -8,6 +8,7 @@ + #define _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H + + #include ++#include "mozilla/gfx/Types.h" + + namespace mozilla { + namespace widget { +@@ -66,14 +67,14 @@ public: + WindowBackBuffer(nsWaylandDisplay* aDisplay, int aWidth, int aHeight); + ~WindowBackBuffer(); + +- already_AddRefed Lock(const LayoutDeviceIntRegion& aRegion); ++ already_AddRefed Lock(); + + void Attach(wl_surface* aSurface); + void Detach(); + bool IsAttached() { return mAttached; } + + 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(); + + private: +- WindowBackBuffer* GetBufferToDraw(int aWidth, int aHeight); +- void UpdateScaleFactor(); ++ WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight); ++ ++ already_AddRefed LockWaylandBuffer(int aWidth, int aHeight); ++ 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; + }; + + } // namespace widget +diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp +--- thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp 2018-11-20 12:04:43.743787331 +0100 +@@ -12,19 +12,42 @@ + #include "gfxPlatform.h" + #include "gfx2DGlue.h" + ++#include ++ + namespace mozilla { + namespace widget { + ++// gfxImageSurface pixel format configuration. ++#define SHAPED_IMAGE_SURFACE_BPP 4 ++#ifdef IS_BIG_ENDIAN ++ #define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 0 ++#else ++ #define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 3 ++#endif ++ + WindowSurfaceX11Image::WindowSurfaceX11Image(Display* aDisplay, + Window aWindow, + Visual* aVisual, +- unsigned int aDepth) ++ unsigned int aDepth, ++ bool aIsShaped) + : WindowSurfaceX11(aDisplay, aWindow, aVisual, aDepth) ++ , mTransparencyBitmap(nullptr) ++ , mTransparencyBitmapWidth(0) ++ , mTransparencyBitmapHeight(0) ++ , mIsShaped(aIsShaped) + { + } + + WindowSurfaceX11Image::~WindowSurfaceX11Image() + { ++ if (mTransparencyBitmap) { ++ delete[] mTransparencyBitmap; ++ ++ Display* xDisplay = mWindowSurface->XDisplay(); ++ Window xDrawable = mWindowSurface->XDrawable(); ++ ++ XShapeCombineMask(xDisplay, xDrawable, ShapeBounding, 0, 0, X11None, ShapeSet); ++ } + } + + already_AddRefed +@@ -50,6 +73,13 @@ WindowSurfaceX11Image::Lock(const Layout + gfx::SurfaceFormat::X8R8G8B8_UINT32; + } + ++ // Use alpha image format for shaped window as we derive ++ // the shape bitmap from alpha channel. Must match SHAPED_IMAGE_SURFACE_BPP ++ // and SHAPED_IMAGE_SURFACE_ALPHA_INDEX. ++ if (mIsShaped) { ++ format = gfx::SurfaceFormat::A8R8G8B8_UINT32; ++ } ++ + mImageSurface = new gfxImageSurface(size, format); + if (mImageSurface->CairoStatus()) { + return nullptr; +@@ -82,6 +112,132 @@ WindowSurfaceX11Image::Lock(const Layout + ImageFormatToSurfaceFormat(format)); + } + ++// The transparency bitmap routines are derived form the ones at nsWindow.cpp. ++// The difference here is that we compose to RGBA image and then create ++// the shape mask from final image alpha channel. ++static inline int32_t ++GetBitmapStride(int32_t width) ++{ ++ return (width+7)/8; ++} ++ ++static bool ++ChangedMaskBits(gchar* aMaskBits, int32_t aMaskWidth, int32_t aMaskHeight, ++ const nsIntRect& aRect, uint8_t* aImageData) ++{ ++ int32_t stride = aMaskWidth*SHAPED_IMAGE_SURFACE_BPP; ++ int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost(); ++ int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth); ++ for (y = aRect.y; y < yMax; y++) { ++ gchar* maskBytes = aMaskBits + y*maskBytesPerRow; ++ uint8_t* alphas = aImageData; ++ for (x = aRect.x; x < xMax; x++) { ++ bool newBit = *(alphas+SHAPED_IMAGE_SURFACE_ALPHA_INDEX) > 0x7f; ++ alphas += SHAPED_IMAGE_SURFACE_BPP; ++ ++ gchar maskByte = maskBytes[x >> 3]; ++ bool maskBit = (maskByte & (1 << (x & 7))) != 0; ++ ++ if (maskBit != newBit) { ++ return true; ++ } ++ } ++ aImageData += stride; ++ } ++ ++ return false; ++} ++ ++static void ++UpdateMaskBits(gchar* aMaskBits, int32_t aMaskWidth, int32_t aMaskHeight, ++ const nsIntRect& aRect, uint8_t* aImageData) ++{ ++ int32_t stride = aMaskWidth*SHAPED_IMAGE_SURFACE_BPP; ++ int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost(); ++ int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth); ++ for (y = aRect.y; y < yMax; y++) { ++ gchar* maskBytes = aMaskBits + y*maskBytesPerRow; ++ uint8_t* alphas = aImageData; ++ for (x = aRect.x; x < xMax; x++) { ++ bool newBit = *(alphas+SHAPED_IMAGE_SURFACE_ALPHA_INDEX) > 0x7f; ++ alphas += SHAPED_IMAGE_SURFACE_BPP; ++ ++ gchar mask = 1 << (x & 7); ++ gchar maskByte = maskBytes[x >> 3]; ++ // Note: '-newBit' turns 0 into 00...00 and 1 into 11...11 ++ maskBytes[x >> 3] = (maskByte & ~mask) | (-newBit & mask); ++ } ++ aImageData += stride; ++ } ++} ++ ++void ++WindowSurfaceX11Image::ResizeTransparencyBitmap(int aWidth, int aHeight) ++{ ++ int32_t actualSize = ++ GetBitmapStride(mTransparencyBitmapWidth)*mTransparencyBitmapHeight; ++ int32_t newSize = GetBitmapStride(aWidth)*aHeight; ++ ++ if (actualSize < newSize) { ++ delete[] mTransparencyBitmap; ++ mTransparencyBitmap = new gchar[newSize]; ++ } ++ ++ mTransparencyBitmapWidth = aWidth; ++ mTransparencyBitmapHeight = aHeight; ++} ++ ++void ++WindowSurfaceX11Image::ApplyTransparencyBitmap() ++{ ++ gfx::IntSize size = mWindowSurface->GetSize(); ++ bool maskChanged = true; ++ ++ if (!mTransparencyBitmap) { ++ mTransparencyBitmapWidth = size.width; ++ mTransparencyBitmapHeight = size.height; ++ ++ int32_t byteSize = ++ GetBitmapStride(mTransparencyBitmapWidth)*mTransparencyBitmapHeight; ++ mTransparencyBitmap = new gchar[byteSize]; ++ } else { ++ bool sizeChanged = (size.width != mTransparencyBitmapWidth || ++ size.height != mTransparencyBitmapHeight); ++ ++ if (sizeChanged) { ++ ResizeTransparencyBitmap(size.width, size.height); ++ } else { ++ maskChanged = ChangedMaskBits(mTransparencyBitmap, ++ mTransparencyBitmapWidth, mTransparencyBitmapHeight, ++ nsIntRect(0, 0, size.width, size.height), ++ (uint8_t*)mImageSurface->Data()); ++ } ++ } ++ ++ if (maskChanged) { ++ UpdateMaskBits(mTransparencyBitmap, ++ mTransparencyBitmapWidth, ++ mTransparencyBitmapHeight, ++ nsIntRect(0, 0, size.width, size.height), ++ (uint8_t*)mImageSurface->Data()); ++ ++ // We use X11 calls where possible, because GDK handles expose events ++ // for shaped windows in a way that's incompatible with us (Bug 635903). ++ // It doesn't occur when the shapes are set through X. ++ Display* xDisplay = mWindowSurface->XDisplay(); ++ Window xDrawable = mWindowSurface->XDrawable(); ++ Pixmap maskPixmap = XCreateBitmapFromData(xDisplay, ++ xDrawable, ++ mTransparencyBitmap, ++ mTransparencyBitmapWidth, ++ mTransparencyBitmapHeight); ++ XShapeCombineMask(xDisplay, xDrawable, ++ ShapeBounding, 0, 0, ++ maskPixmap, ShapeSet); ++ XFreePixmap(xDisplay, maskPixmap); ++ } ++} ++ + void + WindowSurfaceX11Image::Commit(const LayoutDeviceIntRegion& aInvalidRegion) + { +@@ -112,6 +268,10 @@ WindowSurfaceX11Image::Commit(const Layo + dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); + } + ++ if (mIsShaped) { ++ ApplyTransparencyBitmap(); ++ } ++ + dt->DrawSurface(surf, rect, rect); + + if (numRects != 1) { +diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h +--- thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h.wayland 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h 2018-11-20 12:04:43.743787331 +0100 +@@ -19,7 +19,7 @@ namespace widget { + class WindowSurfaceX11Image : public WindowSurfaceX11 { + public: + WindowSurfaceX11Image(Display* aDisplay, Window aWindow, Visual* aVisual, +- unsigned int aDepth); ++ unsigned int aDepth, bool aIsShaped); + ~WindowSurfaceX11Image(); + + already_AddRefed Lock(const LayoutDeviceIntRegion& aRegion) override; +@@ -27,8 +27,16 @@ public: + bool IsFallback() const override { return true; } + + private: ++ void ResizeTransparencyBitmap(int aWidth, int aHeight); ++ void ApplyTransparencyBitmap(); ++ + RefPtr mWindowSurface; + RefPtr mImageSurface; ++ ++ gchar* mTransparencyBitmap; ++ int32_t mTransparencyBitmapWidth; ++ int32_t mTransparencyBitmapHeight; ++ bool mIsShaped; + }; + + } // namespace widget diff --git a/thunderbird-dbus-remote.patch b/thunderbird-dbus-remote.patch new file mode 100644 index 0000000..856e64e --- /dev/null +++ b/thunderbird-dbus-remote.patch @@ -0,0 +1,188 @@ +diff -up thunderbird-60.3.0/toolkit/components/remote/nsDBusRemoteService.cpp.old thunderbird-60.3.0/toolkit/components/remote/nsDBusRemoteService.cpp +--- thunderbird-60.3.0/toolkit/components/remote/nsDBusRemoteService.cpp.old 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/toolkit/components/remote/nsDBusRemoteService.cpp 2018-11-14 13:37:32.223714689 +0100 +@@ -174,6 +174,7 @@ nsDBusRemoteService::Startup(const char* + return NS_ERROR_FAILURE; + } + dbus_connection_set_exit_on_disconnect(mConnection, false); ++ dbus_connection_setup_with_g_main(mConnection, nullptr); + + mAppName = aAppName; + ToLowerCase(mAppName); +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-20 10:55:35.584756422 +0100 ++++ thunderbird-60.3.0/toolkit/components/remote/nsRemoteService.cpp 2018-11-14 13:37:32.244714628 +0100 +@@ -34,20 +34,18 @@ NS_IMPL_ISUPPORTS(nsRemoteService, + NS_IMETHODIMP + nsRemoteService::Startup(const char* aAppName, const char* aProfileName) + { +-#if 0 ++#if defined(MOZ_ENABLE_DBUS) && defined(MOZ_WAYLAND) + nsresult rv; + mDBusRemoteService = new nsDBusRemoteService(); + rv = mDBusRemoteService->Startup(aAppName, aProfileName); + if (NS_FAILED(rv)) { + mDBusRemoteService = nullptr; + } ++#elif !defined(MOZ_WAYLAND) ++ mGtkRemoteService = new nsGTKRemoteService(); ++ mGtkRemoteService->Startup(aAppName, aProfileName); + #endif + +- if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) { +- mGtkRemoteService = new nsGTKRemoteService(); +- mGtkRemoteService->Startup(aAppName, aProfileName); +- } +- + if (!mDBusRemoteService && !mGtkRemoteService) + return NS_ERROR_FAILURE; + +@@ -73,7 +71,7 @@ nsRemoteService::RegisterWindow(mozIDOMW + NS_IMETHODIMP + nsRemoteService::Shutdown() + { +-#if defined(MOZ_ENABLE_DBUS) ++#if defined(MOZ_ENABLE_DBUS) && defined(MOZ_WAYLAND) + if (mDBusRemoteService) { + mDBusRemoteService->Shutdown(); + mDBusRemoteService = nullptr; +diff -up thunderbird-60.3.0/toolkit/components/remote/nsXRemoteService.cpp.old thunderbird-60.3.0/toolkit/components/remote/nsXRemoteService.cpp +--- thunderbird-60.3.0/toolkit/components/remote/nsXRemoteService.cpp.old 2018-10-30 12:45:34.000000000 +0100 ++++ thunderbird-60.3.0/toolkit/components/remote/nsXRemoteService.cpp 2018-10-31 01:08:14.000000000 +0100 +@@ -192,5 +192,5 @@ nsXRemoteService::EnsureAtoms(void) + sMozUserAtom = XAtoms[i++]; + sMozProfileAtom = XAtoms[i++]; + sMozProgramAtom = XAtoms[i++]; +- sMozCommandLineAtom = XAtoms[i++]; ++ sMozCommandLineAtom = XAtoms[i]; + } +diff -up thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.cpp.old thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.cpp +--- thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.cpp.old 2018-10-30 12:45:35.000000000 +0100 ++++ thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.cpp 2018-11-14 13:37:32.224714686 +0100 +@@ -12,6 +12,7 @@ + #include "mozilla/Base64.h" + #include "nsPrintfCString.h" + ++#include + #include + + using mozilla::LogLevel; +@@ -43,6 +44,7 @@ DBusRemoteClient::Init() + return NS_ERROR_FAILURE; + + dbus_connection_set_exit_on_disconnect(mConnection, false); ++ dbus_connection_setup_with_g_main(mConnection, nullptr); + + return NS_OK; + } +diff -up thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.h.old thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.h +diff -up thunderbird-60.3.0/widget/xremoteclient/moz.build.old thunderbird-60.3.0/widget/xremoteclient/moz.build +--- thunderbird-60.3.0/widget/xremoteclient/moz.build.old 2018-10-31 01:08:14.000000000 +0100 ++++ thunderbird-60.3.0/widget/xremoteclient/moz.build 2018-11-14 13:37:32.244714628 +0100 +@@ -11,7 +11,6 @@ FINAL_LIBRARY = 'xul' + + SOURCES += [ + 'RemoteUtils.cpp', +- 'XRemoteClient.cpp', + ] + + if CONFIG['MOZ_ENABLE_DBUS'] and CONFIG['MOZ_WAYLAND']: +@@ -20,3 +19,7 @@ if CONFIG['MOZ_ENABLE_DBUS'] and CONFIG[ + ] + CXXFLAGS += CONFIG['TK_CFLAGS'] + CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] ++else: ++ SOURCES += [ ++ 'XRemoteClient.cpp', ++ ] +diff -up thunderbird-60.3.0/widget/xremoteclient/XRemoteClient.cpp.old thunderbird-60.3.0/widget/xremoteclient/XRemoteClient.cpp +--- thunderbird-60.3.0/widget/xremoteclient/XRemoteClient.cpp.old 2018-10-30 12:45:37.000000000 +0100 ++++ thunderbird-60.3.0/widget/xremoteclient/XRemoteClient.cpp 2018-10-31 01:08:15.000000000 +0100 +@@ -9,6 +9,7 @@ + #include "mozilla/ArrayUtils.h" + #include "mozilla/IntegerPrintfMacros.h" + #include "mozilla/Sprintf.h" ++#include "mozilla/Unused.h" + #include "XRemoteClient.h" + #include "RemoteUtils.h" + #include "plstr.h" +@@ -41,7 +42,7 @@ + #else + #define TO_LITTLE_ENDIAN32(x) (x) + #endif +- ++ + #ifndef MAX_PATH + #ifdef PATH_MAX + #define MAX_PATH PATH_MAX +@@ -51,6 +52,7 @@ + #endif + + using mozilla::LogLevel; ++using mozilla::Unused; + + static mozilla::LazyLogModule sRemoteLm("XRemoteClient"); + +@@ -118,7 +120,7 @@ XRemoteClient::Init() + mMozUserAtom = XAtoms[i++]; + mMozProfileAtom = XAtoms[i++]; + mMozProgramAtom = XAtoms[i++]; +- mMozCommandLineAtom = XAtoms[i++]; ++ mMozCommandLineAtom = XAtoms[i]; + + mInitialized = true; + +@@ -472,12 +474,12 @@ XRemoteClient::FindBestWindow(const char + // pass in a program name and this window doesn't support that + // protocol, we don't include it in our list. + if (aProgram && strcmp(aProgram, "any")) { +- status = XGetWindowProperty(mDisplay, w, mMozProgramAtom, +- 0, (65536 / sizeof(long)), +- False, XA_STRING, +- &type, &format, &nitems, &bytesafter, +- &data_return); +- ++ Unused << XGetWindowProperty(mDisplay, w, mMozProgramAtom, ++ 0, (65536 / sizeof(long)), ++ False, XA_STRING, ++ &type, &format, &nitems, &bytesafter, ++ &data_return); ++ + // If the return name is not the same as what someone passed in, + // we don't want this window. + if (data_return) { +@@ -507,11 +509,11 @@ XRemoteClient::FindBestWindow(const char + } + + if (username) { +- status = XGetWindowProperty(mDisplay, w, mMozUserAtom, +- 0, (65536 / sizeof(long)), +- False, XA_STRING, +- &type, &format, &nitems, &bytesafter, +- &data_return); ++ Unused << XGetWindowProperty(mDisplay, w, mMozUserAtom, ++ 0, (65536 / sizeof(long)), ++ False, XA_STRING, ++ &type, &format, &nitems, &bytesafter, ++ &data_return); + + // if there's a username compare it with what we have + if (data_return) { +@@ -529,11 +531,11 @@ XRemoteClient::FindBestWindow(const char + // there is, then we need to make sure it matches what someone + // passed in. + if (aProfile) { +- status = XGetWindowProperty(mDisplay, w, mMozProfileAtom, +- 0, (65536 / sizeof(long)), +- False, XA_STRING, +- &type, &format, &nitems, &bytesafter, +- &data_return); ++ Unused << XGetWindowProperty(mDisplay, w, mMozProfileAtom, ++ 0, (65536 / sizeof(long)), ++ False, XA_STRING, ++ &type, &format, &nitems, &bytesafter, ++ &data_return); + + // If there's a profile compare it with what we have + if (data_return) { + diff --git a/thunderbird-mozconfig b/thunderbird-mozconfig index 0dce186..c6e3cc4 100644 --- a/thunderbird-mozconfig +++ b/thunderbird-mozconfig @@ -2,7 +2,7 @@ mk_add_options MOZ_CO_PROJECT=mail ac_add_options --enable-application=comm/mail mk_add_options AUTOCONF=autoconf-2.13 -#ac_add_options --with-system-png +ac_add_options --enable-default-toolkit=cairo-gtk3-wayland ac_add_options --prefix="$PREFIX" ac_add_options --libdir="$LIBDIR" diff --git a/thunderbird-wayland.desktop b/thunderbird-wayland.desktop new file mode 100644 index 0000000..23a7c24 --- /dev/null +++ b/thunderbird-wayland.desktop @@ -0,0 +1,30 @@ +[Desktop Entry] +Version=1.0 +Name=Thunderbird on Wayland +GenericName=Email +Comment=Send and Receive Email +Exec=thunderbird %u +TryExec=thunderbird-wayland +Icon=thunderbird +Terminal=false +Type=Application +MimeType=message/rfc822;x-scheme-handler/mailto; +StartupNotify=true +Categories=Network;Email; +Name[cs]=Poštovní klient Thunderbird +Name[ca]=Client de correu Thunderbird +Name[fi]=Thunderbird-sähköposti +Name[fr]=Messagerie Thunderbird +Name[pl]=Klient poczty Thunderbird +Name[pt_BR]=Cliente de E-mail Thunderbird +Name[sv]=E-postklienten Thunderbird +Comment[ca]=Llegiu i escriviu correu +Comment[cs]=Čtení a psaní pošty +Comment[de]=Emails lesen und verfassen +Comment[fi]=Lue ja kirjoita sähköposteja +Comment[fr]=Lire et écrire des courriels +Comment[it]=Leggere e scrivere email +Comment[ja]=メールの読み書き +Comment[pl]=Czytanie i wysyłanie e-maili +Comment[pt_BR]=Ler e escrever suas mensagens +Comment[sv]=Läs och skriv e-post diff --git a/thunderbird-wayland.sh.in b/thunderbird-wayland.sh.in new file mode 100644 index 0000000..0bbbd9c --- /dev/null +++ b/thunderbird-wayland.sh.in @@ -0,0 +1,7 @@ +#!/bin/bash +# +# Run Thunderbird under Wayland +# + +export GDK_BACKEND=wayland +exec /usr/bin/thunderbird "$@" diff --git a/thunderbird.sh.in b/thunderbird.sh.in index b0ff04d..c178d2f 100644 --- a/thunderbird.sh.in +++ b/thunderbird.sh.in @@ -36,6 +36,13 @@ MOZ_LANGPACKS_DIR="$MOZ_DIST_BIN/langpacks" MOZ_EXTENSIONS_PROFILE_DIR="$HOME/.mozilla/extensions/{3550f703-e582-4d05-9a08-453d09bdfdc6}" MOZ_LAUNCHER="$MOZ_DIST_BIN/thunderbird" +## +## Enable X11 backend by default? +## +if ! [ "$GDK_BACKEND" ]; then + export GDK_BACKEND=x11 +fi + ## ## Set MOZ_ENABLE_PANGO is no longer used because Pango is enabled by default ## you may use MOZ_DISABLE_PANGO=1 to force disabling of pango diff --git a/thunderbird.spec b/thunderbird.spec index 3a8955c..0f8882c 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -9,7 +9,6 @@ %define system_sqlite 0 %define system_ffi 1 -%define use_gtk3 0 %define build_langpacks 1 @@ -55,23 +54,19 @@ %define big_endian 1 %endif -%if 0%{?fedora} >= 26 || 0%{?rhel} > 7 -%define use_gtk3 1 -%endif - %if %{?system_libvpx} %global libvpx_version 1.4.0 %endif %define tb_version 45.6.0 -%define thunderbird_app_id \{3550f703-e582-4d05-9a08-453d09bdfdc6\} +%define thunderbird_app_id \{3550f703-e582-4d05-9a08-453d09bdfdc6\} %global langpackdir %{mozappdir}/distribution/extensions # The tarball is pretty inconsistent with directory structure. # Sometimes there is a top level directory. That goes here. # -# IMPORTANT: If there is no top level directory, this should be +# IMPORTANT: If there is no top level directory, this should be # set to the cwd, ie: '.' %define objdir objdir %define mozappdir %{_libdir}/%{name} @@ -89,7 +84,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.3.0 -Release: 3%{?dist} +Release: 4%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -106,6 +101,8 @@ Source11: thunderbird-mozconfig-branded Source12: thunderbird-redhat-default-prefs.js Source20: thunderbird.desktop Source21: thunderbird.sh.in +Source28: thunderbird-wayland.sh.in +Source29: thunderbird-wayland.desktop # Mozilla (XULRunner) patches Patch9: mozilla-build-arm.patch @@ -129,6 +126,8 @@ Patch309: mozilla-1460871-ldap-query.patch # Fedora specific patches Patch310: disable-dbus-remote.patch +Patch311: firefox-wayland.patch +Patch312: thunderbird-dbus-remote.patch # Upstream patches @@ -155,9 +154,7 @@ BuildRequires: zip BuildRequires: bzip2-devel BuildRequires: zlib-devel BuildRequires: libIDL-devel -%if %{?use_gtk3} BuildRequires: pkgconfig(gtk+-3.0) -%endif BuildRequires: pkgconfig(gtk+-2.0) BuildRequires: krb5-devel BuildRequires: pango-devel @@ -203,6 +200,16 @@ Suggests: u2f-hidraw-policy %description Mozilla Thunderbird is a standalone mail and newsgroup client. +%package wayland +Summary: Thunderbird Wayland launcher. +Requires: %{name} +%description wayland +The thunderbird-wayland package contains launcher and desktop file +to run Thunderbird natively on Wayland. +%files wayland +%{_bindir}/thunderbird-wayland +%attr(644,root,root) %{_datadir}/applications/mozilla-thunderbird-wayland.desktop + %if %{enable_mozilla_crashreporter} %global moz_debug_prefix %{_prefix}/lib/debug %global moz_debug_dir %{moz_debug_prefix}%{mozappdir} @@ -263,6 +270,11 @@ debug %{name}, you want to install %{name}-debuginfo instead. %endif #cd .. +# TODO - needs fixes +#%patch311 -p1 -b .wayland +#%patch312 -p1 -b .thunderbird-dbus-remote + + %if %{official_branding} # Required by Mozilla Corporation @@ -374,11 +386,6 @@ echo "ac_add_options --with-system-libvpx" >> .mozconfig %else echo "ac_add_options --without-system-libvpx" >> .mozconfig %endif -%if %{?use_gtk3} - echo "ac_add_options --enable-default-toolkit=cairo-gtk3" >> .mozconfig -%else - echo "ac_add_options --enable-default-toolkit=cairo-gtk2" >> .mozconfig -%endif %if %{enable_mozilla_crashreporter} echo "ac_add_options --enable-crashreporter" >> .mozconfig %else @@ -415,7 +422,7 @@ find ./ -name config.guess -exec cp /usr/lib/rpm/config.guess {} ';' # everywhere in the code; so, don't override that. # # Disable C++ exceptions since Mozilla code is not exception-safe -# +# MOZ_OPT_FLAGS=$(echo "$RPM_OPT_FLAGS -fpermissive" | \ %{__sed} -e 's/-Wall//') #rhbz#1037353 @@ -488,12 +495,17 @@ done desktop-file-install --vendor mozilla \ --dir $RPM_BUILD_ROOT%{_datadir}/applications \ %{SOURCE20} +desktop-file-install --vendor mozilla \ + --dir $RPM_BUILD_ROOT%{_datadir}/applications \ + %{SOURCE29} # set up the thunderbird start script rm -f $RPM_BUILD_ROOT/%{_bindir}/thunderbird %{__cat} %{SOURCE21} > $RPM_BUILD_ROOT%{_bindir}/thunderbird %{__chmod} 755 $RPM_BUILD_ROOT/%{_bindir}/thunderbird +%{__cat} %{SOURCE28} > %{buildroot}%{_bindir}/thunderbird-wayland +%{__chmod} 755 %{buildroot}%{_bindir}/thunderbird-wayland # set up our default preferences %{__cat} %{SOURCE12} | %{__sed} -e 's,THUNDERBIRD_RPM_VR,%{tb_version}-%{release},g' > \ @@ -556,7 +568,7 @@ ln -s %{_datadir}/myspell $RPM_BUILD_ROOT%{mozappdir}/dictionaries touch $RPM_BUILD_ROOT%{mozappdir}/components/compreg.dat touch $RPM_BUILD_ROOT%{mozappdir}/components/xpti.dat -# Add debuginfo for crash-stats.mozilla.com +# Add debuginfo for crash-stats.mozilla.com %if %{enable_mozilla_crashreporter} %{__mkdir_p} $RPM_BUILD_ROOT/%{moz_debug_dir} %{__cp} %{objdir}/dist/%{symbols_file_name} $RPM_BUILD_ROOT/%{moz_debug_dir} @@ -673,19 +685,18 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %endif %{mozappdir}/dependentlibs.list %{mozappdir}/distribution -%if !%{?system_libicu} -#%{mozappdir}/icudt*.dat -%endif %{mozappdir}/fonts %{mozappdir}/chrome.manifest %{mozappdir}/pingsender -%if %{?use_gtk3} %{mozappdir}/gtk2/libmozgtk.so -%endif #=============================================================================== %changelog +* Tue Nov 20 2018 Martin Stransky - 60.3.0-4 +- Build with Wayland support +- Enabled DBus remote for Wayland + * Tue Nov 13 2018 Caolán McNamara - 60.3.0-3 - rebuild for hunspell-1.7.0 @@ -986,7 +997,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : - Update to 24.3.0 * Mon Dec 16 2013 Martin Stransky - 24.2.0-4 -- Fixed rhbz#1024232 - thunderbird: squiggly lines used +- Fixed rhbz#1024232 - thunderbird: squiggly lines used for spelling correction disappear randomly * Fri Dec 13 2013 Martin Stransky - 24.2.0-3 @@ -1322,7 +1333,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : - Update to 3.0.1 * Mon Jan 18 2010 Martin Stransky - 3.0-5 -- Added fix for #480603 - thunderbird takes +- Added fix for #480603 - thunderbird takes unacceptably long time to start * Wed Dec 9 2009 Jan Horak - 3.0-4 @@ -1371,7 +1382,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : * Mon Mar 2 2009 Jan Horak - 3.0-1.beta2 - Update to 3.0 beta2 -- Added Patch2 to build correctly when building with --enable-shared option +- Added Patch2 to build correctly when building with --enable-shared option * Wed Feb 25 2009 Fedora Release Engineering - 2.0.0.18-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild @@ -1425,7 +1436,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : - Removed hardcoded MAX_PATH, PATH_MAX and MAXPATHLEN macros * Tue Sep 11 2007 Christopher Aillon 2.0.0.6-4 -- Fix crashes when using GTK+ themes containing a gtkrc which specify +- Fix crashes when using GTK+ themes containing a gtkrc which specify GtkOptionMenu::indicator_size and GtkOptionMenu::indicator_spacing * Mon Sep 10 2007 Martin Stransky 2.0.0.6-3 @@ -1471,7 +1482,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : * Mon Feb 12 2007 Martin Stransky 1.5.0.9-8 - added fix for #227406: garbage characters on some websites (when pango is disabled) - + * Tue Jan 30 2007 Christopher Aillon 1.5.0.9-7 - Updated cursor position patch from tagoh to fix issue with "jumping" cursor when in a textfield with tabs. @@ -1740,7 +1751,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : * Wed Sep 01 2004 David Hill 0.7.3-4 - remove all Xvfb-related hacks -* Wed Sep 01 2004 Warren Togami +* Wed Sep 01 2004 Warren Togami - actually apply psfonts - add mozilla gnome-uriloader patch to prevent build failure @@ -1784,7 +1795,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : - temporary workaround for enigmail skin "modern" bug * Mon May 10 2004 David Hill 0.6-0.fdr.4 -- update to Enigmail 0.84.0 +- update to Enigmail 0.84.0 - update launch script * Mon May 10 2004 David Hill 0.6-0.fdr.3 @@ -1921,4 +1932,3 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : * Mon Sep 01 2003 David Hill - initial RPM (based on the fedora MozillaFirebird-0.6.1 specfile) - From e4e91bea579ce641148385f4922ef12b41a0baf4 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 21 Nov 2018 19:35:56 +0100 Subject: [PATCH 019/402] Backported Wayland patches from Firefox 63, fixed crashes on display changes --- firefox-wayland-crash-mozbz1507475.patch | 94 + firefox-wayland.patch | 5219 +--------------------- thunderbird.spec | 13 +- 3 files changed, 224 insertions(+), 5102 deletions(-) create mode 100644 firefox-wayland-crash-mozbz1507475.patch diff --git a/firefox-wayland-crash-mozbz1507475.patch b/firefox-wayland-crash-mozbz1507475.patch new file mode 100644 index 0000000..bab96bc --- /dev/null +++ b/firefox-wayland-crash-mozbz1507475.patch @@ -0,0 +1,94 @@ +diff -up firefox-63.0.3/widget/gtk/mozcontainer.cpp.mozbz1507475 firefox-63.0.3/widget/gtk/mozcontainer.cpp +--- firefox-63.0.3/widget/gtk/mozcontainer.cpp.mozbz1507475 2018-11-15 01:20:56.000000000 +0100 ++++ firefox-63.0.3/widget/gtk/mozcontainer.cpp 2018-11-21 15:41:41.858692640 +0100 +@@ -169,6 +169,8 @@ moz_container_class_init (MozContainerCl + } + + #if defined(MOZ_WAYLAND) ++static struct wl_subcompositor *subcompositor; ++ + static void + registry_handle_global (void *data, + struct wl_registry *registry, +@@ -176,9 +178,8 @@ registry_handle_global (void *data, + const char *interface, + uint32_t version) + { +- MozContainer *container = MOZ_CONTAINER(data); + if(strcmp(interface, "wl_subcompositor") == 0) { +- container->subcompositor = ++ subcompositor = + static_cast(wl_registry_bind(registry, + name, + &wl_subcompositor_interface, +@@ -197,6 +198,24 @@ static const struct wl_registry_listener + registry_handle_global, + registry_handle_global_remove + }; ++ ++struct wl_subcompositor* subcompositor_get(void) ++{ ++ if (!subcompositor) { ++ GdkDisplay *gdk_display = gdk_display_get_default(); ++ // Available as of GTK 3.8+ ++ static auto sGdkWaylandDisplayGetWlDisplay = ++ (wl_display *(*)(GdkDisplay *)) ++ dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display"); ++ ++ wl_display* display = sGdkWaylandDisplayGetWlDisplay(gdk_display); ++ wl_registry* registry = wl_display_get_registry(display); ++ wl_registry_add_listener(registry, ®istry_listener, nullptr); ++ wl_display_dispatch(display); ++ wl_display_roundtrip(display); ++ } ++ return subcompositor; ++} + #endif + + void +@@ -208,25 +227,10 @@ moz_container_init (MozContainer *contai + + #if defined(MOZ_WAYLAND) + { +- container->subcompositor = nullptr; + container->surface = nullptr; + container->subsurface = nullptr; + container->eglwindow = nullptr; + container->parent_surface_committed = false; +- +- GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container)); +- if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) { +- // Available as of GTK 3.8+ +- static auto sGdkWaylandDisplayGetWlDisplay = +- (wl_display *(*)(GdkDisplay *)) +- dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display"); +- +- wl_display* display = sGdkWaylandDisplayGetWlDisplay(gdk_display); +- wl_registry* registry = wl_display_get_registry(display); +- wl_registry_add_listener(registry, ®istry_listener, container); +- wl_display_dispatch(display); +- wl_display_roundtrip(display); +- } + } + #endif + } +@@ -298,7 +302,7 @@ moz_container_map_surface(MozContainer * + } + + container->subsurface = +- wl_subcompositor_get_subsurface (container->subcompositor, ++ wl_subcompositor_get_subsurface (subcompositor_get(), + container->surface, + gtk_surface); + gint x, y; +diff -up firefox-63.0.3/widget/gtk/mozcontainer.h.mozbz1507475 firefox-63.0.3/widget/gtk/mozcontainer.h +--- firefox-63.0.3/widget/gtk/mozcontainer.h.mozbz1507475 2018-11-15 01:20:56.000000000 +0100 ++++ firefox-63.0.3/widget/gtk/mozcontainer.h 2018-11-21 14:16:54.412397805 +0100 +@@ -69,7 +69,6 @@ struct _MozContainer + GList *children; + + #ifdef MOZ_WAYLAND +- struct wl_subcompositor *subcompositor; + struct wl_surface *surface; + struct wl_subsurface *subsurface; + struct wl_egl_window *eglwindow; diff --git a/firefox-wayland.patch b/firefox-wayland.patch index d5d1306..00b408c 100644 --- a/firefox-wayland.patch +++ b/firefox-wayland.patch @@ -1,523 +1,6 @@ -diff -up thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp.wayland thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp ---- thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/gtk3drawing.cpp 2018-11-20 12:04:43.731787368 +0100 -@@ -24,7 +24,7 @@ static gboolean checkbox_check_state; - static gboolean notebook_has_tab_gap; - - static ScrollbarGTKMetrics sScrollbarMetrics[2]; --static ScrollbarGTKMetrics sScrollbarMetricsActive[2]; -+static ScrollbarGTKMetrics sActiveScrollbarMetrics[2]; - static ToggleGTKMetrics sCheckboxMetrics; - static ToggleGTKMetrics sRadioMetrics; - static ToolbarGTKMetrics sToolbarMetrics; -@@ -39,6 +39,28 @@ static ToolbarGTKMetrics sToolbarMetrics - #endif - - static GtkBorder -+operator-(const GtkBorder& first, const GtkBorder& second) -+{ -+ GtkBorder result; -+ result.left = first.left - second.left; -+ result.right = first.right - second.right; -+ result.top = first.top - second.top; -+ result.bottom = first.bottom - second.bottom; -+ return result; -+} -+ -+static GtkBorder -+operator+(const GtkBorder& first, const GtkBorder& second) -+{ -+ GtkBorder result; -+ result.left = first.left + second.left; -+ result.right = first.right + second.right; -+ result.top = first.top + second.top; -+ result.bottom = first.bottom + second.bottom; -+ return result; -+} -+ -+static GtkBorder - operator+=(GtkBorder& first, const GtkBorder& second) - { - first.left += second.left; -@@ -84,7 +106,7 @@ moz_gtk_add_style_border(GtkStyleContext - { - GtkBorder border; - -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); - - *left += border.left; - *right += border.right; -@@ -98,7 +120,7 @@ moz_gtk_add_style_padding(GtkStyleContex - { - GtkBorder padding; - -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - *left += padding.left; - *right += padding.right; -@@ -193,8 +215,8 @@ moz_gtk_refresh() - - sScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; - sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; -- sScrollbarMetricsActive[GTK_ORIENTATION_HORIZONTAL].initialized = false; -- sScrollbarMetricsActive[GTK_ORIENTATION_VERTICAL].initialized = false; -+ sActiveScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; -+ sActiveScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; - sCheckboxMetrics.initialized = false; - sRadioMetrics.initialized = false; - sToolbarMetrics.initialized = false; -@@ -229,8 +251,8 @@ moz_gtk_get_focus_outline_size(GtkStyleC - { - GtkBorder border; - GtkBorder padding; -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - *focus_h_width = border.left + padding.left; - *focus_v_width = border.top + padding.top; - return MOZ_GTK_SUCCESS; -@@ -688,8 +710,8 @@ calculate_button_inner_rect(GtkWidget* b - style = gtk_widget_get_style_context(button); - - /* This mirrors gtkbutton's child positioning */ -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - inner_rect->x = rect->x + border.left + padding.left; - inner_rect->y = rect->y + padding.top + border.top; -@@ -1008,19 +1030,21 @@ moz_gtk_scrollbar_thumb_paint(WidgetNode - GtkTextDirection direction) - { - GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); -+ GtkStyleContext* style = GetStyleContext(widget, direction, state_flags); -+ -+ GtkOrientation orientation = (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ? -+ GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; - - GdkRectangle rect = *aRect; -- GtkStyleContext* style = GetStyleContext(widget, direction, state_flags); -- InsetByMargin(&rect, style); - -- gtk_render_slider(style, cr, -- rect.x, -- rect.y, -- rect.width, -- rect.height, -- (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ? -- GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); -+ const ScrollbarGTKMetrics* metrics = -+ (state->depressed || state->active || state->inHover) ? -+ GetActiveScrollbarMetrics(orientation) : -+ GetScrollbarMetrics(orientation); -+ Inset(&rect, metrics->margin.thumb); - -+ gtk_render_slider(style, cr, rect.x, rect.y, rect.width, rect.height, -+ orientation); - - return MOZ_GTK_SUCCESS; - } -@@ -1217,7 +1241,7 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRect - GtkStyleContext* style) - { - gint x = rect->x, y = rect->y, width = rect->width, height = rect->height; -- int draw_focus_outline_only = state->depressed; // NS_THEME_FOCUS_OUTLINE -+ int draw_focus_outline_only = state->depressed; // StyleAppearance::FocusOutline - - if (draw_focus_outline_only) { - // Inflate the given 'rect' with the focus outline size. -@@ -1621,7 +1645,7 @@ moz_gtk_toolbar_separator_paint(cairo_t - rect->height * (end_fraction - start_fraction)); - } else { - GtkBorder padding; -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - paint_width = padding.left; - if (paint_width > rect->width) -@@ -1790,7 +1814,7 @@ moz_gtk_get_tab_thickness(GtkStyleContex - return 0; /* tabs do not overdraw the tabpanel border with "no gap" style */ - - GtkBorder border; -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); - if (border.top < 2) - return 2; /* some themes don't set ythickness correctly */ - -@@ -2127,7 +2151,7 @@ moz_gtk_menu_separator_paint(cairo_t *cr - GtkBorder padding; - - style = GetStyleContext(MOZ_GTK_MENUSEPARATOR, direction); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - x = rect->x; - y = rect->y; -@@ -2433,7 +2457,7 @@ moz_gtk_get_widget_border(WidgetNodeType - NULL); - - if (!wide_separators) { -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), - &border); - separator_width = border.left; - } -@@ -2606,13 +2630,13 @@ moz_gtk_get_tab_border(gint* left, gint* - } else { - GtkBorder margin; - -- gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin); -+ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), &margin); - *left += margin.left; - *right += margin.right; - - if (flags & MOZ_GTK_TAB_FIRST) { - style = GetStyleContext(MOZ_GTK_NOTEBOOK_HEADER, direction); -- gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin); -+ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), &margin); - *left += margin.left; - *right += margin.right; - } -@@ -2687,7 +2711,7 @@ moz_gtk_get_toolbar_separator_width(gint - "separator-width", &separator_width, - NULL); - /* Just in case... */ -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); - *size = MAX(*size, (wide_separators ? separator_width : border.left)); - return MOZ_GTK_SUCCESS; - } -@@ -2718,7 +2742,7 @@ moz_gtk_get_menu_separator_height(gint * - gint separator_height; - GtkBorder padding; - GtkStyleContext* style = GetStyleContext(MOZ_GTK_MENUSEPARATOR); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - gtk_style_context_save(style); - gtk_style_context_add_class(style, GTK_STYLE_CLASS_SEPARATOR); -@@ -2750,8 +2774,8 @@ moz_gtk_get_entry_min_height(gint* heigh - - GtkBorder border; - GtkBorder padding; -- gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); -- gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); -+ gtk_style_context_get_border(style, gtk_style_context_get_state(style), &border); -+ gtk_style_context_get_padding(style, gtk_style_context_get_state(style), &padding); - - *height += (border.top + border.bottom + padding.top + padding.bottom); - } -@@ -2901,23 +2925,17 @@ GetToggleMetrics(bool isRadio) - return metrics; - } - --const ScrollbarGTKMetrics* --GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive) -+static void -+InitScrollbarMetrics(ScrollbarGTKMetrics* aMetrics, -+ GtkOrientation aOrientation, -+ GtkStateFlags aStateFlags) - { -- auto metrics = aActive ? &sScrollbarMetricsActive[aOrientation] : -- &sScrollbarMetrics[aOrientation]; -- if (metrics->initialized) -- return metrics; -- -- metrics->initialized = true; -- - WidgetNodeType scrollbar = aOrientation == GTK_ORIENTATION_HORIZONTAL ? - MOZ_GTK_SCROLLBAR_HORIZONTAL : MOZ_GTK_SCROLLBAR_VERTICAL; - - gboolean backward, forward, secondary_backward, secondary_forward; - GtkStyleContext* style = GetStyleContext(scrollbar, GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -+ aStateFlags); - gtk_style_context_get_style(style, - "has-backward-stepper", &backward, - "has-forward-stepper", &forward, -@@ -2938,15 +2956,15 @@ GetScrollbarMetrics(GtkOrientation aOrie - "min-slider-length", &min_slider_size, - nullptr); - -- metrics->size.thumb = -+ aMetrics->size.thumb = - SizeFromLengthAndBreadth(aOrientation, min_slider_size, slider_width); -- metrics->size.button = -+ aMetrics->size.button = - SizeFromLengthAndBreadth(aOrientation, stepper_size, slider_width); - // overall scrollbar - gint breadth = slider_width + 2 * trough_border; - // Require room for the slider in the track if we don't have buttons. - gint length = hasButtons ? 0 : min_slider_size + 2 * trough_border; -- metrics->size.scrollbar = -+ aMetrics->size.scrollbar = - SizeFromLengthAndBreadth(aOrientation, length, breadth); - - // Borders on the major axis are set on the outermost scrollbar -@@ -2956,23 +2974,24 @@ GetScrollbarMetrics(GtkOrientation aOrie - // receives mouse events, as in GTK. - // Other borders have been zero-initialized. - if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { -- metrics->border.scrollbar.left = -- metrics->border.scrollbar.right = -- metrics->border.track.top = -- metrics->border.track.bottom = trough_border; -+ aMetrics->border.scrollbar.left = -+ aMetrics->border.scrollbar.right = -+ aMetrics->border.track.top = -+ aMetrics->border.track.bottom = trough_border; - } else { -- metrics->border.scrollbar.top = -- metrics->border.scrollbar.bottom = -- metrics->border.track.left = -- metrics->border.track.right = trough_border; -+ aMetrics->border.scrollbar.top = -+ aMetrics->border.scrollbar.bottom = -+ aMetrics->border.track.left = -+ aMetrics->border.track.right = trough_border; - } - -- return metrics; -+ // We're done here for Gtk+ < 3.20... -+ return; - } - - // GTK version > 3.20 - // scrollbar -- metrics->border.scrollbar = GetMarginBorderPadding(style); -+ aMetrics->border.scrollbar = GetMarginBorderPadding(style); - - WidgetNodeType contents, track, thumb; - if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { -@@ -3003,72 +3022,102 @@ GetScrollbarMetrics(GtkOrientation aOrie - */ - - // thumb -- style = CreateStyleContextWithStates(thumb, GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -- metrics->size.thumb = GetMinMarginBox(style); -+ style = CreateStyleContextWithStates(thumb, GTK_TEXT_DIR_NONE, aStateFlags); -+ aMetrics->size.thumb = GetMinMarginBox(style); -+ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), -+ &aMetrics->margin.thumb); - g_object_unref(style); - - // track -- style = CreateStyleContextWithStates(track, GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -- metrics->border.track = GetMarginBorderPadding(style); -- MozGtkSize trackMinSize = GetMinContentBox(style) + metrics->border.track; -- MozGtkSize trackSizeForThumb = metrics->size.thumb + metrics->border.track; -+ style = CreateStyleContextWithStates(track, GTK_TEXT_DIR_NONE, aStateFlags); -+ aMetrics->border.track = GetMarginBorderPadding(style); -+ MozGtkSize trackMinSize = GetMinContentBox(style) + aMetrics->border.track; -+ MozGtkSize trackSizeForThumb = aMetrics->size.thumb + aMetrics->border.track; - g_object_unref(style); - - // button - if (hasButtons) { - style = CreateStyleContextWithStates(MOZ_GTK_SCROLLBAR_BUTTON, -- GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -- metrics->size.button = GetMinMarginBox(style); -+ GTK_TEXT_DIR_NONE, aStateFlags); -+ aMetrics->size.button = GetMinMarginBox(style); - g_object_unref(style); - } else { -- metrics->size.button = {0, 0}; -+ aMetrics->size.button = {0, 0}; - } - if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { -- metrics->size.button.Rotate(); -+ aMetrics->size.button.Rotate(); - // If the track is wider than necessary for the thumb, including when - // the buttons will cause Gecko to expand the track to fill - // available breadth, then add to the track border to prevent Gecko - // from expanding the thumb to fill available breadth. - gint extra = - std::max(trackMinSize.height, -- metrics->size.button.height) - trackSizeForThumb.height; -+ aMetrics->size.button.height) - trackSizeForThumb.height; - if (extra > 0) { - // If extra is odd, then the thumb is 0.5 pixels above - // center as in gtk_range_compute_slider_position(). -- metrics->border.track.top += extra / 2; -- metrics->border.track.bottom += extra - extra / 2; -+ aMetrics->border.track.top += extra / 2; -+ aMetrics->border.track.bottom += extra - extra / 2; - // Update size for change in border. - trackSizeForThumb.height += extra; - } - } else { - gint extra = - std::max(trackMinSize.width, -- metrics->size.button.width) - trackSizeForThumb.width; -+ aMetrics->size.button.width) - trackSizeForThumb.width; - if (extra > 0) { - // If extra is odd, then the thumb is 0.5 pixels to the left - // of center as in gtk_range_compute_slider_position(). -- metrics->border.track.left += extra / 2; -- metrics->border.track.right += extra - extra / 2; -+ aMetrics->border.track.left += extra / 2; -+ aMetrics->border.track.right += extra - extra / 2; - trackSizeForThumb.width += extra; - } - } - - style = CreateStyleContextWithStates(contents, GTK_TEXT_DIR_NONE, -- aActive ? GTK_STATE_FLAG_PRELIGHT : -- GTK_STATE_FLAG_NORMAL); -+ aStateFlags); - GtkBorder contentsBorder = GetMarginBorderPadding(style); - g_object_unref(style); - -- metrics->size.scrollbar = -- trackSizeForThumb + contentsBorder + metrics->border.scrollbar; -+ aMetrics->size.scrollbar = -+ trackSizeForThumb + contentsBorder + aMetrics->border.scrollbar; -+} -+ -+const ScrollbarGTKMetrics* -+GetScrollbarMetrics(GtkOrientation aOrientation) -+{ -+ auto metrics = &sScrollbarMetrics[aOrientation]; -+ if (!metrics->initialized) { -+ InitScrollbarMetrics(metrics, aOrientation, GTK_STATE_FLAG_NORMAL); -+ -+ // We calculate thumb margin here because it's composited from -+ // thumb class margin + difference margin between active and inactive -+ // scrollbars. It's a workaround which alows us to emulate -+ // overlay scrollbars for some Gtk+ themes (Ubuntu/Ambiance), -+ // when an inactive scrollbar thumb is smaller than the active one. -+ const ScrollbarGTKMetrics *metricsActive = -+ GetActiveScrollbarMetrics(aOrientation); -+ -+ if (metrics->size.thumb < metricsActive->size.thumb) { -+ metrics->margin.thumb += -+ (metrics->border.scrollbar + metrics->border.track) - -+ (metricsActive->border.scrollbar + metricsActive->border.track); -+ } - -- return metrics; -+ metrics->initialized = true; -+ } -+ return metrics; -+} -+ -+const ScrollbarGTKMetrics* -+GetActiveScrollbarMetrics(GtkOrientation aOrientation) -+{ -+ auto metrics = &sActiveScrollbarMetrics[aOrientation]; -+ if (!metrics->initialized) { -+ InitScrollbarMetrics(metrics, aOrientation, GTK_STATE_FLAG_PRELIGHT); -+ metrics->initialized = true; -+ } -+ return metrics; - } - - /* -@@ -3078,6 +3127,16 @@ GetScrollbarMetrics(GtkOrientation aOrie - bool - GetCSDDecorationSize(GtkWindow *aGtkWindow, GtkBorder* aDecorationSize) - { -+ // Available on GTK 3.20+. -+ static auto sGtkRenderBackgroundGetClip = -+ (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*)) -+ dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip"); -+ -+ if (!sGtkRenderBackgroundGetClip) { -+ *aDecorationSize = {0,0,0,0}; -+ return false; -+ } -+ - GtkStyleContext* context = gtk_widget_get_style_context(GTK_WIDGET(aGtkWindow)); - bool solidDecorations = gtk_style_context_has_class(context, "solid-csd"); - context = GetStyleContext(solidDecorations ? -@@ -3091,54 +3150,32 @@ GetCSDDecorationSize(GtkWindow *aGtkWind - gtk_style_context_get_padding(context, state, &padding); - *aDecorationSize += padding; - -- // Available on GTK 3.20+. -- static auto sGtkRenderBackgroundGetClip = -- (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*)) -- dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip"); - - GtkBorder margin; - gtk_style_context_get_margin(context, state, &margin); - -- GtkBorder extents = {0, 0, 0, 0}; -- if (sGtkRenderBackgroundGetClip) { -- /* Get shadow extents but combine with style margin; use the bigger value. -- */ -- GdkRectangle clip; -- sGtkRenderBackgroundGetClip(context, 0, 0, 0, 0, &clip); -- -- extents.top = -clip.y; -- extents.right = clip.width + clip.x; -- extents.bottom = clip.height + clip.y; -- extents.left = -clip.x; -- -- // Margin is used for resize grip size - it's not present on -- // popup windows. -- if (gtk_window_get_window_type(aGtkWindow) != GTK_WINDOW_POPUP) { -- extents.top = MAX(extents.top, margin.top); -- extents.right = MAX(extents.right, margin.right); -- extents.bottom = MAX(extents.bottom, margin.bottom); -- extents.left = MAX(extents.left, margin.left); -- } -- } else { -- /* If we can't get shadow extents use decoration-resize-handle instead -- * as a workaround. This is inspired by update_border_windows() -- * from gtkwindow.c although this is not 100% accurate as we emulate -- * the extents here. -- */ -- gint handle; -- gtk_widget_style_get(GetWidget(MOZ_GTK_WINDOW), -- "decoration-resize-handle", &handle, -- NULL); -- -- extents.top = handle + margin.top; -- extents.right = handle + margin.right; -- extents.bottom = handle + margin.bottom; -- extents.left = handle + margin.left; -+ /* Get shadow extents but combine with style margin; use the bigger value. -+ */ -+ GdkRectangle clip; -+ sGtkRenderBackgroundGetClip(context, 0, 0, 0, 0, &clip); -+ -+ GtkBorder extents; -+ extents.top = -clip.y; -+ extents.right = clip.width + clip.x; -+ extents.bottom = clip.height + clip.y; -+ extents.left = -clip.x; -+ -+ // Margin is used for resize grip size - it's not present on -+ // popup windows. -+ if (gtk_window_get_window_type(aGtkWindow) != GTK_WINDOW_POPUP) { -+ extents.top = MAX(extents.top, margin.top); -+ extents.right = MAX(extents.right, margin.right); -+ extents.bottom = MAX(extents.bottom, margin.bottom); -+ extents.left = MAX(extents.left, margin.left); - } - - *aDecorationSize += extents; -- -- return (sGtkRenderBackgroundGetClip != nullptr); -+ return true; - } - - /* cairo_t *cr argument has to be a system-cairo. */ diff -up thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp.wayland thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp --- thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp 2018-11-20 12:04:43.731787368 +0100 ++++ thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp 2018-11-21 13:42:00.757025666 +0100 @@ -40,7 +40,9 @@ GtkCompositorWidget::GtkCompositorWidget // Grab the window's visual and depth @@ -529,1438 +12,19 @@ diff -up thunderbird-60.3.0/widget/gtk/GtkCompositorWidget.cpp.wayland thunderbi Visual* visual = windowAttrs.visual; int depth = windowAttrs.depth; -@@ -50,8 +52,8 @@ GtkCompositorWidget::GtkCompositorWidget +@@ -50,8 +52,7 @@ GtkCompositorWidget::GtkCompositorWidget mXDisplay, mXWindow, visual, - depth - ); -+ depth, -+ aInitData.Shaped()); ++ depth); } mClientSize = aInitData.InitialClientSize(); } -diff -up thunderbird-60.3.0/widget/gtk/gtkdrawing.h.wayland thunderbird-60.3.0/widget/gtk/gtkdrawing.h ---- thunderbird-60.3.0/widget/gtk/gtkdrawing.h.wayland 2018-10-30 12:45:37.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/gtkdrawing.h 2018-11-20 12:04:43.731787368 +0100 -@@ -83,6 +83,9 @@ typedef struct { - GtkBorder scrollbar; - GtkBorder track; - } border; -+ struct { -+ GtkBorder thumb; -+ } margin; - } ScrollbarGTKMetrics; - - typedef struct { -@@ -502,11 +505,17 @@ moz_gtk_get_scalethumb_metrics(GtkOrient - /** - * Get the metrics in GTK pixels for a scrollbar. - * aOrientation: [IN] the scrollbar orientation -- * aActive: [IN] Metricts for scrollbar with mouse pointer over it. -- * - */ - const ScrollbarGTKMetrics* --GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive = false); -+GetScrollbarMetrics(GtkOrientation aOrientation); -+ -+/** -+ * Get the metrics in GTK pixels for a scrollbar which is active -+ * (selected by mouse pointer). -+ * aOrientation: [IN] the scrollbar orientation -+ */ -+const ScrollbarGTKMetrics* -+GetActiveScrollbarMetrics(GtkOrientation aOrientation); - - /** - * Get the desired size of a dropdown arrow button -diff -up thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp.wayland thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp ---- thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/IMContextWrapper.cpp 2018-11-20 12:04:43.732787365 +0100 -@@ -14,6 +14,7 @@ - #include "mozilla/Likely.h" - #include "mozilla/MiscEvents.h" - #include "mozilla/Preferences.h" -+#include "mozilla/Telemetry.h" - #include "mozilla/TextEventDispatcher.h" - #include "mozilla/TextEvents.h" - #include "WritingModes.h" -@@ -59,6 +60,73 @@ GetEventType(GdkEventKey* aKeyEvent) - } - } - -+class GetEventStateName : public nsAutoCString -+{ -+public: -+ explicit GetEventStateName(guint aState, -+ IMContextWrapper::IMContextID aIMContextID = -+ IMContextWrapper::IMContextID::eUnknown) -+ { -+ if (aState & GDK_SHIFT_MASK) { -+ AppendModifier("shift"); -+ } -+ if (aState & GDK_CONTROL_MASK) { -+ AppendModifier("control"); -+ } -+ if (aState & GDK_MOD1_MASK) { -+ AppendModifier("mod1"); -+ } -+ if (aState & GDK_MOD2_MASK) { -+ AppendModifier("mod2"); -+ } -+ if (aState & GDK_MOD3_MASK) { -+ AppendModifier("mod3"); -+ } -+ if (aState & GDK_MOD4_MASK) { -+ AppendModifier("mod4"); -+ } -+ if (aState & GDK_MOD4_MASK) { -+ AppendModifier("mod5"); -+ } -+ if (aState & GDK_MOD4_MASK) { -+ AppendModifier("mod5"); -+ } -+ switch (aIMContextID) { -+ case IMContextWrapper::IMContextID::eIBus: -+ static const guint IBUS_HANDLED_MASK = 1 << 24; -+ static const guint IBUS_IGNORED_MASK = 1 << 25; -+ if (aState & IBUS_HANDLED_MASK) { -+ AppendModifier("IBUS_HANDLED_MASK"); -+ } -+ if (aState & IBUS_IGNORED_MASK) { -+ AppendModifier("IBUS_IGNORED_MASK"); -+ } -+ break; -+ case IMContextWrapper::IMContextID::eFcitx: -+ static const guint FcitxKeyState_HandledMask = 1 << 24; -+ static const guint FcitxKeyState_IgnoredMask = 1 << 25; -+ if (aState & FcitxKeyState_HandledMask) { -+ AppendModifier("FcitxKeyState_HandledMask"); -+ } -+ if (aState & FcitxKeyState_IgnoredMask) { -+ AppendModifier("FcitxKeyState_IgnoredMask"); -+ } -+ break; -+ default: -+ break; -+ } -+ } -+ -+private: -+ void AppendModifier(const char* aModifierName) -+ { -+ if (!IsEmpty()) { -+ AppendLiteral(" + "); -+ } -+ Append(aModifierName); -+ } -+}; -+ - class GetWritingModeName : public nsAutoCString - { - public: -@@ -281,12 +349,17 @@ IMContextWrapper::IMContextWrapper(nsWin - , mCompositionStart(UINT32_MAX) - , mProcessingKeyEvent(nullptr) - , mCompositionState(eCompositionState_NotComposing) -+ , mIMContextID(IMContextID::eUnknown) - , mIsIMFocused(false) -+ , mFallbackToKeyEvent(false) -+ , mKeyboardEventWasDispatched(false) - , mIsDeletingSurrounding(false) - , mLayoutChanged(false) - , mSetCursorPositionOnKeyEvent(true) - , mPendingResettingIMContext(false) - , mRetrieveSurroundingSignalReceived(false) -+ , mMaybeInDeadKeySequence(false) -+ , mIsIMInAsyncKeyHandlingMode(false) - { - static bool sFirstInstance = true; - if (sFirstInstance) { -@@ -299,15 +372,101 @@ IMContextWrapper::IMContextWrapper(nsWin - Init(); - } - -+static bool -+IsIBusInSyncMode() -+{ -+ // See ibus_im_context_class_init() in client/gtk2/ibusimcontext.c -+ // https://github.com/ibus/ibus/blob/86963f2f94d1e4fc213b01c2bc2ba9dcf4b22219/client/gtk2/ibusimcontext.c#L610 -+ const char* env = PR_GetEnv("IBUS_ENABLE_SYNC_MODE"); -+ -+ // See _get_boolean_env() in client/gtk2/ibusimcontext.c -+ // https://github.com/ibus/ibus/blob/86963f2f94d1e4fc213b01c2bc2ba9dcf4b22219/client/gtk2/ibusimcontext.c#L520-L537 -+ if (!env) { -+ return false; -+ } -+ nsDependentCString envStr(env); -+ if (envStr.IsEmpty() || -+ envStr.EqualsLiteral("0") || -+ envStr.EqualsLiteral("false") || -+ envStr.EqualsLiteral("False") || -+ envStr.EqualsLiteral("FALSE")) { -+ return false; -+ } -+ return true; -+} -+ -+static bool -+GetFcitxBoolEnv(const char* aEnv) -+{ -+ // See fcitx_utils_get_boolean_env in src/lib/fcitx-utils/utils.c -+ // https://github.com/fcitx/fcitx/blob/0c87840dc7d9460c2cb5feaeefec299d0d3d62ec/src/lib/fcitx-utils/utils.c#L721-L736 -+ const char* env = PR_GetEnv(aEnv); -+ if (!env) { -+ return false; -+ } -+ nsDependentCString envStr(env); -+ if (envStr.IsEmpty() || -+ envStr.EqualsLiteral("0") || -+ envStr.EqualsLiteral("false")) { -+ return false; -+ } -+ return true; -+} -+ -+static bool -+IsFcitxInSyncMode() -+{ -+ // See fcitx_im_context_class_init() in src/frontend/gtk2/fcitximcontext.c -+ // https://github.com/fcitx/fcitx/blob/78b98d9230dc9630e99d52e3172bdf440ffd08c4/src/frontend/gtk2/fcitximcontext.c#L395-L398 -+ return GetFcitxBoolEnv("IBUS_ENABLE_SYNC_MODE") || -+ GetFcitxBoolEnv("FCITX_ENABLE_SYNC_MODE"); -+} -+ -+nsDependentCSubstring -+IMContextWrapper::GetIMName() const -+{ -+ const char* contextIDChar = -+ gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(mContext)); -+ if (!contextIDChar) { -+ return nsDependentCSubstring(); -+ } -+ -+ nsDependentCSubstring im(contextIDChar, strlen(contextIDChar)); -+ -+ // If the context is XIM, actual engine must be specified with -+ // |XMODIFIERS=@im=foo|. -+ const char* xmodifiersChar = PR_GetEnv("XMODIFIERS"); -+ if (!im.EqualsLiteral("xim") || !xmodifiersChar) { -+ return im; -+ } -+ -+ nsDependentCString xmodifiers(xmodifiersChar); -+ int32_t atIMValueStart = xmodifiers.Find("@im=") + 4; -+ if (atIMValueStart < 4 || -+ xmodifiers.Length() <= static_cast(atIMValueStart)) { -+ return im; -+ } -+ -+ int32_t atIMValueEnd = -+ xmodifiers.Find("@", false, atIMValueStart); -+ if (atIMValueEnd > atIMValueStart) { -+ return nsDependentCSubstring(xmodifiersChar + atIMValueStart, -+ atIMValueEnd - atIMValueStart); -+ } -+ -+ if (atIMValueEnd == kNotFound) { -+ return nsDependentCSubstring(xmodifiersChar + atIMValueStart, -+ strlen(xmodifiersChar) - atIMValueStart); -+ } -+ -+ return im; -+} -+ - void - IMContextWrapper::Init() - { -- MOZ_LOG(gGtkIMLog, LogLevel::Info, -- ("0x%p Init(), mOwnerWindow=0x%p", -- this, mOwnerWindow)); -- - MozContainer* container = mOwnerWindow->GetMozContainer(); -- NS_PRECONDITION(container, "container is null"); -+ MOZ_ASSERT(container, "container is null"); - GdkWindow* gdkWindow = gtk_widget_get_window(GTK_WIDGET(container)); - - // Overwrite selection colors of the window before associating the window -@@ -333,6 +492,47 @@ IMContextWrapper::Init() - G_CALLBACK(IMContextWrapper::OnStartCompositionCallback), this); - g_signal_connect(mContext, "preedit_end", - G_CALLBACK(IMContextWrapper::OnEndCompositionCallback), this); -+ nsDependentCSubstring im = GetIMName(); -+ if (im.EqualsLiteral("ibus")) { -+ mIMContextID = IMContextID::eIBus; -+ mIsIMInAsyncKeyHandlingMode = !IsIBusInSyncMode(); -+ // Although ibus has key snooper mode, it's forcibly disabled on Firefox -+ // in default settings by its whitelist since we always send key events -+ // to IME before handling shortcut keys. The whitelist can be -+ // customized with env, IBUS_NO_SNOOPER_APPS, but we don't need to -+ // support such rare cases for reducing maintenance cost. -+ mIsKeySnooped = false; -+ } else if (im.EqualsLiteral("fcitx")) { -+ mIMContextID = IMContextID::eFcitx; -+ mIsIMInAsyncKeyHandlingMode = !IsFcitxInSyncMode(); -+ // Although Fcitx has key snooper mode similar to ibus, it's also -+ // disabled on Firefox in default settings by its whitelist. The -+ // whitelist can be customized with env, IBUS_NO_SNOOPER_APPS or -+ // FCITX_NO_SNOOPER_APPS, but we don't need to support such rare cases -+ // for reducing maintenance cost. -+ mIsKeySnooped = false; -+ } else if (im.EqualsLiteral("uim")) { -+ mIMContextID = IMContextID::eUim; -+ mIsIMInAsyncKeyHandlingMode = false; -+ // We cannot know if uim uses key snooper since it's build option of -+ // uim. Therefore, we need to retrieve the consideration from the -+ // pref for making users and distributions allowed to choose their -+ // preferred value. -+ mIsKeySnooped = -+ Preferences::GetBool("intl.ime.hack.uim.using_key_snooper", true); -+ } else if (im.EqualsLiteral("scim")) { -+ mIMContextID = IMContextID::eScim; -+ mIsIMInAsyncKeyHandlingMode = false; -+ mIsKeySnooped = false; -+ } else if (im.EqualsLiteral("iiim")) { -+ mIMContextID = IMContextID::eIIIMF; -+ mIsIMInAsyncKeyHandlingMode = false; -+ mIsKeySnooped = false; -+ } else { -+ mIMContextID = IMContextID::eUnknown; -+ mIsIMInAsyncKeyHandlingMode = false; -+ mIsKeySnooped = false; -+ } - - // Simple context - if (sUseSimpleContext) { -@@ -361,6 +561,18 @@ IMContextWrapper::Init() - // Dummy context - mDummyContext = gtk_im_multicontext_new(); - gtk_im_context_set_client_window(mDummyContext, gdkWindow); -+ -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p Init(), mOwnerWindow=%p, mContext=%p (im=\"%s\"), " -+ "mIsIMInAsyncKeyHandlingMode=%s, mIsKeySnooped=%s, " -+ "mSimpleContext=%p, mDummyContext=%p, " -+ "gtk_im_multicontext_get_context_id()=\"%s\", " -+ "PR_GetEnv(\"XMODIFIERS\")=\"%s\"", -+ this, mOwnerWindow, mContext, nsAutoCString(im).get(), -+ ToChar(mIsIMInAsyncKeyHandlingMode), ToChar(mIsKeySnooped), -+ mSimpleContext, mDummyContext, -+ gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(mContext)), -+ PR_GetEnv("XMODIFIERS"))); - } - - /* static */ -@@ -469,7 +681,7 @@ IMContextWrapper::OnDestroyWindow(nsWind - "mOwnerWindow=0x%p, mLastFocusedModule=0x%p", - this, aWindow, mLastFocusedWindow, mOwnerWindow, sLastFocusedContext)); - -- NS_PRECONDITION(aWindow, "aWindow must not be null"); -+ MOZ_ASSERT(aWindow, "aWindow must not be null"); - - if (mLastFocusedWindow == aWindow) { - EndIMEComposition(aWindow); -@@ -524,46 +736,46 @@ IMContextWrapper::OnDestroyWindow(nsWind - mOwnerWindow = nullptr; - mLastFocusedWindow = nullptr; - mInputContext.mIMEState.mEnabled = IMEState::DISABLED; -+ mPostingKeyEvents.Clear(); - - MOZ_LOG(gGtkIMLog, LogLevel::Debug, - ("0x%p OnDestroyWindow(), succeeded, Completely destroyed", - this)); - } - --// Work around gtk bug http://bugzilla.gnome.org/show_bug.cgi?id=483223: --// (and the similar issue of GTK+ IIIM) --// The GTK+ XIM and IIIM modules register handlers for the "closed" signal --// on the display, but: --// * The signal handlers are not disconnected when the module is unloaded. --// --// The GTK+ XIM module has another problem: --// * When the signal handler is run (with the module loaded) it tries --// XFree (and fails) on a pointer that did not come from Xmalloc. --// --// To prevent these modules from being unloaded, use static variables to --// hold ref of GtkIMContext class. --// For GTK+ XIM module, to prevent the signal handler from being run, --// find the signal handlers and remove them. --// --// GtkIMContextXIMs share XOpenIM connections and display closed signal --// handlers (where possible). -- - void - IMContextWrapper::PrepareToDestroyContext(GtkIMContext* aContext) - { -- GtkIMContext *slave = nullptr; //TODO GTK3 -- if (!slave) { -- return; -- } -- -- GType slaveType = G_TYPE_FROM_INSTANCE(slave); -- const gchar *im_type_name = g_type_name(slaveType); -- if (strcmp(im_type_name, "GtkIMContextIIIM") == 0) { -- // Add a reference to prevent the IIIM module from being unloaded -- static gpointer gtk_iiim_context_class = -- g_type_class_ref(slaveType); -- // Mute unused variable warning: -- (void)gtk_iiim_context_class; -+ if (mIMContextID == IMContextID::eIIIMF) { -+ // IIIM module registers handlers for the "closed" signal on the -+ // display, but the signal handler is not disconnected when the module -+ // is unloaded. To prevent the module from being unloaded, use static -+ // variable to hold reference of slave context class declared by IIIM. -+ // Note that this does not grab any instance, it grabs the "class". -+ static gpointer sGtkIIIMContextClass = nullptr; -+ if (!sGtkIIIMContextClass) { -+ // We retrieved slave context class with g_type_name() and actual -+ // slave context instance when our widget was GTK2. That must be -+ // _GtkIMContext::priv::slave in GTK3. However, _GtkIMContext::priv -+ // is an opacity struct named _GtkIMMulticontextPrivate, i.e., it's -+ // not exposed by GTK3. Therefore, we cannot access the instance -+ // safely. So, we need to retrieve the slave context class with -+ // g_type_from_name("GtkIMContextIIIM") directly (anyway, we needed -+ // to compare the class name with "GtkIMContextIIIM"). -+ GType IIMContextType = g_type_from_name("GtkIMContextIIIM"); -+ if (IIMContextType) { -+ sGtkIIIMContextClass = g_type_class_ref(IIMContextType); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p PrepareToDestroyContext(), added to reference to " -+ "GtkIMContextIIIM class to prevent it from being unloaded", -+ this)); -+ } else { -+ MOZ_LOG(gGtkIMLog, LogLevel::Error, -+ ("0x%p PrepareToDestroyContext(), FAILED to prevent the " -+ "IIIM module from being uploaded", -+ this)); -+ } -+ } - } - } - -@@ -603,9 +815,9 @@ IMContextWrapper::OnBlurWindow(nsWindow* - bool - IMContextWrapper::OnKeyEvent(nsWindow* aCaller, - GdkEventKey* aEvent, -- bool aKeyDownEventWasSent /* = false */) -+ bool aKeyboardEventWasDispatched /* = false */) - { -- NS_PRECONDITION(aEvent, "aEvent must be non-null"); -+ MOZ_ASSERT(aEvent, "aEvent must be non-null"); - - if (!mInputContext.mIMEState.MaybeEditable() || - MOZ_UNLIKELY(IsDestroyed())) { -@@ -613,13 +825,24 @@ IMContextWrapper::OnKeyEvent(nsWindow* a - } - - MOZ_LOG(gGtkIMLog, LogLevel::Info, -- ("0x%p OnKeyEvent(aCaller=0x%p, aKeyDownEventWasSent=%s), " -- "mCompositionState=%s, current context=0x%p, active context=0x%p, " -- "aEvent(0x%p): { type=%s, keyval=%s, unicode=0x%X }", -- this, aCaller, ToChar(aKeyDownEventWasSent), -+ ("0x%p OnKeyEvent(aCaller=0x%p, " -+ "aEvent(0x%p): { type=%s, keyval=%s, unicode=0x%X, state=%s, " -+ "time=%u, hardware_keycode=%u, group=%u }, " -+ "aKeyboardEventWasDispatched=%s)", -+ this, aCaller, aEvent, GetEventType(aEvent), -+ gdk_keyval_name(aEvent->keyval), -+ gdk_keyval_to_unicode(aEvent->keyval), -+ GetEventStateName(aEvent->state, mIMContextID).get(), -+ aEvent->time, aEvent->hardware_keycode, aEvent->group, -+ ToChar(aKeyboardEventWasDispatched))); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnKeyEvent(), mMaybeInDeadKeySequence=%s, " -+ "mCompositionState=%s, current context=%p, active context=%p, " -+ "mIMContextID=%s, mIsIMInAsyncKeyHandlingMode=%s", -+ this, ToChar(mMaybeInDeadKeySequence), - GetCompositionStateName(), GetCurrentContext(), GetActiveContext(), -- aEvent, GetEventType(aEvent), gdk_keyval_name(aEvent->keyval), -- gdk_keyval_to_unicode(aEvent->keyval))); -+ GetIMContextIDName(mIMContextID), -+ ToChar(mIsIMInAsyncKeyHandlingMode))); - - if (aCaller != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Error, -@@ -644,49 +867,158 @@ IMContextWrapper::OnKeyEvent(nsWindow* a - mSetCursorPositionOnKeyEvent = false; - } - -- mKeyDownEventWasSent = aKeyDownEventWasSent; -- mFilterKeyEvent = true; -+ // Let's support dead key event even if active keyboard layout also -+ // supports complicated composition like CJK IME. -+ bool isDeadKey = -+ KeymapWrapper::ComputeDOMKeyNameIndex(aEvent) == KEY_NAME_INDEX_Dead; -+ mMaybeInDeadKeySequence |= isDeadKey; -+ -+ // If current context is mSimpleContext, both ibus and fcitx handles key -+ // events synchronously. So, only when current context is mContext which -+ // is GtkIMMulticontext, the key event may be handled by IME asynchronously. -+ bool maybeHandledAsynchronously = -+ mIsIMInAsyncKeyHandlingMode && currentContext == mContext; -+ -+ // If IM is ibus or fcitx and it handles key events asynchronously, -+ // they mark aEvent->state as "handled by me" when they post key event -+ // to another process. Unfortunately, we need to check this hacky -+ // flag because it's difficult to store all pending key events by -+ // an array or a hashtable. -+ if (maybeHandledAsynchronously) { -+ switch (mIMContextID) { -+ case IMContextID::eIBus: -+ // ibus won't send back key press events in a dead key sequcne. -+ if (mMaybeInDeadKeySequence && aEvent->type == GDK_KEY_PRESS) { -+ maybeHandledAsynchronously = false; -+ break; -+ } -+ // ibus handles key events synchronously if focused editor is -+ // or |ime-mode: disabled;|. -+ if (mInputContext.mIMEState.mEnabled == IMEState::PASSWORD) { -+ maybeHandledAsynchronously = false; -+ break; -+ } -+ // See src/ibustypes.h -+ static const guint IBUS_IGNORED_MASK = 1 << 25; -+ // If IBUS_IGNORED_MASK was set to aEvent->state, the event -+ // has already been handled by another process and it wasn't -+ // used by IME. -+ if (aEvent->state & IBUS_IGNORED_MASK) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnKeyEvent(), aEvent->state has " -+ "IBUS_IGNORED_MASK, so, it won't be handled " -+ "asynchronously anymore. Removing posted events from " -+ "the queue", -+ this)); -+ maybeHandledAsynchronously = false; -+ mPostingKeyEvents.RemoveEvent(aEvent); -+ break; -+ } -+ break; -+ case IMContextID::eFcitx: -+ // fcitx won't send back key press events in a dead key sequcne. -+ if (mMaybeInDeadKeySequence && aEvent->type == GDK_KEY_PRESS) { -+ maybeHandledAsynchronously = false; -+ break; -+ } -+ -+ // fcitx handles key events asynchronously even if focused -+ // editor cannot use IME actually. -+ -+ // See src/lib/fcitx-utils/keysym.h -+ static const guint FcitxKeyState_IgnoredMask = 1 << 25; -+ // If FcitxKeyState_IgnoredMask was set to aEvent->state, -+ // the event has already been handled by another process and -+ // it wasn't used by IME. -+ if (aEvent->state & FcitxKeyState_IgnoredMask) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnKeyEvent(), aEvent->state has " -+ "FcitxKeyState_IgnoredMask, so, it won't be handled " -+ "asynchronously anymore. Removing posted events from " -+ "the queue", -+ this)); -+ maybeHandledAsynchronously = false; -+ mPostingKeyEvents.RemoveEvent(aEvent); -+ break; -+ } -+ break; -+ default: -+ MOZ_ASSERT_UNREACHABLE("IME may handle key event " -+ "asyncrhonously, but not yet confirmed if it comes agian " -+ "actually"); -+ } -+ } -+ -+ mKeyboardEventWasDispatched = aKeyboardEventWasDispatched; -+ mFallbackToKeyEvent = false; - mProcessingKeyEvent = aEvent; - gboolean isFiltered = - gtk_im_context_filter_keypress(currentContext, aEvent); -- mProcessingKeyEvent = nullptr; - -- // We filter the key event if the event was not committed (because -- // it's probably part of a composition) or if the key event was -- // committed _and_ changed. This way we still let key press -- // events go through as simple key press events instead of -- // composed characters. -- bool filterThisEvent = isFiltered && mFilterKeyEvent; -- -- if (IsComposingOnCurrentContext() && !isFiltered) { -- if (aEvent->type == GDK_KEY_PRESS) { -- if (!mDispatchedCompositionString.IsEmpty()) { -- // If there is composition string, we shouldn't dispatch -- // any keydown events during composition. -- filterThisEvent = true; -- } else { -- // A Hangul input engine for SCIM doesn't emit preedit_end -- // signal even when composition string becomes empty. On the -- // other hand, we should allow to make composition with empty -- // string for other languages because there *might* be such -- // IM. For compromising this issue, we should dispatch -- // compositionend event, however, we don't need to reset IM -- // actually. -- DispatchCompositionCommitEvent(currentContext, &EmptyString()); -- filterThisEvent = false; -- } -- } else { -- // Key release event may not be consumed by IM, however, we -- // shouldn't dispatch any keyup event during composition. -- filterThisEvent = true; -+ // The caller of this shouldn't handle aEvent anymore if we've dispatched -+ // composition events or modified content with other events. -+ bool filterThisEvent = isFiltered && !mFallbackToKeyEvent; -+ -+ if (IsComposingOnCurrentContext() && !isFiltered && -+ aEvent->type == GDK_KEY_PRESS && -+ mDispatchedCompositionString.IsEmpty()) { -+ // A Hangul input engine for SCIM doesn't emit preedit_end -+ // signal even when composition string becomes empty. On the -+ // other hand, we should allow to make composition with empty -+ // string for other languages because there *might* be such -+ // IM. For compromising this issue, we should dispatch -+ // compositionend event, however, we don't need to reset IM -+ // actually. -+ // NOTE: Don't dispatch key events as "processed by IME" since -+ // we need to dispatch keyboard events as IME wasn't handled it. -+ mProcessingKeyEvent = nullptr; -+ DispatchCompositionCommitEvent(currentContext, &EmptyString()); -+ mProcessingKeyEvent = aEvent; -+ // In this case, even though we handle the keyboard event here, -+ // but we should dispatch keydown event as -+ filterThisEvent = false; -+ } -+ -+ if (filterThisEvent && !mKeyboardEventWasDispatched) { -+ // If IME handled the key event but we've not dispatched eKeyDown nor -+ // eKeyUp event yet, we need to dispatch here unless the key event is -+ // now being handled by other IME process. -+ if (!maybeHandledAsynchronously) { -+ MaybeDispatchKeyEventAsProcessedByIME(eVoidEvent); -+ // Be aware, the widget might have been gone here. -+ } -+ // If we need to wait reply from IM, IM may send some signals to us -+ // without sending the key event again. In such case, we need to -+ // dispatch keyboard events with a copy of aEvent. Therefore, we -+ // need to use information of this key event to dispatch an KeyDown -+ // or eKeyUp event later. -+ else { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnKeyEvent(), putting aEvent into the queue...", -+ this)); -+ mPostingKeyEvents.PutEvent(aEvent); - } - } - -+ mProcessingKeyEvent = nullptr; -+ -+ if (aEvent->type == GDK_KEY_PRESS && !filterThisEvent) { -+ // If the key event hasn't been handled by active IME nor keyboard -+ // layout, we can assume that the dead key sequence has been or was -+ // ended. Note that we should not reset it when the key event is -+ // GDK_KEY_RELEASE since it may not be filtered by active keyboard -+ // layout even in composition. -+ mMaybeInDeadKeySequence = false; -+ } -+ - MOZ_LOG(gGtkIMLog, LogLevel::Debug, - ("0x%p OnKeyEvent(), succeeded, filterThisEvent=%s " -- "(isFiltered=%s, mFilterKeyEvent=%s), mCompositionState=%s", -+ "(isFiltered=%s, mFallbackToKeyEvent=%s, " -+ "maybeHandledAsynchronously=%s), mCompositionState=%s, " -+ "mMaybeInDeadKeySequence=%s", - this, ToChar(filterThisEvent), ToChar(isFiltered), -- ToChar(mFilterKeyEvent), GetCompositionStateName())); -+ ToChar(mFallbackToKeyEvent), ToChar(maybeHandledAsynchronously), -+ GetCompositionStateName(), ToChar(mMaybeInDeadKeySequence))); - - return filterThisEvent; - } -@@ -1005,6 +1337,10 @@ IMContextWrapper::Focus() - - sLastFocusedContext = this; - -+ // Forget all posted key events when focus is moved since they shouldn't -+ // be fired in different editor. -+ mPostingKeyEvents.Clear(); -+ - gtk_im_context_focus_in(currentContext); - mIsIMFocused = true; - mSetCursorPositionOnKeyEvent = true; -@@ -1400,6 +1736,7 @@ IMContextWrapper::OnCommitCompositionNat - { - const gchar emptyStr = 0; - const gchar *commitString = aUTF8Char ? aUTF8Char : &emptyStr; -+ NS_ConvertUTF8toUTF16 utf16CommitString(commitString); - - MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("0x%p OnCommitCompositionNative(aContext=0x%p), " -@@ -1422,7 +1759,7 @@ IMContextWrapper::OnCommitCompositionNat - // signal, we would dispatch compositionstart, text, compositionend - // events with empty string. Of course, they are unnecessary events - // for Web applications and our editor. -- if (!IsComposingOn(aContext) && !commitString[0]) { -+ if (!IsComposingOn(aContext) && utf16CommitString.IsEmpty()) { - MOZ_LOG(gGtkIMLog, LogLevel::Warning, - ("0x%p OnCommitCompositionNative(), Warning, does nothing " - "because has not started composition and commit string is empty", -@@ -1431,11 +1768,14 @@ IMContextWrapper::OnCommitCompositionNat - } - - // If IME doesn't change their keyevent that generated this commit, -- // don't send it through XIM - just send it as a normal key press -- // event. -+ // we should treat that IME didn't handle the key event because -+ // web applications want to receive "keydown" and "keypress" event -+ // in such case. - // NOTE: While a key event is being handled, this might be caused on - // current context. Otherwise, this may be caused on active context. -- if (!IsComposingOn(aContext) && mProcessingKeyEvent && -+ if (!IsComposingOn(aContext) && -+ mProcessingKeyEvent && -+ mProcessingKeyEvent->type == GDK_KEY_PRESS && - aContext == GetCurrentContext()) { - char keyval_utf8[8]; /* should have at least 6 bytes of space */ - gint keyval_utf8_len; -@@ -1445,12 +1785,80 @@ IMContextWrapper::OnCommitCompositionNat - keyval_utf8_len = g_unichar_to_utf8(keyval_unicode, keyval_utf8); - keyval_utf8[keyval_utf8_len] = '\0'; - -+ // If committing string is exactly same as a character which is -+ // produced by the key, eKeyDown and eKeyPress event should be -+ // dispatched by the caller of OnKeyEvent() normally. Note that -+ // mMaybeInDeadKeySequence will be set to false by OnKeyEvent() -+ // since we set mFallbackToKeyEvent to true here. - if (!strcmp(commitString, keyval_utf8)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("0x%p OnCommitCompositionNative(), " - "we'll send normal key event", - this)); -- mFilterKeyEvent = false; -+ mFallbackToKeyEvent = true; -+ return; -+ } -+ -+ // If we're in a dead key sequence, commit string is a character in -+ // the BMP and mProcessingKeyEvent produces some characters but it's -+ // not same as committing string, we should dispatch an eKeyPress -+ // event from here. -+ WidgetKeyboardEvent keyDownEvent(true, eKeyDown, -+ mLastFocusedWindow); -+ KeymapWrapper::InitKeyEvent(keyDownEvent, mProcessingKeyEvent, false); -+ if (mMaybeInDeadKeySequence && -+ utf16CommitString.Length() == 1 && -+ keyDownEvent.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) { -+ mKeyboardEventWasDispatched = true; -+ // Anyway, we're not in dead key sequence anymore. -+ mMaybeInDeadKeySequence = false; -+ -+ RefPtr dispatcher = GetTextEventDispatcher(); -+ nsresult rv = dispatcher->BeginNativeInputTransaction(); -+ if (NS_WARN_IF(NS_FAILED(rv))) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Error, -+ ("0x%p OnCommitCompositionNative(), FAILED, " -+ "due to BeginNativeInputTransaction() failure", -+ this)); -+ return; -+ } -+ -+ // First, dispatch eKeyDown event. -+ keyDownEvent.mKeyValue = utf16CommitString; -+ nsEventStatus status = nsEventStatus_eIgnore; -+ bool dispatched = -+ dispatcher->DispatchKeyboardEvent(eKeyDown, keyDownEvent, -+ status, mProcessingKeyEvent); -+ if (!dispatched || status == nsEventStatus_eConsumeNoDefault) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnCommitCompositionNative(), " -+ "doesn't dispatch eKeyPress event because the preceding " -+ "eKeyDown event was not dispatched or was consumed", -+ this)); -+ return; -+ } -+ if (mLastFocusedWindow != keyDownEvent.mWidget || -+ mLastFocusedWindow->Destroyed()) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p OnCommitCompositionNative(), Warning, " -+ "stop dispatching eKeyPress event because the preceding " -+ "eKeyDown event caused changing focused widget or " -+ "destroyed", -+ this)); -+ return; -+ } -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnCommitCompositionNative(), " -+ "dispatched eKeyDown event for the committed character", -+ this)); -+ -+ // Next, dispatch eKeyPress event. -+ dispatcher->MaybeDispatchKeypressEvents(keyDownEvent, status, -+ mProcessingKeyEvent); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p OnCommitCompositionNative(), " -+ "dispatched eKeyPress event for the committed character", -+ this)); - return; - } - } -@@ -1470,7 +1878,7 @@ IMContextWrapper::GetCompositionString(G - gtk_im_context_get_preedit_string(aContext, &preedit_string, - &feedback_list, &cursor_pos); - if (preedit_string && *preedit_string) { -- CopyUTF8toUTF16(preedit_string, aCompositionString); -+ CopyUTF8toUTF16(MakeStringSpan(preedit_string), aCompositionString); - } else { - aCompositionString.Truncate(); - } -@@ -1485,6 +1893,173 @@ IMContextWrapper::GetCompositionString(G - } - - bool -+IMContextWrapper::MaybeDispatchKeyEventAsProcessedByIME( -+ EventMessage aFollowingEvent) -+{ -+ if (!mLastFocusedWindow) { -+ return false; -+ } -+ -+ if (!mIsKeySnooped && -+ ((!mProcessingKeyEvent && mPostingKeyEvents.IsEmpty()) || -+ (mProcessingKeyEvent && mKeyboardEventWasDispatched))) { -+ return true; -+ } -+ -+ // A "keydown" or "keyup" event handler may change focus with the -+ // following event. In such case, we need to cancel this composition. -+ // So, we need to store IM context now because mComposingContext may be -+ // overwritten with different context if calling this method recursively. -+ // Note that we don't need to grab the context here because |context| -+ // will be used only for checking if it's same as mComposingContext. -+ GtkIMContext* oldCurrentContext = GetCurrentContext(); -+ GtkIMContext* oldComposingContext = mComposingContext; -+ -+ RefPtr lastFocusedWindow(mLastFocusedWindow); -+ -+ if (mProcessingKeyEvent || !mPostingKeyEvents.IsEmpty()) { -+ if (mProcessingKeyEvent) { -+ mKeyboardEventWasDispatched = true; -+ } -+ // If we're not handling a key event synchronously, the signal may be -+ // sent by IME without sending key event to us. In such case, we -+ // should dispatch keyboard event for the last key event which was -+ // posted to other IME process. -+ GdkEventKey* sourceEvent = -+ mProcessingKeyEvent ? mProcessingKeyEvent : -+ mPostingKeyEvents.GetFirstEvent(); -+ -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(" -+ "aFollowingEvent=%s), dispatch %s %s " -+ "event: { type=%s, keyval=%s, unicode=0x%X, state=%s, " -+ "time=%u, hardware_keycode=%u, group=%u }", -+ this, ToChar(aFollowingEvent), -+ ToChar(sourceEvent->type == GDK_KEY_PRESS ? eKeyDown : eKeyUp), -+ mProcessingKeyEvent ? "processing" : "posted", -+ GetEventType(sourceEvent), gdk_keyval_name(sourceEvent->keyval), -+ gdk_keyval_to_unicode(sourceEvent->keyval), -+ GetEventStateName(sourceEvent->state, mIMContextID).get(), -+ sourceEvent->time, sourceEvent->hardware_keycode, -+ sourceEvent->group)); -+ -+ // Let's dispatch eKeyDown event or eKeyUp event now. Note that only -+ // when we're not in a dead key composition, we should mark the -+ // eKeyDown and eKeyUp event as "processed by IME" since we should -+ // expose raw keyCode and key value to web apps the key event is a -+ // part of a dead key sequence. -+ // FYI: We should ignore if default of preceding keydown or keyup -+ // event is prevented since even on the other browsers, web -+ // applications cannot cancel the following composition event. -+ // Spec bug: https://github.com/w3c/uievents/issues/180 -+ bool isCancelled; -+ lastFocusedWindow->DispatchKeyDownOrKeyUpEvent(sourceEvent, -+ !mMaybeInDeadKeySequence, -+ &isCancelled); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), keydown or keyup " -+ "event is dispatched", -+ this)); -+ -+ if (!mProcessingKeyEvent) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), removing first " -+ "event from the queue", -+ this)); -+ mPostingKeyEvents.RemoveEvent(sourceEvent); -+ } -+ } else { -+ MOZ_ASSERT(mIsKeySnooped); -+ // Currently, we support key snooper mode of uim only. -+ MOZ_ASSERT(mIMContextID == IMContextID::eUim); -+ // uim sends "preedit_start" signal and "preedit_changed" separately -+ // at starting composition, "commit" and "preedit_end" separately at -+ // committing composition. -+ -+ // Currently, we should dispatch only fake eKeyDown event because -+ // we cannot decide which is the last signal of each key operation -+ // and Chromium also dispatches only "keydown" event in this case. -+ bool dispatchFakeKeyDown = false; -+ switch (aFollowingEvent) { -+ case eCompositionStart: -+ case eCompositionCommit: -+ case eCompositionCommitAsIs: -+ dispatchFakeKeyDown = true; -+ break; -+ // XXX Unfortunately, I don't have a good idea to prevent to -+ // dispatch redundant eKeyDown event for eCompositionStart -+ // immediately after "delete_surrounding" signal. However, -+ // not dispatching eKeyDown event is worse than dispatching -+ // redundant eKeyDown events. -+ case eContentCommandDelete: -+ dispatchFakeKeyDown = true; -+ break; -+ // We need to prevent to dispatch redundant eKeyDown event for -+ // eCompositionChange immediately after eCompositionStart. So, -+ // We should not dispatch eKeyDown event if dispatched composition -+ // string is still empty string. -+ case eCompositionChange: -+ dispatchFakeKeyDown = !mDispatchedCompositionString.IsEmpty(); -+ break; -+ default: -+ MOZ_ASSERT_UNREACHABLE("Do you forget to handle the case?"); -+ break; -+ } -+ -+ if (dispatchFakeKeyDown) { -+ WidgetKeyboardEvent fakeKeyDownEvent(true, eKeyDown, -+ lastFocusedWindow); -+ fakeKeyDownEvent.mKeyCode = NS_VK_PROCESSKEY; -+ fakeKeyDownEvent.mKeyNameIndex = KEY_NAME_INDEX_Process; -+ // It's impossible to get physical key information in this case but -+ // this should be okay since web apps shouldn't do anything with -+ // physical key information during composition. -+ fakeKeyDownEvent.mCodeNameIndex = CODE_NAME_INDEX_UNKNOWN; -+ -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(" -+ "aFollowingEvent=%s), dispatch fake eKeyDown event", -+ this, ToChar(aFollowingEvent))); -+ -+ bool isCancelled; -+ lastFocusedWindow->DispatchKeyDownOrKeyUpEvent(fakeKeyDownEvent, -+ &isCancelled); -+ MOZ_LOG(gGtkIMLog, LogLevel::Info, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), " -+ "fake keydown event is dispatched", -+ this)); -+ } -+ } -+ -+ if (lastFocusedWindow->IsDestroyed() || -+ lastFocusedWindow != mLastFocusedWindow) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), Warning, the " -+ "focused widget was destroyed/changed by a key event", -+ this)); -+ return false; -+ } -+ -+ // If the dispatched keydown event caused moving focus and that also -+ // caused changing active context, we need to cancel composition here. -+ if (GetCurrentContext() != oldCurrentContext) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p MaybeDispatchKeyEventAsProcessedByIME(), Warning, the key " -+ "event causes changing active IM context", -+ this)); -+ if (mComposingContext == oldComposingContext) { -+ // Only when the context is still composing, we should call -+ // ResetIME() here. Otherwise, it should've already been -+ // cleaned up. -+ ResetIME(); -+ } -+ return false; -+ } -+ -+ return true; -+} -+ -+bool - IMContextWrapper::DispatchCompositionStart(GtkIMContext* aContext) - { - MOZ_LOG(gGtkIMLog, LogLevel::Info, -@@ -1528,50 +2103,16 @@ IMContextWrapper::DispatchCompositionSta - mCompositionStart = mSelection.mOffset; - mDispatchedCompositionString.Truncate(); - -- if (mProcessingKeyEvent && !mKeyDownEventWasSent && -- mProcessingKeyEvent->type == GDK_KEY_PRESS) { -- // A keydown event handler may change focus with the following keydown -- // event. In such case, we need to cancel this composition. So, we -- // need to store IM context now because mComposingContext may be -- // overwritten with different context if calling this method -- // recursively. -- // Note that we don't need to grab the context here because |context| -- // will be used only for checking if it's same as mComposingContext. -- GtkIMContext* context = mComposingContext; -- -- // If this composition is started by a native keydown event, we need to -- // dispatch our keydown event here (before composition start). -- bool isCancelled; -- mLastFocusedWindow->DispatchKeyDownEvent(mProcessingKeyEvent, -- &isCancelled); -- MOZ_LOG(gGtkIMLog, LogLevel::Debug, -- ("0x%p DispatchCompositionStart(), preceding keydown event is " -- "dispatched", -+ // If this composition is started by a key press, we need to dispatch -+ // eKeyDown or eKeyUp event before dispatching eCompositionStart event. -+ // Note that dispatching a keyboard event which is marked as "processed -+ // by IME" is okay since Chromium also dispatches keyboard event as so. -+ if (!MaybeDispatchKeyEventAsProcessedByIME(eCompositionStart)) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p DispatchCompositionStart(), Warning, " -+ "MaybeDispatchKeyEventAsProcessedByIME() returned false", - this)); -- if (lastFocusedWindow->IsDestroyed() || -- lastFocusedWindow != mLastFocusedWindow) { -- MOZ_LOG(gGtkIMLog, LogLevel::Warning, -- ("0x%p DispatchCompositionStart(), Warning, the focused " -- "widget was destroyed/changed by keydown event", -- this)); -- return false; -- } -- -- // If the dispatched keydown event caused moving focus and that also -- // caused changing active context, we need to cancel composition here. -- if (GetCurrentContext() != context) { -- MOZ_LOG(gGtkIMLog, LogLevel::Warning, -- ("0x%p DispatchCompositionStart(), Warning, the preceding " -- "keydown event causes changing active IM context", -- this)); -- if (mComposingContext == context) { -- // Only when the context is still composing, we should call -- // ResetIME() here. Otherwise, it should've already been -- // cleaned up. -- ResetIME(); -- } -- return false; -- } -+ return false; - } - - RefPtr dispatcher = GetTextEventDispatcher(); -@@ -1584,6 +2125,25 @@ IMContextWrapper::DispatchCompositionSta - return false; - } - -+ static bool sHasSetTelemetry = false; -+ if (!sHasSetTelemetry) { -+ sHasSetTelemetry = true; -+ NS_ConvertUTF8toUTF16 im(GetIMName()); -+ // 72 is kMaximumKeyStringLength in TelemetryScalar.cpp -+ if (im.Length() > 72) { -+ if (NS_IS_LOW_SURROGATE(im[72 - 1]) && -+ NS_IS_HIGH_SURROGATE(im[72 - 2])) { -+ im.Truncate(72 - 2); -+ } else { -+ im.Truncate(72 - 1); -+ } -+ // U+2026 is "..." -+ im.Append(char16_t(0x2026)); -+ } -+ Telemetry::ScalarSet(Telemetry::ScalarID::WIDGET_IME_NAME_ON_LINUX, -+ im, true); -+ } -+ - MOZ_LOG(gGtkIMLog, LogLevel::Debug, - ("0x%p DispatchCompositionStart(), dispatching " - "compositionstart... (mCompositionStart=%u)", -@@ -1629,6 +2189,15 @@ IMContextWrapper::DispatchCompositionCha - return false; - } - } -+ // If this composition string change caused by a key press, we need to -+ // dispatch eKeyDown or eKeyUp before dispatching eCompositionChange event. -+ else if (!MaybeDispatchKeyEventAsProcessedByIME(eCompositionChange)) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p DispatchCompositionChangeEvent(), Warning, " -+ "MaybeDispatchKeyEventAsProcessedByIME() returned false", -+ this)); -+ return false; -+ } - - RefPtr dispatcher = GetTextEventDispatcher(); - nsresult rv = dispatcher->BeginNativeInputTransaction(); -@@ -1718,6 +2287,14 @@ IMContextWrapper::DispatchCompositionCom - return false; - } - -+ // TODO: We need special care to handle request to commit composition -+ // by content while we're committing composition because we have -+ // commit string information now but IME may not have composition -+ // anymore. Therefore, we may not be able to handle commit as -+ // expected. However, this is rare case because this situation -+ // never occurs with remote content. So, it's okay to fix this -+ // issue later. (Perhaps, TextEventDisptcher should do it for -+ // all platforms. E.g., creating WillCommitComposition()?) - if (!IsComposing()) { - if (!aCommitString || aCommitString->IsEmpty()) { - MOZ_LOG(gGtkIMLog, LogLevel::Error, -@@ -1734,6 +2311,17 @@ IMContextWrapper::DispatchCompositionCom - return false; - } - } -+ // If this commit caused by a key press, we need to dispatch eKeyDown or -+ // eKeyUp before dispatching composition events. -+ else if (!MaybeDispatchKeyEventAsProcessedByIME( -+ aCommitString ? eCompositionCommit : eCompositionCommitAsIs)) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p DispatchCompositionCommitEvent(), Warning, " -+ "MaybeDispatchKeyEventAsProcessedByIME() returned false", -+ this)); -+ mCompositionState = eCompositionState_NotComposing; -+ return false; -+ } - - RefPtr dispatcher = GetTextEventDispatcher(); - nsresult rv = dispatcher->BeginNativeInputTransaction(); -@@ -1755,6 +2343,11 @@ IMContextWrapper::DispatchCompositionCom - mSelection.mWritingMode); - - mCompositionState = eCompositionState_NotComposing; -+ // Reset dead key sequence too because GTK doesn't support dead key chain -+ // (i.e., a key press doesn't cause both producing some characters and -+ // restarting new dead key sequence at one time). So, committing -+ // composition means end of a dead key sequence. -+ mMaybeInDeadKeySequence = false; - mCompositionStart = UINT32_MAX; - mCompositionTargetRange.Clear(); - mDispatchedCompositionString.Truncate(); -@@ -2427,6 +3020,16 @@ IMContextWrapper::DeleteText(GtkIMContex - this)); - return NS_ERROR_FAILURE; - } -+ -+ // If this deleting text caused by a key press, we need to dispatch -+ // eKeyDown or eKeyUp before dispatching eContentCommandDelete event. -+ if (!MaybeDispatchKeyEventAsProcessedByIME(eContentCommandDelete)) { -+ MOZ_LOG(gGtkIMLog, LogLevel::Warning, -+ ("0x%p DeleteText(), Warning, " -+ "MaybeDispatchKeyEventAsProcessedByIME() returned false", -+ this)); -+ return NS_ERROR_FAILURE; -+ } - - // Delete the selection - WidgetContentCommandEvent contentCommandEvent(true, eContentCommandDelete, -diff -up thunderbird-60.3.0/widget/gtk/IMContextWrapper.h.wayland thunderbird-60.3.0/widget/gtk/IMContextWrapper.h ---- thunderbird-60.3.0/widget/gtk/IMContextWrapper.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/IMContextWrapper.h 2018-11-20 12:04:43.733787362 +0100 -@@ -70,13 +70,26 @@ public: - // OnThemeChanged is called when desktop theme is changed. - static void OnThemeChanged(); - -- // OnKeyEvent is called when aWindow gets a native key press event or a -- // native key release event. If this returns TRUE, the key event was -- // filtered by IME. Otherwise, this returns FALSE. -- // NOTE: When the keypress event starts composition, this returns TRUE but -- // this dispatches keydown event before compositionstart event. -+ /** -+ * OnKeyEvent() is called when aWindow gets a native key press event or a -+ * native key release event. If this returns true, the key event was -+ * filtered by IME. Otherwise, this returns false. -+ * NOTE: When the native key press event starts composition, this returns -+ * true but dispatches an eKeyDown event or eKeyUp event before -+ * dispatching composition events or content command event. -+ * -+ * @param aWindow A window on which user operate the -+ * key. -+ * @param aEvent A native key press or release -+ * event. -+ * @param aKeyboardEventWasDispatched true if eKeyDown or eKeyUp event -+ * for aEvent has already been -+ * dispatched. In this case, -+ * this class doesn't dispatch -+ * keyboard event anymore. -+ */ - bool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent, -- bool aKeyDownEventWasSent = false); -+ bool aKeyboardEventWasDispatched = false); - - // IME related nsIWidget methods. - nsresult EndIMEComposition(nsWindow* aCaller); -@@ -89,6 +102,43 @@ public: - - TextEventDispatcher* GetTextEventDispatcher(); - -+ // TODO: Typically, new IM comes every several years. And now, our code -+ // becomes really IM behavior dependent. So, perhaps, we need prefs -+ // to control related flags for IM developers. -+ enum class IMContextID : uint8_t -+ { -+ eFcitx, -+ eIBus, -+ eIIIMF, -+ eScim, -+ eUim, -+ eUnknown, -+ }; -+ -+ static const char* GetIMContextIDName(IMContextID aIMContextID) -+ { -+ switch (aIMContextID) { -+ case IMContextID::eFcitx: -+ return "eFcitx"; -+ case IMContextID::eIBus: -+ return "eIBus"; -+ case IMContextID::eIIIMF: -+ return "eIIIMF"; -+ case IMContextID::eScim: -+ return "eScim"; -+ case IMContextID::eUim: -+ return "eUim"; -+ default: -+ return "eUnknown"; -+ } -+ } -+ -+ /** -+ * GetIMName() returns IM name associated with mContext. If the context is -+ * xim, this look for actual engine from XMODIFIERS environment variable. -+ */ -+ nsDependentCSubstring GetIMName() const; -+ - protected: - ~IMContextWrapper(); - -@@ -144,6 +194,100 @@ protected: - // event. - GdkEventKey* mProcessingKeyEvent; - -+ /** -+ * GdkEventKeyQueue stores *copy* of GdkEventKey instances. However, this -+ * must be safe to our usecase since it has |time| and the value should not -+ * be same as older event. -+ */ -+ class GdkEventKeyQueue final -+ { -+ public: -+ ~GdkEventKeyQueue() { Clear(); } -+ -+ void Clear() -+ { -+ if (!mEvents.IsEmpty()) { -+ RemoveEventsAt(0, mEvents.Length()); -+ } -+ } -+ -+ /** -+ * PutEvent() puts new event into the queue. -+ */ -+ void PutEvent(const GdkEventKey* aEvent) -+ { -+ GdkEventKey* newEvent = -+ reinterpret_cast( -+ gdk_event_copy(reinterpret_cast(aEvent))); -+ newEvent->state &= GDK_MODIFIER_MASK; -+ mEvents.AppendElement(newEvent); -+ } -+ -+ /** -+ * RemoveEvent() removes oldest same event and its preceding events -+ * from the queue. -+ */ -+ void RemoveEvent(const GdkEventKey* aEvent) -+ { -+ size_t index = IndexOf(aEvent); -+ if (NS_WARN_IF(index == mEvents.NoIndex)) { -+ return; -+ } -+ RemoveEventsAt(0, index + 1); -+ } -+ -+ /** -+ * FirstEvent() returns oldest event in the queue. -+ */ -+ GdkEventKey* GetFirstEvent() const -+ { -+ if (mEvents.IsEmpty()) { -+ return nullptr; -+ } -+ return mEvents[0]; -+ } -+ -+ bool IsEmpty() const { return mEvents.IsEmpty(); } -+ -+ private: -+ nsTArray mEvents; -+ -+ void RemoveEventsAt(size_t aStart, size_t aCount) -+ { -+ for (size_t i = aStart; i < aStart + aCount; i++) { -+ gdk_event_free(reinterpret_cast(mEvents[i])); -+ } -+ mEvents.RemoveElementsAt(aStart, aCount); -+ } -+ -+ size_t IndexOf(const GdkEventKey* aEvent) const -+ { -+ static_assert(!(GDK_MODIFIER_MASK & (1 << 24)), -+ "We assumes 25th bit is used by some IM, but used by GDK"); -+ static_assert(!(GDK_MODIFIER_MASK & (1 << 25)), -+ "We assumes 26th bit is used by some IM, but used by GDK"); -+ for (size_t i = 0; i < mEvents.Length(); i++) { -+ GdkEventKey* event = mEvents[i]; -+ // It must be enough to compare only type, time, keyval and -+ // part of state. Note that we cannot compaire two events -+ // simply since IME may have changed unused bits of state. -+ if (event->time == aEvent->time) { -+ if (NS_WARN_IF(event->type != aEvent->type) || -+ NS_WARN_IF(event->keyval != aEvent->keyval) || -+ NS_WARN_IF(event->state != -+ (aEvent->state & GDK_MODIFIER_MASK))) { -+ continue; -+ } -+ } -+ return i; -+ } -+ return mEvents.NoIndex; -+ } -+ }; -+ // OnKeyEvent() append mPostingKeyEvents when it believes that a key event -+ // is posted to other IME process. -+ GdkEventKeyQueue mPostingKeyEvents; -+ - struct Range - { - uint32_t mOffset; -@@ -167,7 +311,8 @@ protected: - Range mCompositionTargetRange; - - // mCompositionState indicates current status of composition. -- enum eCompositionState { -+ enum eCompositionState : uint8_t -+ { - eCompositionState_NotComposing, - eCompositionState_CompositionStartDispatched, - eCompositionState_CompositionChangeEventDispatched -@@ -219,6 +364,10 @@ protected: - } - } - -+ // mIMContextID indicates the ID of mContext. This is actually indicates -+ // IM which user selected. -+ IMContextID mIMContextID; -+ - struct Selection final - { - nsString mString; -@@ -268,16 +417,20 @@ protected: - // mIsIMFocused is set to TRUE when we call gtk_im_context_focus_in(). And - // it's set to FALSE when we call gtk_im_context_focus_out(). - bool mIsIMFocused; -- // mFilterKeyEvent is used by OnKeyEvent(). If the commit event should -- // be processed as simple key event, this is set to TRUE by the commit -- // handler. -- bool mFilterKeyEvent; -- // mKeyDownEventWasSent is used by OnKeyEvent() and -- // DispatchCompositionStart(). DispatchCompositionStart() dispatches -- // a keydown event if the composition start is caused by a native -- // keypress event. If this is true, the keydown event has been dispatched. -- // Then, DispatchCompositionStart() doesn't dispatch keydown event. -- bool mKeyDownEventWasSent; -+ // mFallbackToKeyEvent is set to false when this class starts to handle -+ // a native key event (at that time, mProcessingKeyEvent is set to the -+ // native event). If active IME just commits composition with a character -+ // which is produced by the key with current keyboard layout, this is set -+ // to true. -+ bool mFallbackToKeyEvent; -+ // mKeyboardEventWasDispatched is used by OnKeyEvent() and -+ // MaybeDispatchKeyEventAsProcessedByIME(). -+ // MaybeDispatchKeyEventAsProcessedByIME() dispatches an eKeyDown or -+ // eKeyUp event event if the composition is caused by a native -+ // key press event. If this is true, a keyboard event has been dispatched -+ // for the native event. If so, MaybeDispatchKeyEventAsProcessedByIME() -+ // won't dispatch keyboard event anymore. -+ bool mKeyboardEventWasDispatched; - // mIsDeletingSurrounding is true while OnDeleteSurroundingNative() is - // trying to delete the surrounding text. - bool mIsDeletingSurrounding; -@@ -298,6 +451,24 @@ protected: - // mRetrieveSurroundingSignalReceived is true after "retrieve_surrounding" - // signal is received until selection is changed in Gecko. - bool mRetrieveSurroundingSignalReceived; -+ // mMaybeInDeadKeySequence is set to true when we detect a dead key press -+ // and set to false when we're sure dead key sequence has been finished. -+ // Note that we cannot detect which key event causes ending a dead key -+ // sequence. For example, when you press dead key grave with ibus Spanish -+ // keyboard layout, it just consumes the key event when we call -+ // gtk_im_context_filter_keypress(). Then, pressing "Escape" key cancels -+ // the dead key sequence but we don't receive any signal and it's consumed -+ // by gtk_im_context_filter_keypress() normally. On the other hand, when -+ // pressing "Shift" key causes exactly same behavior but dead key sequence -+ // isn't finished yet. -+ bool mMaybeInDeadKeySequence; -+ // mIsIMInAsyncKeyHandlingMode is set to true if we know that IM handles -+ // key events asynchronously. I.e., filtered key event may come again -+ // later. -+ bool mIsIMInAsyncKeyHandlingMode; -+ // mIsKeySnooped is set to true if IM uses key snooper to listen key events. -+ // In such case, we won't receive key events if IME consumes the event. -+ bool mIsKeySnooped; - - // sLastFocusedContext is a pointer to the last focused instance of this - // class. When a instance is destroyed and sLastFocusedContext refers it, -@@ -448,12 +619,31 @@ protected: - * Following methods dispatch gecko events. Then, the focused widget - * can be destroyed, and also it can be stolen focus. If they returns - * FALSE, callers cannot continue the composition. -+ * - MaybeDispatchKeyEventAsProcessedByIME - * - DispatchCompositionStart - * - DispatchCompositionChangeEvent - * - DispatchCompositionCommitEvent - */ - - /** -+ * Dispatch an eKeyDown or eKeyUp event whose mKeyCode value is -+ * NS_VK_PROCESSKEY and mKeyNameIndex is KEY_NAME_INDEX_Process if -+ * we're not in a dead key sequence, mProcessingKeyEvent is nullptr -+ * but mPostingKeyEvents is not empty or mProcessingKeyEvent is not -+ * nullptr and mKeyboardEventWasDispatched is still false. If this -+ * dispatches a keyboard event, this sets mKeyboardEventWasDispatched -+ * to true. -+ * -+ * @param aFollowingEvent The following event message. -+ * @return If the caller can continue to handle -+ * composition, returns true. Otherwise, -+ * false. For example, if focus is moved -+ * by dispatched keyboard event, returns -+ * false. -+ */ -+ bool MaybeDispatchKeyEventAsProcessedByIME(EventMessage aFollowingEvent); -+ -+ /** - * Dispatches a composition start event. - * - * @param aContext A GtkIMContext which is being handled. -diff -up thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h.wayland thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h ---- thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/InProcessGtkCompositorWidget.h 2018-11-20 12:04:43.733787362 +0100 -@@ -3,8 +3,8 @@ - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - --#ifndef widget_gtk_InProcessGtkCompositorWidgetParent_h --#define widget_gtk_InProcessGtkCompositorWidgetParent_h -+#ifndef widget_gtk_InProcessGtkCompositorWidget_h -+#define widget_gtk_InProcessGtkCompositorWidget_h - - #include "GtkCompositorWidget.h" - -@@ -28,4 +28,4 @@ public: - } // namespace widget - } // namespace mozilla - --#endif // widget_gtk_InProcessGtkCompositorWidgetParent_h -+#endif // widget_gtk_InProcessGtkCompositorWidget_h diff -up thunderbird-60.3.0/widget/gtk/moz.build.wayland thunderbird-60.3.0/widget/gtk/moz.build --- thunderbird-60.3.0/widget/gtk/moz.build.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/moz.build 2018-11-20 12:09:34.756903818 +0100 ++++ thunderbird-60.3.0/widget/gtk/moz.build 2018-11-21 13:42:00.757025666 +0100 @@ -123,6 +123,7 @@ include('/ipc/chromium/chromium-config.m FINAL_LIBRARY = 'xul' @@ -1971,7 +35,7 @@ diff -up thunderbird-60.3.0/widget/gtk/moz.build.wayland thunderbird-60.3.0/widg '/other-licenses/atk-1.0', diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.3.0/widget/gtk/mozcontainer.cpp --- thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/mozcontainer.cpp 2018-11-20 12:04:43.733787362 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozcontainer.cpp 2018-11-21 13:42:00.757025666 +0100 @@ -10,6 +10,7 @@ #ifdef MOZ_WAYLAND #include @@ -2049,7 +113,7 @@ diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.3 static void moz_container_unmap_surface(MozContainer *container) { -+ g_clear_pointer(&container->eglwindow, wl_egl_window_destroy); ++ //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); + @@ -2068,18 +132,6 @@ diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.3 } #endif -@@ -434,6 +479,11 @@ moz_container_size_allocate (GtkWidget - gdk_window_get_position(gtk_widget_get_window(widget), &x, &y); - wl_subsurface_set_position(container->subsurface, x, y); - } -+ if (container->eglwindow) { -+ wl_egl_window_resize(container->eglwindow, -+ allocation->width, allocation->height, -+ 0, 0); -+ } - #endif - } - @@ -555,8 +605,40 @@ moz_container_get_wl_surface(MozContaine return nullptr; @@ -2100,7 +152,7 @@ diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.3 + +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) @@ -2112,7 +164,7 @@ diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.3 + gdk_window_get_width(window), + gdk_window_get_height(window)); + } -+ return container->eglwindow; ++ return container->eglwindow;*/ return nullptr; +} + +gboolean @@ -2123,7 +175,7 @@ diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.cpp.wayland thunderbird-60.3 #endif diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.h.wayland thunderbird-60.3.0/widget/gtk/mozcontainer.h --- thunderbird-60.3.0/widget/gtk/mozcontainer.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/mozcontainer.h 2018-11-20 12:04:43.733787362 +0100 ++++ 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; @@ -2145,7 +197,7 @@ diff -up thunderbird-60.3.0/widget/gtk/mozcontainer.h.wayland thunderbird-60.3.0 #endif /* __MOZ_CONTAINER_H__ */ diff -up thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c --- thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c 2018-11-20 12:04:43.734787359 +0100 ++++ thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c 2018-11-21 13:42:00.757025666 +0100 @@ -135,6 +135,8 @@ STUB(gdk_x11_get_xatom_by_name) STUB(gdk_x11_get_xatom_by_name_for_display) STUB(gdk_x11_lookup_xdisplay) @@ -2165,7 +217,7 @@ diff -up thunderbird-60.3.0/widget/gtk/mozgtk/mozgtk.c.wayland thunderbird-60.3. STUB(gtk_info_bar_get_type) diff -up thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c.wayland thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c --- thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c 2018-11-20 12:04:43.734787359 +0100 ++++ 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 { } @@ -2188,57 +240,9 @@ diff -up thunderbird-60.3.0/widget/gtk/mozwayland/mozwayland.c.wayland thunderbi + int dx, int dy) +{ +} -diff -up thunderbird-60.3.0/widget/gtk/nsAppShell.cpp.wayland thunderbird-60.3.0/widget/gtk/nsAppShell.cpp ---- thunderbird-60.3.0/widget/gtk/nsAppShell.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsAppShell.cpp 2018-11-20 12:04:43.734787359 +0100 -@@ -14,7 +14,8 @@ - #include "nsWindow.h" - #include "mozilla/Logging.h" - #include "prenv.h" --#include "mozilla/HangMonitor.h" -+#include "mozilla/BackgroundHangMonitor.h" -+#include "mozilla/Hal.h" - #include "mozilla/Unused.h" - #include "mozilla/WidgetUtils.h" - #include "GeckoProfiler.h" -@@ -46,13 +47,14 @@ static GPollFunc sPollFunc; - static gint - PollWrapper(GPollFD *ufds, guint nfsd, gint timeout_) - { -- mozilla::HangMonitor::Suspend(); -+ mozilla::BackgroundHangMonitor().NotifyWait(); - gint result; - { -+ AUTO_PROFILER_LABEL("PollWrapper", IDLE); - AUTO_PROFILER_THREAD_SLEEP; - result = (*sPollFunc)(ufds, nfsd, timeout_); - } -- mozilla::HangMonitor::NotifyActivity(); -+ mozilla::BackgroundHangMonitor().NotifyActivity(); - return result; - } - -@@ -133,6 +135,8 @@ nsAppShell::EventProcessorCallback(GIOCh - - nsAppShell::~nsAppShell() - { -+ mozilla::hal::Shutdown(); -+ - if (mTag) - g_source_remove(mTag); - if (mPipeFDs[0]) -@@ -150,6 +154,8 @@ nsAppShell::Init() - // is a no-op. - g_type_init(); - -+ mozilla::hal::Init(); -+ - #ifdef MOZ_ENABLE_DBUS - if (XRE_IsParentProcess()) { - nsCOMPtr powerManagerService = diff -up thunderbird-60.3.0/widget/gtk/nsClipboard.cpp.wayland thunderbird-60.3.0/widget/gtk/nsClipboard.cpp --- thunderbird-60.3.0/widget/gtk/nsClipboard.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsClipboard.cpp 2018-11-20 12:04:43.734787359 +0100 ++++ 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 @@ -2301,7 +305,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsClipboard.cpp.wayland thunderbird-60.3. } diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp --- thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp 2018-11-20 12:04:43.735787356 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp 2018-11-21 13:42:00.758025661 +0100 @@ -23,6 +23,7 @@ #include "mozilla/Services.h" #include "mozilla/RefPtr.h" @@ -2914,7 +918,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.cpp.wayland thunderbir return GetClipboardData(sTextMimeTypes[i], aWhichClipboard, diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h.wayland thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h --- thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h 2018-11-20 12:04:43.735787356 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h 2018-11-21 13:42:00.759025657 +0100 @@ -32,6 +32,7 @@ public: private: virtual bool RequestDataTransfer(const char* aMimeType, int fd) = 0; @@ -3021,52 +1025,9 @@ diff -up thunderbird-60.3.0/widget/gtk/nsClipboardWayland.h.wayland thunderbird- int mClipboardRequestNumber; char* mClipboardData; -diff -up thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp.wayland thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp ---- thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsDeviceContextSpecG.cpp 2018-11-20 12:04:43.735787356 +0100 -@@ -33,6 +33,9 @@ - #include - #include - -+// To check if we need to use flatpak portal for printing -+#include "nsIGIOService.h" -+ - using namespace mozilla; - - using mozilla::gfx::IntSize; -@@ -355,6 +358,20 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::En - // If you're not familiar with umasks, they contain the bits of what NOT to set in the permissions - // (thats because files and directories have different numbers of bits for their permissions) - destFile->SetPermissions(0666 & ~(mask)); -+ -+ // Notify flatpak printing portal that file is completely written -+ nsCOMPtr giovfs = -+ do_GetService(NS_GIOSERVICE_CONTRACTID); -+ bool shouldUsePortal; -+ if (giovfs) { -+ giovfs->ShouldUseFlatpakPortal(&shouldUsePortal); -+ if (shouldUsePortal) { -+ // Use the name of the file for printing to match with nsFlatpakPrintPortal -+ nsCOMPtr os = mozilla::services::GetObserverService(); -+ // Pass filename to be sure that observer process the right data -+ os->NotifyObservers(nullptr, "print-to-file-finished", targetPath.get()); -+ } -+ } - } - return NS_OK; - } -@@ -421,7 +438,7 @@ nsPrinterEnumeratorGTK::InitPrintSetting - } - - if (path) { -- CopyUTF8toUTF16(path, filename); -+ CopyUTF8toUTF16(MakeStringSpan(path), filename); - filename.AppendLiteral("/mozilla.pdf"); - } else { - filename.AssignLiteral("mozilla.pdf"); diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60.3.0/widget/gtk/nsDragService.cpp --- thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsDragService.cpp 2018-11-20 12:04:43.736787353 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsDragService.cpp 2018-11-21 13:42:00.759025657 +0100 @@ -34,7 +34,6 @@ #include "nsPresContext.h" #include "nsIContent.h" @@ -3096,81 +1057,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. { // We have to destroy the hidden widget before the event loop stops // running. -@@ -179,7 +185,7 @@ nsDragService::Observe(nsISupports *aSub - } - TargetResetData(); - } else { -- NS_NOTREACHED("unexpected topic"); -+ MOZ_ASSERT_UNREACHABLE("unexpected topic"); - return NS_ERROR_UNEXPECTED; - } - -@@ -269,13 +275,12 @@ OnSourceGrabEventAfter(GtkWidget *widget - } - - static GtkWindow* --GetGtkWindow(nsIDOMDocument *aDocument) -+GetGtkWindow(nsIDocument *aDocument) - { -- nsCOMPtr doc = do_QueryInterface(aDocument); -- if (!doc) -+ if (!aDocument) - return nullptr; - -- nsCOMPtr presShell = doc->GetShell(); -+ nsCOMPtr presShell = aDocument->GetShell(); - if (!presShell) - return nullptr; - -@@ -304,10 +309,9 @@ GetGtkWindow(nsIDOMDocument *aDocument) - // nsIDragService - - NS_IMETHODIMP --nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode, -+nsDragService::InvokeDragSession(nsINode *aDOMNode, - const nsACString& aPrincipalURISpec, - nsIArray * aArrayTransferables, -- nsIScriptableRegion * aRegion, - uint32_t aActionType, - nsContentPolicyType aContentPolicyType = - nsIContentPolicy::TYPE_OTHER) -@@ -323,14 +327,14 @@ nsDragService::InvokeDragSession(nsIDOMN - - return nsBaseDragService::InvokeDragSession(aDOMNode, aPrincipalURISpec, - aArrayTransferables, -- aRegion, aActionType, -+ aActionType, - aContentPolicyType); - } - - // nsBaseDragService - nsresult - nsDragService::InvokeDragSessionImpl(nsIArray* aArrayTransferables, -- nsIScriptableRegion* aRegion, -+ const Maybe& aRegion, - uint32_t aActionType) - { - // make sure that we have an array of transferables to use -@@ -346,9 +350,6 @@ nsDragService::InvokeDragSessionImpl(nsI - if (!sourceList) - return NS_OK; - -- // stored temporarily until the drag-begin signal has been received -- mSourceRegion = aRegion; -- - // save our action type - GdkDragAction action = GDK_ACTION_DEFAULT; - -@@ -391,8 +392,6 @@ nsDragService::InvokeDragSessionImpl(nsI - 1, - &event); - -- mSourceRegion = nullptr; -- - nsresult rv; - if (context) { - StartDragSession(); -@@ -516,6 +515,9 @@ nsDragService::EndDragSession(bool aDone +@@ -516,6 +522,9 @@ nsDragService::EndDragSession(bool aDone // We're done with the drag context. mTargetDragContextForRemote = nullptr; @@ -3180,7 +1067,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. return nsBaseDragService::EndDragSession(aDoneDrag, aKeyModifiers); } -@@ -636,6 +638,14 @@ nsDragService::GetNumDropItems(uint32_t +@@ -636,6 +645,14 @@ nsDragService::GetNumDropItems(uint32_t return NS_OK; } @@ -3195,7 +1082,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. bool isList = IsTargetContextList(); if (isList) mSourceDataItems->GetLength(aNumItems); -@@ -1027,9 +1037,18 @@ nsDragService::IsDataFlavorSupported(con +@@ -1027,9 +1044,18 @@ nsDragService::IsDataFlavorSupported(con } // check the target context vs. this flavor, one at a time @@ -3217,7 +1104,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. /* Bug 331198 */ GdkAtom atom = GDK_POINTER_TO_ATOM(tmp->data); gchar *name = nullptr; -@@ -1074,6 +1093,15 @@ nsDragService::IsDataFlavorSupported(con +@@ -1074,6 +1100,15 @@ nsDragService::IsDataFlavorSupported(con } g_free(name); } @@ -3233,7 +1120,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. return NS_OK; } -@@ -1105,6 +1133,36 @@ nsDragService::ReplyToDragMotion(GdkDrag +@@ -1105,6 +1140,36 @@ nsDragService::ReplyToDragMotion(GdkDrag gdk_drag_status(aDragContext, action, mTargetTime); } @@ -3270,7 +1157,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. void nsDragService::TargetDataReceived(GtkWidget *aWidget, GdkDragContext *aContext, -@@ -1136,6 +1194,12 @@ nsDragService::IsTargetContextList(void) +@@ -1136,6 +1201,12 @@ nsDragService::IsTargetContextList(void) { bool retval = false; @@ -3283,7 +1170,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // gMimeListType drags only work for drags within a single process. The // gtk_drag_get_source_widget() function will return nullptr if the source // of the drag is another app, so we use it to check if a gMimeListType -@@ -1174,17 +1238,28 @@ nsDragService::GetTargetDragData(GdkAtom +@@ -1174,17 +1245,28 @@ nsDragService::GetTargetDragData(GdkAtom mTargetDragContext.get())); // reset our target data areas TargetResetData(); @@ -3321,7 +1208,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. MOZ_LOG(sDragLm, LogLevel::Debug, ("finished inner iteration\n")); } -@@ -1435,7 +1510,7 @@ nsDragService::SourceEndDragSession(GdkD +@@ -1435,7 +1517,7 @@ nsDragService::SourceEndDragSession(GdkD } // Schedule the appropriate drag end dom events. @@ -3330,18 +1217,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. } static void -@@ -1642,8 +1717,8 @@ void nsDragService::SetDragIcon(GdkDragC - LayoutDeviceIntRect dragRect; - nsPresContext* pc; - RefPtr surface; -- DrawDrag(mSourceNode, mSourceRegion, mScreenPosition, -- &dragRect, &surface, &pc); -+ DrawDrag(mSourceNode, mRegion, -+ mScreenPosition, &dragRect, &surface, &pc); - if (!pc) - return; - -@@ -1785,9 +1860,10 @@ invisibleSourceDragEnd(GtkWidget +@@ -1785,9 +1867,10 @@ invisibleSourceDragEnd(GtkWidget gboolean nsDragService::ScheduleMotionEvent(nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3353,7 +1229,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // The drag source has sent another motion message before we've // replied to the previous. That shouldn't happen with Xdnd. The // spec for Motif drags is less clear, but we'll just update the -@@ -1798,7 +1874,7 @@ nsDragService::ScheduleMotionEvent(nsWin +@@ -1798,7 +1881,7 @@ nsDragService::ScheduleMotionEvent(nsWin // Returning TRUE means we'll reply with a status message, unless we first // get a leave. @@ -3362,7 +1238,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. aWindowPoint, aTime); } -@@ -1808,7 +1884,8 @@ nsDragService::ScheduleLeaveEvent() +@@ -1808,7 +1891,8 @@ nsDragService::ScheduleLeaveEvent() // We don't know at this stage whether a drop signal will immediately // follow. If the drop signal gets sent it will happen before we return // to the main loop and the scheduled leave task will be replaced. @@ -3372,7 +1248,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. NS_WARNING("Drag leave after drop"); } } -@@ -1816,10 +1893,11 @@ nsDragService::ScheduleLeaveEvent() +@@ -1816,10 +1900,11 @@ nsDragService::ScheduleLeaveEvent() gboolean nsDragService::ScheduleDropEvent(nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3385,7 +1261,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. NS_WARNING("Additional drag drop ignored"); return FALSE; } -@@ -1833,6 +1911,7 @@ nsDragService::ScheduleDropEvent(nsWindo +@@ -1833,6 +1918,7 @@ nsDragService::ScheduleDropEvent(nsWindo gboolean nsDragService::Schedule(DragTask aTask, nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3393,7 +1269,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. LayoutDeviceIntPoint aWindowPoint, guint aTime) { // If there is an existing leave or motion task scheduled, then that -@@ -1851,6 +1930,9 @@ nsDragService::Schedule(DragTask aTask, +@@ -1851,6 +1937,9 @@ nsDragService::Schedule(DragTask aTask, mScheduledTask = aTask; mPendingWindow = aWindow; mPendingDragContext = aDragContext; @@ -3403,7 +1279,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. mPendingWindowPoint = aWindowPoint; mPendingTime = aTime; -@@ -1927,6 +2009,9 @@ nsDragService::RunScheduledTask() +@@ -1927,6 +2016,9 @@ nsDragService::RunScheduledTask() // succeeed. mTargetWidget = mTargetWindow->GetMozContainerWidget(); mTargetDragContext.steal(mPendingDragContext); @@ -3413,7 +1289,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. mTargetTime = mPendingTime; // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model -@@ -1958,10 +2043,20 @@ nsDragService::RunScheduledTask() +@@ -1958,10 +2050,20 @@ nsDragService::RunScheduledTask() if (task == eDragTaskMotion) { if (TakeDragEventDispatchedToChildProcess()) { mTargetDragContextForRemote = mTargetDragContext; @@ -3435,7 +1311,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. } } } -@@ -1972,8 +2067,10 @@ nsDragService::RunScheduledTask() +@@ -1972,8 +2074,10 @@ nsDragService::RunScheduledTask() // Perhaps we should set the del parameter to TRUE when the drag // action is move, but we don't know whether the data was successfully // transferred. @@ -3448,7 +1324,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // This drag is over, so clear out our reference to the previous // window. -@@ -1986,6 +2083,9 @@ nsDragService::RunScheduledTask() +@@ -1986,6 +2090,9 @@ nsDragService::RunScheduledTask() // We're done with the drag context. mTargetWidget = nullptr; mTargetDragContext = nullptr; @@ -3458,7 +1334,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // If we got another drag signal while running the sheduled task, that // must have happened while running a nested event loop. Leave the task -@@ -2015,7 +2115,16 @@ nsDragService::UpdateDragAction() +@@ -2015,7 +2122,16 @@ nsDragService::UpdateDragAction() // default is to do nothing int action = nsIDragService::DRAGDROP_ACTION_NONE; @@ -3476,7 +1352,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. // set the default just in case nothing matches below if (gdkAction & GDK_ACTION_DEFAULT) -@@ -2044,6 +2153,12 @@ nsDragService::UpdateDragEffect() +@@ -2044,6 +2160,12 @@ nsDragService::UpdateDragEffect() ReplyToDragMotion(mTargetDragContextForRemote); mTargetDragContextForRemote = nullptr; } @@ -3491,7 +1367,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.cpp.wayland thunderbird-60. diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3.0/widget/gtk/nsDragService.h --- thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland 2018-10-30 12:45:37.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsDragService.h 2018-11-20 12:04:43.736787353 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsDragService.h 2018-11-21 13:42:00.759025657 +0100 @@ -14,6 +14,7 @@ #include @@ -3500,23 +1376,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. namespace mozilla { namespace gfx { -@@ -60,13 +61,12 @@ public: - - // nsBaseDragService - virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables, -- nsIScriptableRegion* aRegion, -+ const mozilla::Maybe& aRegion, - uint32_t aActionType) override; - // nsIDragService -- NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, -+ NS_IMETHOD InvokeDragSession (nsINode *aDOMNode, - const nsACString& aPrincipalURISpec, - nsIArray * anArrayTransferables, -- nsIScriptableRegion * aRegion, - uint32_t aActionType, - nsContentPolicyType aContentPolicyType) override; - NS_IMETHOD StartDragSession() override; -@@ -98,11 +98,13 @@ public: +@@ -98,11 +99,13 @@ public: gboolean ScheduleMotionEvent(nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3530,7 +1390,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime); -@@ -158,6 +160,9 @@ private: +@@ -158,6 +161,9 @@ private: RefPtr mPendingWindow; mozilla::LayoutDeviceIntPoint mPendingWindowPoint; nsCountedRef mPendingDragContext; @@ -3540,7 +1400,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. guint mPendingTime; // mTargetWindow and mTargetWindowPoint record the position of the last -@@ -169,9 +174,15 @@ private: +@@ -169,9 +175,15 @@ private: // motion or drop events. mTime records the corresponding timestamp. nsCountedRef mTargetWidget; nsCountedRef mTargetDragContext; @@ -3556,16 +1416,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. guint mTargetTime; // is it OK to drop on us? -@@ -197,8 +208,6 @@ private: - // our source data items - nsCOMPtr mSourceDataItems; - -- nsCOMPtr mSourceRegion; -- - // get a list of the sources in gtk's format - GtkTargetList *GetSourceList(void); - -@@ -212,6 +221,7 @@ private: +@@ -212,6 +224,7 @@ private: gboolean Schedule(DragTask aTask, nsWindow *aWindow, GdkDragContext *aDragContext, @@ -3573,7 +1424,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime); // Callback for g_idle_add_full() to run mScheduledTask. -@@ -220,9 +230,11 @@ private: +@@ -220,9 +233,11 @@ private: void UpdateDragAction(); void DispatchMotionEvents(); void ReplyToDragMotion(GdkDragContext* aDragContext); @@ -3586,21 +1437,9 @@ diff -up thunderbird-60.3.0/widget/gtk/nsDragService.h.wayland thunderbird-60.3. #endif // nsDragService_h__ - -diff -up thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp.wayland thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp ---- thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsFilePicker.cpp 2018-11-20 12:04:43.736787353 +0100 -@@ -346,7 +346,7 @@ nsFilePicker::GetFiles(nsISimpleEnumerat - NS_ENSURE_ARG_POINTER(aFiles); - - if (mMode == nsIFilePicker::modeOpenMultiple) { -- return NS_NewArrayEnumerator(aFiles, mFiles); -+ return NS_NewArrayEnumerator(aFiles, mFiles, NS_GET_IID(nsIFile)); - } - - return NS_ERROR_FAILURE; diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp --- thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp 2018-11-20 12:04:43.736787353 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp 2018-11-21 13:42:00.760025653 +0100 @@ -28,6 +28,10 @@ #include "mozilla/MouseEvents.h" #include "mozilla/TextEvents.h" @@ -3847,44 +1686,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland thunderbird-60. KeymapWrapper::~KeymapWrapper() { gdk_window_remove_filter(nullptr, FilterEvents, this); -@@ -931,14 +1141,19 @@ KeymapWrapper::ComputeDOMCodeNameIndex(c - - /* static */ void - KeymapWrapper::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, -- GdkEventKey* aGdkKeyEvent) -+ GdkEventKey* aGdkKeyEvent, -+ bool aIsProcessedByIME) - { -+ MOZ_ASSERT(!aIsProcessedByIME || aKeyEvent.mMessage != eKeyPress, -+ "If the key event is handled by IME, keypress event shouldn't be fired"); -+ - KeymapWrapper* keymapWrapper = GetInstance(); - - aKeyEvent.mCodeNameIndex = ComputeDOMCodeNameIndex(aGdkKeyEvent); - MOZ_ASSERT(aKeyEvent.mCodeNameIndex != CODE_NAME_INDEX_USE_STRING); - aKeyEvent.mKeyNameIndex = -- keymapWrapper->ComputeDOMKeyNameIndex(aGdkKeyEvent); -+ aIsProcessedByIME ? KEY_NAME_INDEX_Process : -+ keymapWrapper->ComputeDOMKeyNameIndex(aGdkKeyEvent); - if (aKeyEvent.mKeyNameIndex == KEY_NAME_INDEX_Unidentified) { - uint32_t charCode = GetCharCodeFor(aGdkKeyEvent); - if (!charCode) { -@@ -951,10 +1166,11 @@ KeymapWrapper::InitKeyEvent(WidgetKeyboa - AppendUCS4ToUTF16(charCode, aKeyEvent.mKeyValue); - } - } -- aKeyEvent.mKeyCode = ComputeDOMKeyCode(aGdkKeyEvent); - -- if (aKeyEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING || -- aKeyEvent.mMessage != eKeyPress) { -+ if (aIsProcessedByIME) { -+ aKeyEvent.mKeyCode = NS_VK_PROCESSKEY; -+ } else if (aKeyEvent.mKeyNameIndex != KEY_NAME_INDEX_USE_STRING || -+ aKeyEvent.mMessage != eKeyPress) { - aKeyEvent.mKeyCode = ComputeDOMKeyCode(aGdkKeyEvent); - } else { - aKeyEvent.mKeyCode = 0; -@@ -1405,6 +1621,14 @@ void +@@ -1405,6 +1615,14 @@ void KeymapWrapper::WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent, GdkEventKey* aGdkKeyEvent) { @@ -3901,7 +1703,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.cpp.wayland thunderbird-60. MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h --- thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h 2018-11-20 12:04:43.737787350 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h 2018-11-21 13:42:00.760025653 +0100 @@ -13,6 +13,10 @@ #include @@ -3913,20 +1715,15 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.3. namespace mozilla { namespace widget { -@@ -131,9 +135,11 @@ public: +@@ -131,6 +135,7 @@ public: * @param aKeyEvent It's an WidgetKeyboardEvent which needs to be * initialized. * @param aGdkKeyEvent A native GDK key event. + * @param aIsProcessedByIME true if aGdkKeyEvent is handled by IME. */ static void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, -- GdkEventKey* aGdkKeyEvent); -+ GdkEventKey* aGdkKeyEvent, -+ bool aIsProcessedByIME); - - /** - * WillDispatchKeyboardEvent() is called via -@@ -148,6 +154,14 @@ public: + GdkEventKey* aGdkKeyEvent); +@@ -148,6 +153,14 @@ public: static void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyEvent, GdkEventKey* aGdkKeyEvent); @@ -3941,7 +1738,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.3. /** * Destroys the singleton KeymapWrapper instance, if it exists. */ -@@ -172,7 +186,10 @@ protected: +@@ -172,7 +185,10 @@ protected: */ void Init(); void InitXKBExtension(); @@ -3953,7 +1750,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.3. /** * mModifierKeys stores each hardware key information. -@@ -374,6 +391,15 @@ protected: +@@ -374,6 +390,15 @@ protected: */ void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent, GdkEventKey* aGdkKeyEvent); @@ -3971,16 +1768,8 @@ diff -up thunderbird-60.3.0/widget/gtk/nsGtkKeyUtils.h.wayland thunderbird-60.3. } // namespace widget diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp --- thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp 2018-11-20 12:04:43.737787350 +0100 -@@ -18,6 +18,7 @@ - - #include - #include "gfxPlatformGtk.h" -+#include "mozilla/FontPropertyTypes.h" - #include "ScreenHelperGTK.h" - - #include "gtkdrawing.h" -@@ -31,7 +32,9 @@ ++++ thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp 2018-11-21 13:42:00.760025653 +0100 +@@ -31,7 +31,9 @@ #include #include "WidgetStyleCache.h" #include "prenv.h" @@ -3990,7 +1779,7 @@ 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 +185,7 @@ GetBorderColors(GtkStyleContext* aContex +@@ -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; @@ -3999,7 +1788,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60. visible = border.top != 0 || border.right != 0 || border.bottom != 0 || border.left != 0; } -@@ -213,6 +216,58 @@ GetBorderColors(GtkStyleContext* aContex +@@ -213,6 +215,58 @@ GetBorderColors(GtkStyleContext* aContex return ret; } @@ -4058,7 +1847,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60. void nsLookAndFeel::NativeInit() { -@@ -269,7 +324,6 @@ nsLookAndFeel::NativeGetColor(ColorID aI +@@ -269,7 +323,6 @@ nsLookAndFeel::NativeGetColor(ColorID aI case eColorID_IMESelectedRawTextBackground: case eColorID_IMESelectedConvertedTextBackground: case eColorID__moz_dragtargetzone: @@ -4066,7 +1855,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60. case eColorID__moz_html_cellhighlight: case eColorID_highlight: // preference selected item, aColor = mTextSelectedBackground; -@@ -279,10 +333,15 @@ nsLookAndFeel::NativeGetColor(ColorID aI +@@ -279,10 +332,15 @@ nsLookAndFeel::NativeGetColor(ColorID aI case eColorID_IMESelectedRawTextForeground: case eColorID_IMESelectedConvertedTextForeground: case eColorID_highlighttext: @@ -4083,47 +1872,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60. case eColorID_Widget3DHighlight: aColor = NS_RGB(0xa0,0xa0,0xa0); break; -@@ -668,6 +727,17 @@ nsLookAndFeel::GetIntImpl(IntID aID, int - EnsureInit(); - aResult = mCSDCloseButton; - break; -+ case eIntID_PrefersReducedMotion: { -+ GtkSettings *settings; -+ gboolean enableAnimations; -+ -+ settings = gtk_settings_get_default(); -+ g_object_get(settings, -+ "gtk-enable-animations", -+ &enableAnimations, nullptr); -+ aResult = enableAnimations ? 0 : 1; -+ break; -+ } - default: - aResult = 0; - res = NS_ERROR_FAILURE; -@@ -708,7 +778,7 @@ GetSystemFontInfo(GtkStyleContext *aStyl - nsString *aFontName, - gfxFontStyle *aFontStyle) - { -- aFontStyle->style = NS_FONT_STYLE_NORMAL; -+ aFontStyle->style = FontSlantStyle::Normal(); - - // As in - // https://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?h=3.22.19#n10333 -@@ -722,10 +792,10 @@ GetSystemFontInfo(GtkStyleContext *aStyl - NS_ConvertUTF8toUTF16 family(pango_font_description_get_family(desc)); - *aFontName = quote + family + quote; - -- aFontStyle->weight = pango_font_description_get_weight(desc); -+ aFontStyle->weight = FontWeight(pango_font_description_get_weight(desc)); - - // FIXME: Set aFontStyle->stretch correctly! -- aFontStyle->stretch = NS_FONT_STRETCH_NORMAL; -+ aFontStyle->stretch = FontStretch::Normal(); - - float size = float(pango_font_description_get_size(desc)) / PANGO_SCALE; - -@@ -1009,6 +1079,9 @@ nsLookAndFeel::EnsureInit() +@@ -1009,6 +1067,9 @@ nsLookAndFeel::EnsureInit() mOddCellBackground = GDK_RGBA_TO_NS_RGBA(color); gtk_style_context_restore(style); @@ -4135,7 +1884,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.cpp.wayland thunderbird-60. // root node, so check the root node if no border is found on the border diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h.wayland thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h --- thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h 2018-11-20 12:04:43.737787350 +0100 ++++ 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; @@ -4154,1888 +1903,10 @@ diff -up thunderbird-60.3.0/widget/gtk/nsLookAndFeel.h.wayland thunderbird-60.3. + nsresult InitCellHighlightColors(); }; - #endif -diff -up thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp.wayland thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp ---- thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.cpp 2018-11-20 12:04:43.738787347 +0100 -@@ -4,7 +4,7 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - #include "nsNativeThemeGTK.h" --#include "nsThemeConstants.h" -+#include "nsStyleConsts.h" - #include "gtkdrawing.h" - #include "ScreenHelperGTK.h" - -@@ -39,6 +39,8 @@ - #include "mozilla/gfx/HelpersCairo.h" - #include "mozilla/gfx/PathHelpers.h" - #include "mozilla/Preferences.h" -+#include "mozilla/layers/StackingContextHelper.h" -+#include "mozilla/StaticPrefs.h" - - #ifdef MOZ_X11 - # ifdef CAIRO_HAS_XLIB_SURFACE -@@ -119,7 +121,7 @@ nsNativeThemeGTK::Observe(nsISupports *a - if (!nsCRT::strcmp(aTopic, "xpcom-shutdown")) { - moz_gtk_shutdown(); - } else { -- NS_NOTREACHED("unexpected topic"); -+ MOZ_ASSERT_UNREACHABLE("unexpected topic"); - return NS_ERROR_UNEXPECTED; - } - -@@ -149,41 +151,43 @@ static bool IsFrameContentNodeInNamespac - return content->IsInNamespace(aNamespace); - } - --static bool IsWidgetTypeDisabled(uint8_t* aDisabledVector, uint8_t aWidgetType) { -- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); -- return (aDisabledVector[aWidgetType >> 3] & (1 << (aWidgetType & 7))) != 0; -+static bool IsWidgetTypeDisabled(uint8_t* aDisabledVector, StyleAppearance aWidgetType) { -+ auto type = static_cast(aWidgetType); -+ MOZ_ASSERT(type < static_cast(mozilla::StyleAppearance::Count)); -+ return (aDisabledVector[type >> 3] & (1 << (type & 7))) != 0; - } - --static void SetWidgetTypeDisabled(uint8_t* aDisabledVector, uint8_t aWidgetType) { -- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); -- aDisabledVector[aWidgetType >> 3] |= (1 << (aWidgetType & 7)); -+static void SetWidgetTypeDisabled(uint8_t* aDisabledVector, StyleAppearance aWidgetType) { -+ auto type = static_cast(aWidgetType); -+ MOZ_ASSERT(type < static_cast(mozilla::StyleAppearance::Count)); -+ aDisabledVector[type >> 3] |= (1 << (type & 7)); - } - - static inline uint16_t --GetWidgetStateKey(uint8_t aWidgetType, GtkWidgetState *aWidgetState) -+GetWidgetStateKey(StyleAppearance aWidgetType, GtkWidgetState *aWidgetState) - { - return (aWidgetState->active | - aWidgetState->focused << 1 | - aWidgetState->inHover << 2 | - aWidgetState->disabled << 3 | - aWidgetState->isDefault << 4 | -- aWidgetType << 5); -+ static_cast(aWidgetType) << 5); - } - - static bool IsWidgetStateSafe(uint8_t* aSafeVector, -- uint8_t aWidgetType, -- GtkWidgetState *aWidgetState) -+ StyleAppearance aWidgetType, -+ GtkWidgetState *aWidgetState) - { -- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); -+ MOZ_ASSERT(static_cast(aWidgetType) < static_cast(mozilla::StyleAppearance::Count)); - uint16_t key = GetWidgetStateKey(aWidgetType, aWidgetState); - return (aSafeVector[key >> 3] & (1 << (key & 7))) != 0; - } - - static void SetWidgetStateSafe(uint8_t *aSafeVector, -- uint8_t aWidgetType, -+ StyleAppearance aWidgetType, - GtkWidgetState *aWidgetState) - { -- MOZ_ASSERT(aWidgetType < ThemeWidgetType_COUNT); -+ MOZ_ASSERT(static_cast(aWidgetType) < static_cast(mozilla::StyleAppearance::Count)); - uint16_t key = GetWidgetStateKey(aWidgetType, aWidgetState); - aSafeVector[key >> 3] |= (1 << (key & 7)); - } -@@ -213,33 +217,38 @@ nsNativeThemeGTK::GetTabMarginPixels(nsI - } - - static bool ShouldScrollbarButtonBeDisabled(int32_t aCurpos, int32_t aMaxpos, -- uint8_t aWidgetType) -+ StyleAppearance aWidgetType) - { -- return ((aCurpos == 0 && (aWidgetType == NS_THEME_SCROLLBARBUTTON_UP || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT)) -- || (aCurpos == aMaxpos && (aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT))); -+ return ((aCurpos == 0 && (aWidgetType == StyleAppearance::ScrollbarbuttonUp || -+ aWidgetType == StyleAppearance::ScrollbarbuttonLeft)) -+ || (aCurpos == aMaxpos && (aWidgetType == StyleAppearance::ScrollbarbuttonDown || -+ aWidgetType == StyleAppearance::ScrollbarbuttonRight))); - } - - bool --nsNativeThemeGTK::GetGtkWidgetAndState(uint8_t aWidgetType, nsIFrame* aFrame, -+nsNativeThemeGTK::GetGtkWidgetAndState(StyleAppearance aWidgetType, nsIFrame* aFrame, - WidgetNodeType& aGtkWidgetType, - GtkWidgetState* aState, - gint* aWidgetFlags) - { -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } -+ - if (aState) { - // For XUL checkboxes and radio buttons, the state of the parent - // determines our state. - nsIFrame *stateFrame = aFrame; -- if (aFrame && ((aWidgetFlags && (aWidgetType == NS_THEME_CHECKBOX || -- aWidgetType == NS_THEME_RADIO)) || -- aWidgetType == NS_THEME_CHECKBOX_LABEL || -- aWidgetType == NS_THEME_RADIO_LABEL)) { -+ if (aFrame && ((aWidgetFlags && (aWidgetType == StyleAppearance::Checkbox || -+ aWidgetType == StyleAppearance::Radio)) || -+ aWidgetType == StyleAppearance::CheckboxLabel || -+ aWidgetType == StyleAppearance::RadioLabel)) { - - nsAtom* atom = nullptr; - if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) { -- if (aWidgetType == NS_THEME_CHECKBOX_LABEL || -- aWidgetType == NS_THEME_RADIO_LABEL) { -+ if (aWidgetType == StyleAppearance::CheckboxLabel || -+ aWidgetType == StyleAppearance::RadioLabel) { - // Adjust stateFrame so GetContentState finds the correct state. - stateFrame = aFrame = aFrame->GetParent()->GetParent(); - } else { -@@ -249,8 +258,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - if (aWidgetFlags) { - if (!atom) { -- atom = (aWidgetType == NS_THEME_CHECKBOX || -- aWidgetType == NS_THEME_CHECKBOX_LABEL) ? nsGkAtoms::checked -+ atom = (aWidgetType == StyleAppearance::Checkbox || -+ aWidgetType == StyleAppearance::CheckboxLabel) ? nsGkAtoms::checked - : nsGkAtoms::selected; - } - *aWidgetFlags = CheckBooleanAttr(aFrame, atom); -@@ -258,7 +267,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } else { - if (aWidgetFlags) { - *aWidgetFlags = 0; -- HTMLInputElement* inputElt = HTMLInputElement::FromContent(aFrame->GetContent()); -+ HTMLInputElement* inputElt = HTMLInputElement::FromNode(aFrame->GetContent()); - if (inputElt && inputElt->Checked()) - *aWidgetFlags |= MOZ_GTK_WIDGET_CHECKED; - -@@ -266,12 +275,12 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - *aWidgetFlags |= MOZ_GTK_WIDGET_INCONSISTENT; - } - } -- } else if (aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN || -- aWidgetType == NS_THEME_TREEHEADERSORTARROW || -- aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS || -- aWidgetType == NS_THEME_BUTTON_ARROW_NEXT || -- aWidgetType == NS_THEME_BUTTON_ARROW_UP || -- aWidgetType == NS_THEME_BUTTON_ARROW_DOWN) { -+ } else if (aWidgetType == StyleAppearance::ToolbarbuttonDropdown || -+ aWidgetType == StyleAppearance::Treeheadersortarrow || -+ aWidgetType == StyleAppearance::ButtonArrowPrevious || -+ aWidgetType == StyleAppearance::ButtonArrowNext || -+ aWidgetType == StyleAppearance::ButtonArrowUp || -+ aWidgetType == StyleAppearance::ButtonArrowDown) { - // The state of an arrow comes from its parent. - stateFrame = aFrame = aFrame->GetParent(); - } -@@ -287,7 +296,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - aState->canDefault = FALSE; // XXX fix me - aState->depressed = FALSE; - -- if (aWidgetType == NS_THEME_FOCUS_OUTLINE) { -+ if (aWidgetType == StyleAppearance::FocusOutline) { - aState->disabled = FALSE; - aState->active = FALSE; - aState->inHover = FALSE; -@@ -296,15 +305,16 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - aState->focused = TRUE; - aState->depressed = TRUE; // see moz_gtk_entry_paint() -- } else if (aWidgetType == NS_THEME_BUTTON || -- aWidgetType == NS_THEME_TOOLBARBUTTON || -- aWidgetType == NS_THEME_DUALBUTTON || -- aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN || -- aWidgetType == NS_THEME_MENULIST || -- aWidgetType == NS_THEME_MENULIST_BUTTON) { -+ } else if (aWidgetType == StyleAppearance::Button || -+ aWidgetType == StyleAppearance::Toolbarbutton || -+ aWidgetType == StyleAppearance::Dualbutton || -+ aWidgetType == StyleAppearance::ToolbarbuttonDropdown || -+ aWidgetType == StyleAppearance::Menulist || -+ aWidgetType == StyleAppearance::MenulistButton || -+ aWidgetType == StyleAppearance::MozMenulistButton) { - aState->active &= aState->inHover; -- } else if (aWidgetType == NS_THEME_TREETWISTY || -- aWidgetType == NS_THEME_TREETWISTYOPEN) { -+ } else if (aWidgetType == StyleAppearance::Treetwisty || -+ aWidgetType == StyleAppearance::Treetwistyopen) { - nsTreeBodyFrame *treeBodyFrame = do_QueryFrame(aFrame); - if (treeBodyFrame) { - const mozilla::AtomArray& atoms = -@@ -318,22 +328,22 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - // For these widget types, some element (either a child or parent) - // actually has element focus, so we check the focused attribute - // to see whether to draw in the focused state. -- if (aWidgetType == NS_THEME_NUMBER_INPUT || -- aWidgetType == NS_THEME_TEXTFIELD || -- aWidgetType == NS_THEME_TEXTFIELD_MULTILINE || -- aWidgetType == NS_THEME_MENULIST_TEXTFIELD || -- aWidgetType == NS_THEME_SPINNER_TEXTFIELD || -- aWidgetType == NS_THEME_RADIO_CONTAINER || -- aWidgetType == NS_THEME_RADIO_LABEL) { -+ if (aWidgetType == StyleAppearance::NumberInput || -+ aWidgetType == StyleAppearance::Textfield || -+ aWidgetType == StyleAppearance::TextfieldMultiline || -+ aWidgetType == StyleAppearance::MenulistTextfield || -+ aWidgetType == StyleAppearance::SpinnerTextfield || -+ aWidgetType == StyleAppearance::RadioContainer || -+ aWidgetType == StyleAppearance::RadioLabel) { - aState->focused = IsFocused(aFrame); -- } else if (aWidgetType == NS_THEME_RADIO || -- aWidgetType == NS_THEME_CHECKBOX) { -+ } else if (aWidgetType == StyleAppearance::Radio || -+ aWidgetType == StyleAppearance::Checkbox) { - // In XUL, checkboxes and radios shouldn't have focus rings, their labels do - aState->focused = FALSE; - } - -- if (aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL || -- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL) { -+ if (aWidgetType == StyleAppearance::ScrollbarthumbVertical || -+ aWidgetType == StyleAppearance::ScrollbarthumbHorizontal) { - // for scrollbars we need to go up two to go from the thumb to - // the slider to the actual scrollbar object - nsIFrame *tmpFrame = aFrame->GetParent()->GetParent(); -@@ -348,10 +358,10 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - } - -- if (aWidgetType == NS_THEME_SCROLLBARBUTTON_UP || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) { -+ if (aWidgetType == StyleAppearance::ScrollbarbuttonUp || -+ aWidgetType == StyleAppearance::ScrollbarbuttonDown || -+ aWidgetType == StyleAppearance::ScrollbarbuttonLeft || -+ aWidgetType == StyleAppearance::ScrollbarbuttonRight) { - // set the state to disabled when the scrollbar is scrolled to - // the beginning or the end, depending on the button type. - int32_t curpos = CheckIntAttr(aFrame, nsGkAtoms::curpos, 0); -@@ -369,7 +379,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - if (aWidgetFlags) { - *aWidgetFlags = GetScrollbarButtonType(aFrame); -- if (aWidgetType - NS_THEME_SCROLLBARBUTTON_UP < 2) -+ if (static_cast(aWidgetType) - -+ static_cast(StyleAppearance::ScrollbarbuttonUp) < 2) - *aWidgetFlags |= MOZ_GTK_STEPPER_VERTICAL; - } - } -@@ -379,11 +390,11 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - // menus which are children of a menu bar are only marked as prelight - // if they are open, not on normal hover. - -- if (aWidgetType == NS_THEME_MENUITEM || -- aWidgetType == NS_THEME_CHECKMENUITEM || -- aWidgetType == NS_THEME_RADIOMENUITEM || -- aWidgetType == NS_THEME_MENUSEPARATOR || -- aWidgetType == NS_THEME_MENUARROW) { -+ if (aWidgetType == StyleAppearance::Menuitem || -+ aWidgetType == StyleAppearance::Checkmenuitem || -+ aWidgetType == StyleAppearance::Radiomenuitem || -+ aWidgetType == StyleAppearance::Menuseparator || -+ aWidgetType == StyleAppearance::Menuarrow) { - bool isTopLevel = false; - nsMenuFrame *menuFrame = do_QueryFrame(aFrame); - if (menuFrame) { -@@ -398,8 +409,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - aState->active = FALSE; - -- if (aWidgetType == NS_THEME_CHECKMENUITEM || -- aWidgetType == NS_THEME_RADIOMENUITEM) { -+ if (aWidgetType == StyleAppearance::Checkmenuitem || -+ aWidgetType == StyleAppearance::Radiomenuitem) { - *aWidgetFlags = 0; - if (aFrame && aFrame->GetContent() && - aFrame->GetContent()->IsElement()) { -@@ -412,12 +423,13 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - // A button with drop down menu open or an activated toggle button - // should always appear depressed. -- if (aWidgetType == NS_THEME_BUTTON || -- aWidgetType == NS_THEME_TOOLBARBUTTON || -- aWidgetType == NS_THEME_DUALBUTTON || -- aWidgetType == NS_THEME_TOOLBARBUTTON_DROPDOWN || -- aWidgetType == NS_THEME_MENULIST || -- aWidgetType == NS_THEME_MENULIST_BUTTON) { -+ if (aWidgetType == StyleAppearance::Button || -+ aWidgetType == StyleAppearance::Toolbarbutton || -+ aWidgetType == StyleAppearance::Dualbutton || -+ aWidgetType == StyleAppearance::ToolbarbuttonDropdown || -+ aWidgetType == StyleAppearance::Menulist || -+ aWidgetType == StyleAppearance::MenulistButton || -+ aWidgetType == StyleAppearance::MozMenulistButton) { - bool menuOpen = IsOpenButton(aFrame); - aState->depressed = IsCheckedButton(aFrame) || menuOpen; - // we must not highlight buttons with open drop down menus on hover. -@@ -426,79 +438,81 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - - // When the input field of the drop down button has focus, some themes - // should draw focus for the drop down button as well. -- if (aWidgetType == NS_THEME_MENULIST_BUTTON && aWidgetFlags) { -+ if ((aWidgetType == StyleAppearance::MenulistButton || -+ aWidgetType == StyleAppearance::MozMenulistButton) && -+ aWidgetFlags) { - *aWidgetFlags = CheckBooleanAttr(aFrame, nsGkAtoms::parentfocused); - } - } - } - - switch (aWidgetType) { -- case NS_THEME_BUTTON: -+ case StyleAppearance::Button: - if (aWidgetFlags) - *aWidgetFlags = GTK_RELIEF_NORMAL; - aGtkWidgetType = MOZ_GTK_BUTTON; - break; -- case NS_THEME_TOOLBARBUTTON: -- case NS_THEME_DUALBUTTON: -+ case StyleAppearance::Toolbarbutton: -+ case StyleAppearance::Dualbutton: - if (aWidgetFlags) - *aWidgetFlags = GTK_RELIEF_NONE; - aGtkWidgetType = MOZ_GTK_TOOLBAR_BUTTON; - break; -- case NS_THEME_FOCUS_OUTLINE: -+ case StyleAppearance::FocusOutline: - aGtkWidgetType = MOZ_GTK_ENTRY; - break; -- case NS_THEME_CHECKBOX: -- case NS_THEME_RADIO: -- aGtkWidgetType = (aWidgetType == NS_THEME_RADIO) ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON; -- break; -- case NS_THEME_SCROLLBARBUTTON_UP: -- case NS_THEME_SCROLLBARBUTTON_DOWN: -- case NS_THEME_SCROLLBARBUTTON_LEFT: -- case NS_THEME_SCROLLBARBUTTON_RIGHT: -+ case StyleAppearance::Checkbox: -+ case StyleAppearance::Radio: -+ aGtkWidgetType = (aWidgetType == StyleAppearance::Radio) ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON; -+ break; -+ case StyleAppearance::ScrollbarbuttonUp: -+ case StyleAppearance::ScrollbarbuttonDown: -+ case StyleAppearance::ScrollbarbuttonLeft: -+ case StyleAppearance::ScrollbarbuttonRight: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_BUTTON; - break; -- case NS_THEME_SCROLLBAR_VERTICAL: -+ case StyleAppearance::ScrollbarVertical: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_VERTICAL; - if (GetWidgetTransparency(aFrame, aWidgetType) == eOpaque) - *aWidgetFlags = MOZ_GTK_TRACK_OPAQUE; - else - *aWidgetFlags = 0; - break; -- case NS_THEME_SCROLLBAR_HORIZONTAL: -+ case StyleAppearance::ScrollbarHorizontal: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_HORIZONTAL; - if (GetWidgetTransparency(aFrame, aWidgetType) == eOpaque) - *aWidgetFlags = MOZ_GTK_TRACK_OPAQUE; - else - *aWidgetFlags = 0; - break; -- case NS_THEME_SCROLLBARTRACK_HORIZONTAL: -+ case StyleAppearance::ScrollbartrackHorizontal: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL; - break; -- case NS_THEME_SCROLLBARTRACK_VERTICAL: -+ case StyleAppearance::ScrollbartrackVertical: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL; - break; -- case NS_THEME_SCROLLBARTHUMB_VERTICAL: -+ case StyleAppearance::ScrollbarthumbVertical: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL; - break; -- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: -+ case StyleAppearance::ScrollbarthumbHorizontal: - aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; - break; -- case NS_THEME_INNER_SPIN_BUTTON: -+ case StyleAppearance::InnerSpinButton: - aGtkWidgetType = MOZ_GTK_INNER_SPIN_BUTTON; - break; -- case NS_THEME_SPINNER: -+ case StyleAppearance::Spinner: - aGtkWidgetType = MOZ_GTK_SPINBUTTON; - break; -- case NS_THEME_SPINNER_UPBUTTON: -+ case StyleAppearance::SpinnerUpbutton: - aGtkWidgetType = MOZ_GTK_SPINBUTTON_UP; - break; -- case NS_THEME_SPINNER_DOWNBUTTON: -+ case StyleAppearance::SpinnerDownbutton: - aGtkWidgetType = MOZ_GTK_SPINBUTTON_DOWN; - break; -- case NS_THEME_SPINNER_TEXTFIELD: -+ case StyleAppearance::SpinnerTextfield: - aGtkWidgetType = MOZ_GTK_SPINBUTTON_ENTRY; - break; -- case NS_THEME_RANGE: -+ case StyleAppearance::Range: - { - if (IsRangeHorizontal(aFrame)) { - if (aWidgetFlags) -@@ -511,7 +525,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - break; - } -- case NS_THEME_RANGE_THUMB: -+ case StyleAppearance::RangeThumb: - { - if (IsRangeHorizontal(aFrame)) { - if (aWidgetFlags) -@@ -524,51 +538,51 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - break; - } -- case NS_THEME_SCALE_HORIZONTAL: -+ case StyleAppearance::ScaleHorizontal: - if (aWidgetFlags) - *aWidgetFlags = GTK_ORIENTATION_HORIZONTAL; - aGtkWidgetType = MOZ_GTK_SCALE_HORIZONTAL; - break; -- case NS_THEME_SCALETHUMB_HORIZONTAL: -+ case StyleAppearance::ScalethumbHorizontal: - if (aWidgetFlags) - *aWidgetFlags = GTK_ORIENTATION_HORIZONTAL; - aGtkWidgetType = MOZ_GTK_SCALE_THUMB_HORIZONTAL; - break; -- case NS_THEME_SCALE_VERTICAL: -+ case StyleAppearance::ScaleVertical: - if (aWidgetFlags) - *aWidgetFlags = GTK_ORIENTATION_VERTICAL; - aGtkWidgetType = MOZ_GTK_SCALE_VERTICAL; - break; -- case NS_THEME_SEPARATOR: -+ case StyleAppearance::Separator: - aGtkWidgetType = MOZ_GTK_TOOLBAR_SEPARATOR; - break; -- case NS_THEME_SCALETHUMB_VERTICAL: -+ case StyleAppearance::ScalethumbVertical: - if (aWidgetFlags) - *aWidgetFlags = GTK_ORIENTATION_VERTICAL; - aGtkWidgetType = MOZ_GTK_SCALE_THUMB_VERTICAL; - break; -- case NS_THEME_TOOLBARGRIPPER: -+ case StyleAppearance::Toolbargripper: - aGtkWidgetType = MOZ_GTK_GRIPPER; - break; -- case NS_THEME_RESIZER: -+ case StyleAppearance::Resizer: - aGtkWidgetType = MOZ_GTK_RESIZER; - break; -- case NS_THEME_NUMBER_INPUT: -- case NS_THEME_TEXTFIELD: -+ case StyleAppearance::NumberInput: -+ case StyleAppearance::Textfield: - aGtkWidgetType = MOZ_GTK_ENTRY; - break; -- case NS_THEME_TEXTFIELD_MULTILINE: -+ case StyleAppearance::TextfieldMultiline: - #ifdef MOZ_WIDGET_GTK - aGtkWidgetType = MOZ_GTK_TEXT_VIEW; - #else - aGtkWidgetType = MOZ_GTK_ENTRY; - #endif - break; -- case NS_THEME_LISTBOX: -- case NS_THEME_TREEVIEW: -+ case StyleAppearance::Listbox: -+ case StyleAppearance::Treeview: - aGtkWidgetType = MOZ_GTK_TREEVIEW; - break; -- case NS_THEME_TREEHEADERCELL: -+ case StyleAppearance::Treeheadercell: - if (aWidgetFlags) { - // In this case, the flag denotes whether the header is the sorted one or not - if (GetTreeSortDirection(aFrame) == eTreeSortDirection_Natural) -@@ -578,7 +592,7 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - aGtkWidgetType = MOZ_GTK_TREE_HEADER_CELL; - break; -- case NS_THEME_TREEHEADERSORTARROW: -+ case StyleAppearance::Treeheadersortarrow: - if (aWidgetFlags) { - switch (GetTreeSortDirection(aFrame)) { - case eTreeSortDirection_Ascending: -@@ -598,74 +612,75 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - aGtkWidgetType = MOZ_GTK_TREE_HEADER_SORTARROW; - break; -- case NS_THEME_TREETWISTY: -+ case StyleAppearance::Treetwisty: - aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER; - if (aWidgetFlags) - *aWidgetFlags = GTK_EXPANDER_COLLAPSED; - break; -- case NS_THEME_TREETWISTYOPEN: -+ case StyleAppearance::Treetwistyopen: - aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER; - if (aWidgetFlags) - *aWidgetFlags = GTK_EXPANDER_EXPANDED; - break; -- case NS_THEME_MENULIST: -+ case StyleAppearance::Menulist: - aGtkWidgetType = MOZ_GTK_DROPDOWN; - if (aWidgetFlags) - *aWidgetFlags = IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XHTML); - break; -- case NS_THEME_MENULIST_TEXT: -+ case StyleAppearance::MenulistText: - return false; // nothing to do, but prevents the bg from being drawn -- case NS_THEME_MENULIST_TEXTFIELD: -+ case StyleAppearance::MenulistTextfield: - aGtkWidgetType = MOZ_GTK_DROPDOWN_ENTRY; - break; -- case NS_THEME_MENULIST_BUTTON: -+ case StyleAppearance::MenulistButton: -+ case StyleAppearance::MozMenulistButton: - aGtkWidgetType = MOZ_GTK_DROPDOWN_ARROW; - break; -- case NS_THEME_TOOLBARBUTTON_DROPDOWN: -- case NS_THEME_BUTTON_ARROW_DOWN: -- case NS_THEME_BUTTON_ARROW_UP: -- case NS_THEME_BUTTON_ARROW_NEXT: -- case NS_THEME_BUTTON_ARROW_PREVIOUS: -+ case StyleAppearance::ToolbarbuttonDropdown: -+ case StyleAppearance::ButtonArrowDown: -+ case StyleAppearance::ButtonArrowUp: -+ case StyleAppearance::ButtonArrowNext: -+ case StyleAppearance::ButtonArrowPrevious: - aGtkWidgetType = MOZ_GTK_TOOLBARBUTTON_ARROW; - if (aWidgetFlags) { - *aWidgetFlags = GTK_ARROW_DOWN; - -- if (aWidgetType == NS_THEME_BUTTON_ARROW_UP) -+ if (aWidgetType == StyleAppearance::ButtonArrowUp) - *aWidgetFlags = GTK_ARROW_UP; -- else if (aWidgetType == NS_THEME_BUTTON_ARROW_NEXT) -+ else if (aWidgetType == StyleAppearance::ButtonArrowNext) - *aWidgetFlags = GTK_ARROW_RIGHT; -- else if (aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS) -+ else if (aWidgetType == StyleAppearance::ButtonArrowPrevious) - *aWidgetFlags = GTK_ARROW_LEFT; - } - break; -- case NS_THEME_CHECKBOX_CONTAINER: -+ case StyleAppearance::CheckboxContainer: - aGtkWidgetType = MOZ_GTK_CHECKBUTTON_CONTAINER; - break; -- case NS_THEME_RADIO_CONTAINER: -+ case StyleAppearance::RadioContainer: - aGtkWidgetType = MOZ_GTK_RADIOBUTTON_CONTAINER; - break; -- case NS_THEME_CHECKBOX_LABEL: -+ case StyleAppearance::CheckboxLabel: - aGtkWidgetType = MOZ_GTK_CHECKBUTTON_LABEL; - break; -- case NS_THEME_RADIO_LABEL: -+ case StyleAppearance::RadioLabel: - aGtkWidgetType = MOZ_GTK_RADIOBUTTON_LABEL; - break; -- case NS_THEME_TOOLBAR: -+ case StyleAppearance::Toolbar: - aGtkWidgetType = MOZ_GTK_TOOLBAR; - break; -- case NS_THEME_TOOLTIP: -+ case StyleAppearance::Tooltip: - aGtkWidgetType = MOZ_GTK_TOOLTIP; - break; -- case NS_THEME_STATUSBARPANEL: -- case NS_THEME_RESIZERPANEL: -+ case StyleAppearance::Statusbarpanel: -+ case StyleAppearance::Resizerpanel: - aGtkWidgetType = MOZ_GTK_FRAME; - break; -- case NS_THEME_PROGRESSBAR: -- case NS_THEME_PROGRESSBAR_VERTICAL: -+ case StyleAppearance::Progressbar: -+ case StyleAppearance::ProgressbarVertical: - aGtkWidgetType = MOZ_GTK_PROGRESSBAR; - break; -- case NS_THEME_PROGRESSCHUNK: -- case NS_THEME_PROGRESSCHUNK_VERTICAL: -+ case StyleAppearance::Progresschunk: -+ case StyleAppearance::ProgresschunkVertical: - { - nsIFrame* stateFrame = aFrame->GetParent(); - EventStates eventStates = GetContentState(stateFrame, aWidgetType); -@@ -677,17 +692,17 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - : MOZ_GTK_PROGRESS_CHUNK; - } - break; -- case NS_THEME_TAB_SCROLL_ARROW_BACK: -- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: -+ case StyleAppearance::TabScrollArrowBack: -+ case StyleAppearance::TabScrollArrowForward: - if (aWidgetFlags) -- *aWidgetFlags = aWidgetType == NS_THEME_TAB_SCROLL_ARROW_BACK ? -+ *aWidgetFlags = aWidgetType == StyleAppearance::TabScrollArrowBack ? - GTK_ARROW_LEFT : GTK_ARROW_RIGHT; - aGtkWidgetType = MOZ_GTK_TAB_SCROLLARROW; - break; -- case NS_THEME_TABPANELS: -+ case StyleAppearance::Tabpanels: - aGtkWidgetType = MOZ_GTK_TABPANELS; - break; -- case NS_THEME_TAB: -+ case StyleAppearance::Tab: - { - if (IsBottomTab(aFrame)) { - aGtkWidgetType = MOZ_GTK_TAB_BOTTOM; -@@ -709,19 +724,19 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - } - break; -- case NS_THEME_SPLITTER: -+ case StyleAppearance::Splitter: - if (IsHorizontal(aFrame)) - aGtkWidgetType = MOZ_GTK_SPLITTER_VERTICAL; - else - aGtkWidgetType = MOZ_GTK_SPLITTER_HORIZONTAL; - break; -- case NS_THEME_MENUBAR: -+ case StyleAppearance::Menubar: - aGtkWidgetType = MOZ_GTK_MENUBAR; - break; -- case NS_THEME_MENUPOPUP: -+ case StyleAppearance::Menupopup: - aGtkWidgetType = MOZ_GTK_MENUPOPUP; - break; -- case NS_THEME_MENUITEM: -+ case StyleAppearance::Menuitem: - { - nsMenuFrame *menuFrame = do_QueryFrame(aFrame); - if (menuFrame && menuFrame->IsOnMenuBar()) { -@@ -731,41 +746,41 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u - } - aGtkWidgetType = MOZ_GTK_MENUITEM; - break; -- case NS_THEME_MENUSEPARATOR: -+ case StyleAppearance::Menuseparator: - aGtkWidgetType = MOZ_GTK_MENUSEPARATOR; - break; -- case NS_THEME_MENUARROW: -+ case StyleAppearance::Menuarrow: - aGtkWidgetType = MOZ_GTK_MENUARROW; - break; -- case NS_THEME_CHECKMENUITEM: -+ case StyleAppearance::Checkmenuitem: - aGtkWidgetType = MOZ_GTK_CHECKMENUITEM; - break; -- case NS_THEME_RADIOMENUITEM: -+ case StyleAppearance::Radiomenuitem: - aGtkWidgetType = MOZ_GTK_RADIOMENUITEM; - break; -- case NS_THEME_WINDOW: -- case NS_THEME_DIALOG: -+ case StyleAppearance::Window: -+ case StyleAppearance::Dialog: - aGtkWidgetType = MOZ_GTK_WINDOW; - break; -- case NS_THEME_GTK_INFO_BAR: -+ case StyleAppearance::MozGtkInfoBar: - aGtkWidgetType = MOZ_GTK_INFO_BAR; - break; -- case NS_THEME_WINDOW_TITLEBAR: -+ case StyleAppearance::MozWindowTitlebar: - aGtkWidgetType = MOZ_GTK_HEADER_BAR; - break; -- case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED: -+ case StyleAppearance::MozWindowTitlebarMaximized: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_MAXIMIZED; - break; -- case NS_THEME_WINDOW_BUTTON_CLOSE: -+ case StyleAppearance::MozWindowButtonClose: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_CLOSE; - break; -- case NS_THEME_WINDOW_BUTTON_MINIMIZE: -+ case StyleAppearance::MozWindowButtonMinimize: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE; - break; -- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: -+ case StyleAppearance::MozWindowButtonMaximize: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE; - break; -- case NS_THEME_WINDOW_BUTTON_RESTORE: -+ case StyleAppearance::MozWindowButtonRestore: - aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE; - break; - default: -@@ -1025,7 +1040,8 @@ DrawThemeWithCairo(gfxContext* aContext, - } - - bool --nsNativeThemeGTK::GetExtraSizeForWidget(nsIFrame* aFrame, uint8_t aWidgetType, -+nsNativeThemeGTK::GetExtraSizeForWidget(nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - nsIntMargin* aExtra) - { - *aExtra = nsIntMargin(0,0,0,0); -@@ -1033,14 +1049,14 @@ nsNativeThemeGTK::GetExtraSizeForWidget( - // GTK2 themes (Ximian Industrial, Bluecurve, Misty, at least); - // We modify the frame's overflow area. See bug 297508. - switch (aWidgetType) { -- case NS_THEME_SCROLLBARTHUMB_VERTICAL: -+ case StyleAppearance::ScrollbarthumbVertical: - aExtra->top = aExtra->bottom = 1; - break; -- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: -+ case StyleAppearance::ScrollbarthumbHorizontal: - aExtra->left = aExtra->right = 1; - break; - -- case NS_THEME_BUTTON : -+ case StyleAppearance::Button : - { - if (IsDefaultButton(aFrame)) { - // Some themes draw a default indicator outside the widget, -@@ -1055,14 +1071,14 @@ nsNativeThemeGTK::GetExtraSizeForWidget( - } - return false; - } -- case NS_THEME_FOCUS_OUTLINE: -+ case StyleAppearance::FocusOutline: - { - moz_gtk_get_focus_outline_size(&aExtra->left, &aExtra->top); - aExtra->right = aExtra->left; - aExtra->bottom = aExtra->top; - break; - } -- case NS_THEME_TAB : -+ case StyleAppearance::Tab : - { - if (!IsSelectedTab(aFrame)) - return false; -@@ -1097,7 +1113,7 @@ nsNativeThemeGTK::GetExtraSizeForWidget( - NS_IMETHODIMP - nsNativeThemeGTK::DrawWidgetBackground(gfxContext* aContext, - nsIFrame* aFrame, -- uint8_t aWidgetType, -+ StyleAppearance aWidgetType, - const nsRect& aRect, - const nsRect& aDirtyRect) - { -@@ -1191,8 +1207,8 @@ nsNativeThemeGTK::DrawWidgetBackground(g - #ifdef DEBUG - printf("GTK theme failed for widget type %d, error was %d, state was " - "[active=%d,focused=%d,inHover=%d,disabled=%d]\n", -- aWidgetType, gLastGdkError, state.active, state.focused, -- state.inHover, state.disabled); -+ static_cast(aWidgetType), gLastGdkError, state.active, -+ state.focused, state.inHover, state.disabled); - #endif - NS_WARNING("GTK theme failed; disabling unsafe widget"); - SetWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType); -@@ -1221,16 +1237,16 @@ nsNativeThemeGTK::CreateWebRenderCommand - const mozilla::layers::StackingContextHelper& aSc, - mozilla::layers::WebRenderLayerManager* aManager, - nsIFrame* aFrame, -- uint8_t aWidgetType, -+ StyleAppearance aWidgetType, - const nsRect& aRect) - { - nsPresContext* presContext = aFrame->PresContext(); -- wr::LayoutRect bounds = aSc.ToRelativeLayoutRect( -+ wr::LayoutRect bounds = wr::ToRoundedLayoutRect( - LayoutDeviceRect::FromAppUnits(aRect, presContext->AppUnitsPerDevPixel())); - - switch (aWidgetType) { -- case NS_THEME_WINDOW: -- case NS_THEME_DIALOG: -+ case StyleAppearance::Window: -+ case StyleAppearance::Dialog: - aBuilder.PushRect(bounds, bounds, true, - wr::ToColorF(Color::FromABGR( - LookAndFeel::GetColor(LookAndFeel::eColorID_WindowBackground, -@@ -1243,7 +1259,7 @@ nsNativeThemeGTK::CreateWebRenderCommand - } - - WidgetNodeType --nsNativeThemeGTK::NativeThemeToGtkTheme(uint8_t aWidgetType, nsIFrame* aFrame) -+nsNativeThemeGTK::NativeThemeToGtkTheme(StyleAppearance aWidgetType, nsIFrame* aFrame) - { - WidgetNodeType gtkWidgetType; - gint unusedFlags; -@@ -1258,9 +1274,10 @@ nsNativeThemeGTK::NativeThemeToGtkTheme( - } - - void --nsNativeThemeGTK::GetCachedWidgetBorder(nsIFrame* aFrame, uint8_t aWidgetType, -+nsNativeThemeGTK::GetCachedWidgetBorder(nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - GtkTextDirection aDirection, -- nsIntMargin* aResult) -+ LayoutDeviceIntMargin* aResult) - { - aResult->SizeTo(0, 0, 0, 0); - -@@ -1277,7 +1294,7 @@ nsNativeThemeGTK::GetCachedWidgetBorder( - } else { - moz_gtk_get_widget_border(gtkWidgetType, &aResult->left, &aResult->top, - &aResult->right, &aResult->bottom, aDirection); -- if (aWidgetType != MOZ_GTK_DROPDOWN) { // depends on aDirection -+ if (gtkWidgetType != MOZ_GTK_DROPDOWN) { // depends on aDirection - mBorderCacheValid[cacheIndex] |= cacheBit; - mBorderCache[gtkWidgetType] = *aResult; - } -@@ -1285,49 +1302,52 @@ nsNativeThemeGTK::GetCachedWidgetBorder( - } - } - --NS_IMETHODIMP --nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, -- uint8_t aWidgetType, nsIntMargin* aResult) -+LayoutDeviceIntMargin -+nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, -+ nsIFrame* aFrame, -+ StyleAppearance aWidgetType) - { -+ LayoutDeviceIntMargin result; - GtkTextDirection direction = GetTextDirection(aFrame); -- aResult->top = aResult->left = aResult->right = aResult->bottom = 0; - switch (aWidgetType) { -- case NS_THEME_SCROLLBAR_HORIZONTAL: -- case NS_THEME_SCROLLBAR_VERTICAL: -+ case StyleAppearance::ScrollbarHorizontal: -+ case StyleAppearance::ScrollbarVertical: - { - GtkOrientation orientation = -- aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? -+ aWidgetType == StyleAppearance::ScrollbarHorizontal ? - GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; -- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); -+ const ScrollbarGTKMetrics* metrics = -+ GetActiveScrollbarMetrics(orientation); - - const GtkBorder& border = metrics->border.scrollbar; -- aResult->top = border.top; -- aResult->right = border.right; -- aResult->bottom = border.bottom; -- aResult->left = border.left; -+ result.top = border.top; -+ result.right = border.right; -+ result.bottom = border.bottom; -+ result.left = border.left; - } - break; -- case NS_THEME_SCROLLBARTRACK_HORIZONTAL: -- case NS_THEME_SCROLLBARTRACK_VERTICAL: -+ case StyleAppearance::ScrollbartrackHorizontal: -+ case StyleAppearance::ScrollbartrackVertical: - { - GtkOrientation orientation = -- aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL ? -+ aWidgetType == StyleAppearance::ScrollbartrackHorizontal ? - GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; -- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); -+ const ScrollbarGTKMetrics* metrics = -+ GetActiveScrollbarMetrics(orientation); - - const GtkBorder& border = metrics->border.track; -- aResult->top = border.top; -- aResult->right = border.right; -- aResult->bottom = border.bottom; -- aResult->left = border.left; -+ result.top = border.top; -+ result.right = border.right; -+ result.bottom = border.bottom; -+ result.left = border.left; - } - break; -- case NS_THEME_TOOLBOX: -+ case StyleAppearance::Toolbox: - // gtk has no toolbox equivalent. So, although we map toolbox to - // gtk's 'toolbar' for purposes of painting the widget background, - // we don't use the toolbar border for toolbox. - break; -- case NS_THEME_DUALBUTTON: -+ case StyleAppearance::Dualbutton: - // TOOLBAR_DUAL_BUTTON is an interesting case. We want a border to draw - // around the entire button + dropdown, and also an inner border if you're - // over the button part. But, we want the inner button to be right up -@@ -1335,23 +1355,23 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi - // To make this happen, we draw a button border for the outer button, - // but don't reserve any space for it. - break; -- case NS_THEME_TAB: -+ case StyleAppearance::Tab: - { - WidgetNodeType gtkWidgetType; - gint flags; - - if (!GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nullptr, -- &flags)) -- return NS_OK; -- -- moz_gtk_get_tab_border(&aResult->left, &aResult->top, -- &aResult->right, &aResult->bottom, direction, -+ &flags)) { -+ return result; -+ } -+ moz_gtk_get_tab_border(&result.left, &result.top, -+ &result.right, &result.bottom, direction, - (GtkTabFlags)flags, gtkWidgetType); - } - break; -- case NS_THEME_MENUITEM: -- case NS_THEME_CHECKMENUITEM: -- case NS_THEME_RADIOMENUITEM: -+ case StyleAppearance::Menuitem: -+ case StyleAppearance::Checkmenuitem: -+ case StyleAppearance::Radiomenuitem: - // For regular menuitems, we will be using GetWidgetPadding instead of - // GetWidgetBorder to pad up the widget's internals; other menuitems - // will need to fall through and use the default case as before. -@@ -1360,50 +1380,57 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi - MOZ_FALLTHROUGH; - default: - { -- GetCachedWidgetBorder(aFrame, aWidgetType, direction, aResult); -+ GetCachedWidgetBorder(aFrame, aWidgetType, direction, &result); - } - } - - gint scale = GetMonitorScaleFactor(aFrame); -- aResult->top *= scale; -- aResult->right *= scale; -- aResult->bottom *= scale; -- aResult->left *= scale; -- return NS_OK; -+ result.top *= scale; -+ result.right *= scale; -+ result.bottom *= scale; -+ result.left *= scale; -+ return result; - } - - bool - nsNativeThemeGTK::GetWidgetPadding(nsDeviceContext* aContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -- nsIntMargin* aResult) --{ -+ nsIFrame* aFrame, -+ StyleAppearance aWidgetType, -+ LayoutDeviceIntMargin* aResult) -+{ -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } -+ - switch (aWidgetType) { -- case NS_THEME_BUTTON_FOCUS: -- case NS_THEME_TOOLBARBUTTON: -- case NS_THEME_WINDOW_BUTTON_CLOSE: -- case NS_THEME_WINDOW_BUTTON_MINIMIZE: -- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: -- case NS_THEME_WINDOW_BUTTON_RESTORE: -- case NS_THEME_DUALBUTTON: -- case NS_THEME_TAB_SCROLL_ARROW_BACK: -- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: -- case NS_THEME_MENULIST_BUTTON: -- case NS_THEME_TOOLBARBUTTON_DROPDOWN: -- case NS_THEME_BUTTON_ARROW_UP: -- case NS_THEME_BUTTON_ARROW_DOWN: -- case NS_THEME_BUTTON_ARROW_NEXT: -- case NS_THEME_BUTTON_ARROW_PREVIOUS: -- case NS_THEME_RANGE_THUMB: -+ case StyleAppearance::ButtonFocus: -+ case StyleAppearance::Toolbarbutton: -+ case StyleAppearance::MozWindowButtonClose: -+ case StyleAppearance::MozWindowButtonMinimize: -+ case StyleAppearance::MozWindowButtonMaximize: -+ case StyleAppearance::MozWindowButtonRestore: -+ case StyleAppearance::Dualbutton: -+ case StyleAppearance::TabScrollArrowBack: -+ case StyleAppearance::TabScrollArrowForward: -+ case StyleAppearance::MenulistButton: -+ case StyleAppearance::MozMenulistButton: -+ case StyleAppearance::ToolbarbuttonDropdown: -+ case StyleAppearance::ButtonArrowUp: -+ case StyleAppearance::ButtonArrowDown: -+ case StyleAppearance::ButtonArrowNext: -+ case StyleAppearance::ButtonArrowPrevious: -+ case StyleAppearance::RangeThumb: - // Radios and checkboxes return a fixed size in GetMinimumWidgetSize - // and have a meaningful baseline, so they can't have - // author-specified padding. -- case NS_THEME_CHECKBOX: -- case NS_THEME_RADIO: -+ case StyleAppearance::Checkbox: -+ case StyleAppearance::Radio: - aResult->SizeTo(0, 0, 0, 0); - return true; -- case NS_THEME_MENUITEM: -- case NS_THEME_CHECKMENUITEM: -- case NS_THEME_RADIOMENUITEM: -+ case StyleAppearance::Menuitem: -+ case StyleAppearance::Checkmenuitem: -+ case StyleAppearance::Radiomenuitem: - { - // Menubar and menulist have their padding specified in CSS. - if (!IsRegularMenuItem(aFrame)) -@@ -1413,8 +1440,7 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev - aResult); - - gint horizontal_padding; -- -- if (aWidgetType == NS_THEME_MENUITEM) -+ if (aWidgetType == StyleAppearance::Menuitem) - moz_gtk_menuitem_get_horizontal_padding(&horizontal_padding); - else - moz_gtk_checkmenuitem_get_horizontal_padding(&horizontal_padding); -@@ -1430,6 +1456,8 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev - - return true; - } -+ default: -+ break; - } - - return false; -@@ -1437,7 +1465,8 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev - - bool - nsNativeThemeGTK::GetWidgetOverflow(nsDeviceContext* aContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -+ nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - nsRect* aOverflowRect) - { - nsIntMargin extraSize; -@@ -1456,37 +1485,43 @@ nsNativeThemeGTK::GetWidgetOverflow(nsDe - - NS_IMETHODIMP - nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -+ nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - LayoutDeviceIntSize* aResult, - bool* aIsOverridable) - { - aResult->width = aResult->height = 0; - *aIsOverridable = true; - -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } -+ - switch (aWidgetType) { -- case NS_THEME_SCROLLBARBUTTON_UP: -- case NS_THEME_SCROLLBARBUTTON_DOWN: -+ case StyleAppearance::ScrollbarbuttonUp: -+ case StyleAppearance::ScrollbarbuttonDown: - { - const ScrollbarGTKMetrics* metrics = -- GetScrollbarMetrics(GTK_ORIENTATION_VERTICAL, true); -+ GetActiveScrollbarMetrics(GTK_ORIENTATION_VERTICAL); - - aResult->width = metrics->size.button.width; - aResult->height = metrics->size.button.height; - *aIsOverridable = false; - } - break; -- case NS_THEME_SCROLLBARBUTTON_LEFT: -- case NS_THEME_SCROLLBARBUTTON_RIGHT: -+ case StyleAppearance::ScrollbarbuttonLeft: -+ case StyleAppearance::ScrollbarbuttonRight: - { - const ScrollbarGTKMetrics* metrics = -- GetScrollbarMetrics(GTK_ORIENTATION_HORIZONTAL, true); -+ GetActiveScrollbarMetrics(GTK_ORIENTATION_HORIZONTAL); - - aResult->width = metrics->size.button.width; - aResult->height = metrics->size.button.height; - *aIsOverridable = false; - } - break; -- case NS_THEME_SPLITTER: -+ case StyleAppearance::Splitter: - { - gint metrics; - if (IsHorizontal(aFrame)) { -@@ -1501,8 +1536,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; - } - break; -- case NS_THEME_SCROLLBAR_HORIZONTAL: -- case NS_THEME_SCROLLBAR_VERTICAL: -+ case StyleAppearance::ScrollbarHorizontal: -+ case StyleAppearance::ScrollbarVertical: - { - /* While we enforce a minimum size for the thumb, this is ignored - * for the some scrollbars if buttons are hidden (bug 513006) because -@@ -1510,28 +1545,30 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - * or track. So add a minimum size to the track as well to prevent a - * 0-width scrollbar. */ - GtkOrientation orientation = -- aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? -+ aWidgetType == StyleAppearance::ScrollbarHorizontal ? - GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; -- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); -+ const ScrollbarGTKMetrics* metrics = -+ GetActiveScrollbarMetrics(orientation); - - aResult->width = metrics->size.scrollbar.width; - aResult->height = metrics->size.scrollbar.height; - } - break; -- case NS_THEME_SCROLLBARTHUMB_VERTICAL: -- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: -+ case StyleAppearance::ScrollbarthumbVertical: -+ case StyleAppearance::ScrollbarthumbHorizontal: - { - GtkOrientation orientation = -- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL ? -+ aWidgetType == StyleAppearance::ScrollbarthumbHorizontal ? - GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; -- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); -+ const ScrollbarGTKMetrics* metrics = -+ GetActiveScrollbarMetrics(orientation); - - aResult->width = metrics->size.thumb.width; - aResult->height = metrics->size.thumb.height; - *aIsOverridable = false; - } - break; -- case NS_THEME_RANGE_THUMB: -+ case StyleAppearance::RangeThumb: - { - gint thumb_length, thumb_height; - -@@ -1546,7 +1583,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; - } - break; -- case NS_THEME_RANGE: -+ case StyleAppearance::Range: - { - gint scale_width, scale_height; - -@@ -1559,12 +1596,12 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = true; - } - break; -- case NS_THEME_SCALETHUMB_HORIZONTAL: -- case NS_THEME_SCALETHUMB_VERTICAL: -+ case StyleAppearance::ScalethumbHorizontal: -+ case StyleAppearance::ScalethumbVertical: - { - gint thumb_length, thumb_height; - -- if (aWidgetType == NS_THEME_SCALETHUMB_VERTICAL) { -+ if (aWidgetType == StyleAppearance::ScalethumbVertical) { - moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_length, &thumb_height); - aResult->width = thumb_height; - aResult->height = thumb_length; -@@ -1577,21 +1614,22 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; - } - break; -- case NS_THEME_TAB_SCROLL_ARROW_BACK: -- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: -+ case StyleAppearance::TabScrollArrowBack: -+ case StyleAppearance::TabScrollArrowForward: - { - moz_gtk_get_tab_scroll_arrow_size(&aResult->width, &aResult->height); - *aIsOverridable = false; - } - break; -- case NS_THEME_MENULIST_BUTTON: -+ case StyleAppearance::MenulistButton: -+ case StyleAppearance::MozMenulistButton: - { - moz_gtk_get_combo_box_entry_button_size(&aResult->width, - &aResult->height); - *aIsOverridable = false; - } - break; -- case NS_THEME_MENUSEPARATOR: -+ case StyleAppearance::Menuseparator: - { - gint separator_height; - -@@ -1601,26 +1639,26 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; - } - break; -- case NS_THEME_CHECKBOX: -- case NS_THEME_RADIO: -+ case StyleAppearance::Checkbox: -+ case StyleAppearance::Radio: - { -- const ToggleGTKMetrics* metrics = GetToggleMetrics(aWidgetType == NS_THEME_RADIO); -+ const ToggleGTKMetrics* metrics = GetToggleMetrics(aWidgetType == StyleAppearance::Radio); - aResult->width = metrics->minSizeWithBorder.width; - aResult->height = metrics->minSizeWithBorder.height; - } - break; -- case NS_THEME_TOOLBARBUTTON_DROPDOWN: -- case NS_THEME_BUTTON_ARROW_UP: -- case NS_THEME_BUTTON_ARROW_DOWN: -- case NS_THEME_BUTTON_ARROW_NEXT: -- case NS_THEME_BUTTON_ARROW_PREVIOUS: -+ case StyleAppearance::ToolbarbuttonDropdown: -+ case StyleAppearance::ButtonArrowUp: -+ case StyleAppearance::ButtonArrowDown: -+ case StyleAppearance::ButtonArrowNext: -+ case StyleAppearance::ButtonArrowPrevious: - { - moz_gtk_get_arrow_size(MOZ_GTK_TOOLBARBUTTON_ARROW, - &aResult->width, &aResult->height); - *aIsOverridable = false; - } - break; -- case NS_THEME_WINDOW_BUTTON_CLOSE: -+ case StyleAppearance::MozWindowButtonClose: - { - const ToolbarButtonGTKMetrics* metrics = - GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_CLOSE); -@@ -1628,7 +1666,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - aResult->height = metrics->minSizeWithBorderMargin.height; - break; - } -- case NS_THEME_WINDOW_BUTTON_MINIMIZE: -+ case StyleAppearance::MozWindowButtonMinimize: - { - const ToolbarButtonGTKMetrics* metrics = - GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE); -@@ -1636,8 +1674,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - aResult->height = metrics->minSizeWithBorderMargin.height; - break; - } -- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: -- case NS_THEME_WINDOW_BUTTON_RESTORE: -+ case StyleAppearance::MozWindowButtonMaximize: -+ case StyleAppearance::MozWindowButtonRestore: - { - const ToolbarButtonGTKMetrics* metrics = - GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE); -@@ -1645,16 +1683,16 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - aResult->height = metrics->minSizeWithBorderMargin.height; - break; - } -- case NS_THEME_CHECKBOX_CONTAINER: -- case NS_THEME_RADIO_CONTAINER: -- case NS_THEME_CHECKBOX_LABEL: -- case NS_THEME_RADIO_LABEL: -- case NS_THEME_BUTTON: -- case NS_THEME_MENULIST: -- case NS_THEME_TOOLBARBUTTON: -- case NS_THEME_TREEHEADERCELL: -+ case StyleAppearance::CheckboxContainer: -+ case StyleAppearance::RadioContainer: -+ case StyleAppearance::CheckboxLabel: -+ case StyleAppearance::RadioLabel: -+ case StyleAppearance::Button: -+ case StyleAppearance::Menulist: -+ case StyleAppearance::Toolbarbutton: -+ case StyleAppearance::Treeheadercell: - { -- if (aWidgetType == NS_THEME_MENULIST) { -+ if (aWidgetType == StyleAppearance::Menulist) { - // Include the arrow size. - moz_gtk_get_arrow_size(MOZ_GTK_DROPDOWN, - &aResult->width, &aResult->height); -@@ -1663,21 +1701,21 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - // descendants; the value returned here will not be helpful, but the - // box model may consider border and padding with child minimum sizes. - -- nsIntMargin border; -+ LayoutDeviceIntMargin border; - GetCachedWidgetBorder(aFrame, aWidgetType, GetTextDirection(aFrame), &border); - aResult->width += border.left + border.right; - aResult->height += border.top + border.bottom; - } - break; - #ifdef MOZ_WIDGET_GTK -- case NS_THEME_NUMBER_INPUT: -- case NS_THEME_TEXTFIELD: -+ case StyleAppearance::NumberInput: -+ case StyleAppearance::Textfield: - { - moz_gtk_get_entry_min_height(&aResult->height); - } - break; - #endif -- case NS_THEME_SEPARATOR: -+ case StyleAppearance::Separator: - { - gint separator_width; - -@@ -1686,26 +1724,26 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - aResult->width = separator_width; - } - break; -- case NS_THEME_INNER_SPIN_BUTTON: -- case NS_THEME_SPINNER: -+ case StyleAppearance::InnerSpinButton: -+ case StyleAppearance::Spinner: - // hard code these sizes - aResult->width = 14; - aResult->height = 26; - break; -- case NS_THEME_TREEHEADERSORTARROW: -- case NS_THEME_SPINNER_UPBUTTON: -- case NS_THEME_SPINNER_DOWNBUTTON: -+ case StyleAppearance::Treeheadersortarrow: -+ case StyleAppearance::SpinnerUpbutton: -+ case StyleAppearance::SpinnerDownbutton: - // hard code these sizes - aResult->width = 14; - aResult->height = 13; - break; -- case NS_THEME_RESIZER: -+ case StyleAppearance::Resizer: - // same as Windows to make our lives easier - aResult->width = aResult->height = 15; - *aIsOverridable = false; - break; -- case NS_THEME_TREETWISTY: -- case NS_THEME_TREETWISTYOPEN: -+ case StyleAppearance::Treetwisty: -+ case StyleAppearance::Treetwistyopen: - { - gint expander_size; - -@@ -1714,6 +1752,8 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - *aIsOverridable = false; - } - break; -+ default: -+ break; - } - - *aResult = *aResult * GetMonitorScaleFactor(aFrame); -@@ -1722,41 +1762,42 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n - } - - NS_IMETHODIMP --nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, -+nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, -+ StyleAppearance aWidgetType, - nsAtom* aAttribute, bool* aShouldRepaint, - const nsAttrValue* aOldValue) - { - // Some widget types just never change state. -- if (aWidgetType == NS_THEME_TOOLBOX || -- aWidgetType == NS_THEME_TOOLBAR || -- aWidgetType == NS_THEME_STATUSBAR || -- aWidgetType == NS_THEME_STATUSBARPANEL || -- aWidgetType == NS_THEME_RESIZERPANEL || -- aWidgetType == NS_THEME_PROGRESSCHUNK || -- aWidgetType == NS_THEME_PROGRESSCHUNK_VERTICAL || -- aWidgetType == NS_THEME_PROGRESSBAR || -- aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL || -- aWidgetType == NS_THEME_MENUBAR || -- aWidgetType == NS_THEME_MENUPOPUP || -- aWidgetType == NS_THEME_TOOLTIP || -- aWidgetType == NS_THEME_MENUSEPARATOR || -- aWidgetType == NS_THEME_WINDOW || -- aWidgetType == NS_THEME_DIALOG) { -+ if (aWidgetType == StyleAppearance::Toolbox || -+ aWidgetType == StyleAppearance::Toolbar || -+ aWidgetType == StyleAppearance::Statusbar || -+ aWidgetType == StyleAppearance::Statusbarpanel || -+ aWidgetType == StyleAppearance::Resizerpanel || -+ aWidgetType == StyleAppearance::Progresschunk || -+ aWidgetType == StyleAppearance::ProgresschunkVertical || -+ aWidgetType == StyleAppearance::Progressbar || -+ aWidgetType == StyleAppearance::ProgressbarVertical || -+ aWidgetType == StyleAppearance::Menubar || -+ aWidgetType == StyleAppearance::Menupopup || -+ aWidgetType == StyleAppearance::Tooltip || -+ aWidgetType == StyleAppearance::Menuseparator || -+ aWidgetType == StyleAppearance::Window || -+ aWidgetType == StyleAppearance::Dialog) { - *aShouldRepaint = false; - return NS_OK; - } - -- if ((aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL || -- aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL) && -+ if ((aWidgetType == StyleAppearance::ScrollbarthumbVertical || -+ aWidgetType == StyleAppearance::ScrollbarthumbHorizontal) && - aAttribute == nsGkAtoms::active) { - *aShouldRepaint = true; - return NS_OK; - } - -- if ((aWidgetType == NS_THEME_SCROLLBARBUTTON_UP || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_DOWN || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT || -- aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) && -+ if ((aWidgetType == StyleAppearance::ScrollbarbuttonUp || -+ aWidgetType == StyleAppearance::ScrollbarbuttonDown || -+ aWidgetType == StyleAppearance::ScrollbarbuttonLeft || -+ aWidgetType == StyleAppearance::ScrollbarbuttonRight) && - (aAttribute == nsGkAtoms::curpos || - aAttribute == nsGkAtoms::maxpos)) { - // If 'curpos' has changed and we are passed its old value, we can -@@ -1820,120 +1861,135 @@ nsNativeThemeGTK::ThemeChanged() - NS_IMETHODIMP_(bool) - nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext, - nsIFrame* aFrame, -- uint8_t aWidgetType) -+ StyleAppearance aWidgetType) - { - if (IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType)) - return false; - -+ if (IsWidgetScrollbarPart(aWidgetType)) { -+ ComputedStyle* cs = nsLayoutUtils::StyleForScrollbar(aFrame); -+ if (cs->StyleUI()->HasCustomScrollbars() || -+ // We cannot handle thin scrollbar on GTK+ widget directly as well. -+ cs->StyleUIReset()->mScrollbarWidth == StyleScrollbarWidth::Thin) { -+ return false; -+ } -+ } -+ -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } -+ - switch (aWidgetType) { - // Combobox dropdowns don't support native theming in vertical mode. -- case NS_THEME_MENULIST: -- case NS_THEME_MENULIST_TEXT: -- case NS_THEME_MENULIST_TEXTFIELD: -+ case StyleAppearance::Menulist: -+ case StyleAppearance::MenulistText: -+ case StyleAppearance::MenulistTextfield: - if (aFrame && aFrame->GetWritingMode().IsVertical()) { - return false; - } - MOZ_FALLTHROUGH; - -- case NS_THEME_BUTTON: -- case NS_THEME_BUTTON_FOCUS: -- case NS_THEME_RADIO: -- case NS_THEME_CHECKBOX: -- case NS_THEME_TOOLBOX: // N/A -- case NS_THEME_TOOLBAR: -- case NS_THEME_TOOLBARBUTTON: -- case NS_THEME_DUALBUTTON: // so we can override the border with 0 -- case NS_THEME_TOOLBARBUTTON_DROPDOWN: -- case NS_THEME_BUTTON_ARROW_UP: -- case NS_THEME_BUTTON_ARROW_DOWN: -- case NS_THEME_BUTTON_ARROW_NEXT: -- case NS_THEME_BUTTON_ARROW_PREVIOUS: -- case NS_THEME_SEPARATOR: -- case NS_THEME_TOOLBARGRIPPER: -- case NS_THEME_STATUSBAR: -- case NS_THEME_STATUSBARPANEL: -- case NS_THEME_RESIZERPANEL: -- case NS_THEME_RESIZER: -- case NS_THEME_LISTBOX: -- // case NS_THEME_LISTITEM: -- case NS_THEME_TREEVIEW: -- // case NS_THEME_TREEITEM: -- case NS_THEME_TREETWISTY: -- // case NS_THEME_TREELINE: -- // case NS_THEME_TREEHEADER: -- case NS_THEME_TREEHEADERCELL: -- case NS_THEME_TREEHEADERSORTARROW: -- case NS_THEME_TREETWISTYOPEN: -- case NS_THEME_PROGRESSBAR: -- case NS_THEME_PROGRESSCHUNK: -- case NS_THEME_PROGRESSBAR_VERTICAL: -- case NS_THEME_PROGRESSCHUNK_VERTICAL: -- case NS_THEME_TAB: -- // case NS_THEME_TABPANEL: -- case NS_THEME_TABPANELS: -- case NS_THEME_TAB_SCROLL_ARROW_BACK: -- case NS_THEME_TAB_SCROLL_ARROW_FORWARD: -- case NS_THEME_TOOLTIP: -- case NS_THEME_INNER_SPIN_BUTTON: -- case NS_THEME_SPINNER: -- case NS_THEME_SPINNER_UPBUTTON: -- case NS_THEME_SPINNER_DOWNBUTTON: -- case NS_THEME_SPINNER_TEXTFIELD: -- // case NS_THEME_SCROLLBAR: (n/a for gtk) -- // case NS_THEME_SCROLLBAR_SMALL: (n/a for gtk) -- case NS_THEME_SCROLLBARBUTTON_UP: -- case NS_THEME_SCROLLBARBUTTON_DOWN: -- case NS_THEME_SCROLLBARBUTTON_LEFT: -- case NS_THEME_SCROLLBARBUTTON_RIGHT: -- case NS_THEME_SCROLLBAR_HORIZONTAL: -- case NS_THEME_SCROLLBAR_VERTICAL: -- case NS_THEME_SCROLLBARTRACK_HORIZONTAL: -- case NS_THEME_SCROLLBARTRACK_VERTICAL: -- case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: -- case NS_THEME_SCROLLBARTHUMB_VERTICAL: -- case NS_THEME_NUMBER_INPUT: -- case NS_THEME_TEXTFIELD: -- case NS_THEME_TEXTFIELD_MULTILINE: -- case NS_THEME_RANGE: -- case NS_THEME_RANGE_THUMB: -- case NS_THEME_SCALE_HORIZONTAL: -- case NS_THEME_SCALETHUMB_HORIZONTAL: -- case NS_THEME_SCALE_VERTICAL: -- case NS_THEME_SCALETHUMB_VERTICAL: -- // case NS_THEME_SCALETHUMBSTART: -- // case NS_THEME_SCALETHUMBEND: -- // case NS_THEME_SCALETHUMBTICK: -- case NS_THEME_CHECKBOX_CONTAINER: -- case NS_THEME_RADIO_CONTAINER: -- case NS_THEME_CHECKBOX_LABEL: -- case NS_THEME_RADIO_LABEL: -- case NS_THEME_MENUBAR: -- case NS_THEME_MENUPOPUP: -- case NS_THEME_MENUITEM: -- case NS_THEME_MENUARROW: -- case NS_THEME_MENUSEPARATOR: -- case NS_THEME_CHECKMENUITEM: -- case NS_THEME_RADIOMENUITEM: -- case NS_THEME_SPLITTER: -- case NS_THEME_WINDOW: -- case NS_THEME_DIALOG: -+ case StyleAppearance::Button: -+ case StyleAppearance::ButtonFocus: -+ case StyleAppearance::Radio: -+ case StyleAppearance::Checkbox: -+ case StyleAppearance::Toolbox: // N/A -+ case StyleAppearance::Toolbar: -+ case StyleAppearance::Toolbarbutton: -+ case StyleAppearance::Dualbutton: // so we can override the border with 0 -+ case StyleAppearance::ToolbarbuttonDropdown: -+ case StyleAppearance::ButtonArrowUp: -+ case StyleAppearance::ButtonArrowDown: -+ case StyleAppearance::ButtonArrowNext: -+ case StyleAppearance::ButtonArrowPrevious: -+ case StyleAppearance::Separator: -+ case StyleAppearance::Toolbargripper: -+ case StyleAppearance::Statusbar: -+ case StyleAppearance::Statusbarpanel: -+ case StyleAppearance::Resizerpanel: -+ case StyleAppearance::Resizer: -+ case StyleAppearance::Listbox: -+ // case StyleAppearance::Listitem: -+ case StyleAppearance::Treeview: -+ // case StyleAppearance::Treeitem: -+ case StyleAppearance::Treetwisty: -+ // case StyleAppearance::Treeline: -+ // case StyleAppearance::Treeheader: -+ case StyleAppearance::Treeheadercell: -+ case StyleAppearance::Treeheadersortarrow: -+ case StyleAppearance::Treetwistyopen: -+ case StyleAppearance::Progressbar: -+ case StyleAppearance::Progresschunk: -+ case StyleAppearance::ProgressbarVertical: -+ case StyleAppearance::ProgresschunkVertical: -+ case StyleAppearance::Tab: -+ // case StyleAppearance::Tabpanel: -+ case StyleAppearance::Tabpanels: -+ case StyleAppearance::TabScrollArrowBack: -+ case StyleAppearance::TabScrollArrowForward: -+ case StyleAppearance::Tooltip: -+ case StyleAppearance::InnerSpinButton: -+ case StyleAppearance::Spinner: -+ case StyleAppearance::SpinnerUpbutton: -+ case StyleAppearance::SpinnerDownbutton: -+ case StyleAppearance::SpinnerTextfield: -+ // case StyleAppearance::Scrollbar: (n/a for gtk) -+ // case StyleAppearance::ScrollbarSmall: (n/a for gtk) -+ case StyleAppearance::ScrollbarbuttonUp: -+ case StyleAppearance::ScrollbarbuttonDown: -+ case StyleAppearance::ScrollbarbuttonLeft: -+ case StyleAppearance::ScrollbarbuttonRight: -+ case StyleAppearance::ScrollbarHorizontal: -+ case StyleAppearance::ScrollbarVertical: -+ case StyleAppearance::ScrollbartrackHorizontal: -+ case StyleAppearance::ScrollbartrackVertical: -+ case StyleAppearance::ScrollbarthumbHorizontal: -+ case StyleAppearance::ScrollbarthumbVertical: -+ case StyleAppearance::NumberInput: -+ case StyleAppearance::Textfield: -+ case StyleAppearance::TextfieldMultiline: -+ case StyleAppearance::Range: -+ case StyleAppearance::RangeThumb: -+ case StyleAppearance::ScaleHorizontal: -+ case StyleAppearance::ScalethumbHorizontal: -+ case StyleAppearance::ScaleVertical: -+ case StyleAppearance::ScalethumbVertical: -+ // case StyleAppearance::Scalethumbstart: -+ // case StyleAppearance::Scalethumbend: -+ // case StyleAppearance::Scalethumbtick: -+ case StyleAppearance::CheckboxContainer: -+ case StyleAppearance::RadioContainer: -+ case StyleAppearance::CheckboxLabel: -+ case StyleAppearance::RadioLabel: -+ case StyleAppearance::Menubar: -+ case StyleAppearance::Menupopup: -+ case StyleAppearance::Menuitem: -+ case StyleAppearance::Menuarrow: -+ case StyleAppearance::Menuseparator: -+ case StyleAppearance::Checkmenuitem: -+ case StyleAppearance::Radiomenuitem: -+ case StyleAppearance::Splitter: -+ case StyleAppearance::Window: -+ case StyleAppearance::Dialog: - #ifdef MOZ_WIDGET_GTK -- case NS_THEME_GTK_INFO_BAR: -+ case StyleAppearance::MozGtkInfoBar: - #endif - return !IsWidgetStyled(aPresContext, aFrame, aWidgetType); - -- case NS_THEME_WINDOW_BUTTON_CLOSE: -- case NS_THEME_WINDOW_BUTTON_MINIMIZE: -- case NS_THEME_WINDOW_BUTTON_MAXIMIZE: -- case NS_THEME_WINDOW_BUTTON_RESTORE: -- case NS_THEME_WINDOW_TITLEBAR: -- case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED: -+ case StyleAppearance::MozWindowButtonClose: -+ case StyleAppearance::MozWindowButtonMinimize: -+ case StyleAppearance::MozWindowButtonMaximize: -+ case StyleAppearance::MozWindowButtonRestore: -+ case StyleAppearance::MozWindowTitlebar: -+ case StyleAppearance::MozWindowTitlebarMaximized: - // GtkHeaderBar is available on GTK 3.10+, which is used for styling - // title bars and title buttons. - return gtk_check_version(3, 10, 0) == nullptr && - !IsWidgetStyled(aPresContext, aFrame, aWidgetType); - -- case NS_THEME_MENULIST_BUTTON: -+ case StyleAppearance::MenulistButton: -+ case StyleAppearance::MozMenulistButton: - if (aFrame && aFrame->GetWritingMode().IsVertical()) { - return false; - } -@@ -1942,37 +1998,50 @@ nsNativeThemeGTK::ThemeSupportsWidget(ns - return (!aFrame || IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) && - !IsWidgetStyled(aPresContext, aFrame, aWidgetType); - -- case NS_THEME_FOCUS_OUTLINE: -+ case StyleAppearance::FocusOutline: - return true; -+ default: -+ break; - } - - return false; - } - - NS_IMETHODIMP_(bool) --nsNativeThemeGTK::WidgetIsContainer(uint8_t aWidgetType) -+nsNativeThemeGTK::WidgetIsContainer(StyleAppearance aWidgetType) - { -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } -+ - // XXXdwh At some point flesh all of this out. -- if (aWidgetType == NS_THEME_MENULIST_BUTTON || -- aWidgetType == NS_THEME_RADIO || -- aWidgetType == NS_THEME_RANGE_THUMB || -- aWidgetType == NS_THEME_CHECKBOX || -- aWidgetType == NS_THEME_TAB_SCROLL_ARROW_BACK || -- aWidgetType == NS_THEME_TAB_SCROLL_ARROW_FORWARD || -- aWidgetType == NS_THEME_BUTTON_ARROW_UP || -- aWidgetType == NS_THEME_BUTTON_ARROW_DOWN || -- aWidgetType == NS_THEME_BUTTON_ARROW_NEXT || -- aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS) -+ if (aWidgetType == StyleAppearance::MenulistButton || -+ aWidgetType == StyleAppearance::MozMenulistButton || -+ aWidgetType == StyleAppearance::Radio || -+ aWidgetType == StyleAppearance::RangeThumb || -+ aWidgetType == StyleAppearance::Checkbox || -+ aWidgetType == StyleAppearance::TabScrollArrowBack || -+ aWidgetType == StyleAppearance::TabScrollArrowForward || -+ aWidgetType == StyleAppearance::ButtonArrowUp || -+ aWidgetType == StyleAppearance::ButtonArrowDown || -+ aWidgetType == StyleAppearance::ButtonArrowNext || -+ aWidgetType == StyleAppearance::ButtonArrowPrevious) - return false; - return true; - } - - bool --nsNativeThemeGTK::ThemeDrawsFocusForWidget(uint8_t aWidgetType) -+nsNativeThemeGTK::ThemeDrawsFocusForWidget(StyleAppearance aWidgetType) - { -- if (aWidgetType == NS_THEME_MENULIST || -- aWidgetType == NS_THEME_BUTTON || -- aWidgetType == NS_THEME_TREEHEADERCELL) -+ if (aWidgetType == StyleAppearance::MenulistButton && -+ StaticPrefs::layout_css_webkit_appearance_enabled()) { -+ aWidgetType = StyleAppearance::Menulist; -+ } -+ -+ if (aWidgetType == StyleAppearance::Menulist || -+ aWidgetType == StyleAppearance::Button || -+ aWidgetType == StyleAppearance::Treeheadercell) - return true; - - return false; -@@ -1985,16 +2054,17 @@ nsNativeThemeGTK::ThemeNeedsComboboxDrop - } - - nsITheme::Transparency --nsNativeThemeGTK::GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) -+nsNativeThemeGTK::GetWidgetTransparency(nsIFrame* aFrame, -+ StyleAppearance aWidgetType) - { - switch (aWidgetType) { - // These widgets always draw a default background. -- case NS_THEME_MENUPOPUP: -- case NS_THEME_WINDOW: -- case NS_THEME_DIALOG: -+ case StyleAppearance::Menupopup: -+ case StyleAppearance::Window: -+ case StyleAppearance::Dialog: - return eOpaque; -- case NS_THEME_SCROLLBAR_VERTICAL: -- case NS_THEME_SCROLLBAR_HORIZONTAL: -+ case StyleAppearance::ScrollbarVertical: -+ case StyleAppearance::ScrollbarHorizontal: - #ifdef MOZ_WIDGET_GTK - // Make scrollbar tracks opaque on the window's scroll frame to prevent - // leaf layers from overlapping. See bug 1179780. -@@ -2006,9 +2076,10 @@ nsNativeThemeGTK::GetWidgetTransparency( - return eOpaque; - // Tooltips use gtk_paint_flat_box() on Gtk2 - // but are shaped on Gtk3 -- case NS_THEME_TOOLTIP: -+ case StyleAppearance::Tooltip: - return eTransparent; -+ default: -+ return eUnknownTransparency; - } - -- return eUnknownTransparency; - } -diff -up thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h.wayland thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h ---- thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h.wayland 2018-10-30 12:45:37.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsNativeThemeGTK.h 2018-11-20 12:04:43.739787343 +0100 -@@ -11,7 +11,7 @@ - #include "nsAtom.h" - #include "nsIObserver.h" - #include "nsNativeTheme.h" --#include "nsThemeConstants.h" -+#include "nsStyleConsts.h" - - #include - #include "gtkdrawing.h" -@@ -26,7 +26,7 @@ public: - - // The nsITheme interface. - NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -+ nsIFrame* aFrame, WidgetType aWidgetType, - const nsRect& aRect, - const nsRect& aDirtyRect) override; - -@@ -35,29 +35,29 @@ public: - const mozilla::layers::StackingContextHelper& aSc, - mozilla::layers::WebRenderLayerManager* aManager, - nsIFrame* aFrame, -- uint8_t aWidgetType, -+ WidgetType aWidgetType, - const nsRect& aRect) override; - -- NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, -- uint8_t aWidgetType, -- nsIntMargin* aResult) override; -- -- virtual bool GetWidgetPadding(nsDeviceContext* aContext, -- nsIFrame* aFrame, -- uint8_t aWidgetType, -- nsIntMargin* aResult) override; -+ MOZ_MUST_USE LayoutDeviceIntMargin GetWidgetBorder(nsDeviceContext* aContext, -+ nsIFrame* aFrame, -+ WidgetType aWidgetType) override; -+ -+ bool GetWidgetPadding(nsDeviceContext* aContext, -+ nsIFrame* aFrame, -+ WidgetType aWidgetType, -+ LayoutDeviceIntMargin* aResult) override; - - virtual bool GetWidgetOverflow(nsDeviceContext* aContext, - nsIFrame* aFrame, -- uint8_t aWidgetType, -+ WidgetType aWidgetType, - nsRect* aOverflowRect) override; - - NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, -- nsIFrame* aFrame, uint8_t aWidgetType, -+ nsIFrame* aFrame, WidgetType aWidgetType, - mozilla::LayoutDeviceIntSize* aResult, - bool* aIsOverridable) override; - -- NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, -+ NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, WidgetType aWidgetType, - nsAtom* aAttribute, - bool* aShouldRepaint, - const nsAttrValue* aOldValue) override; -@@ -66,16 +66,16 @@ public: - - NS_IMETHOD_(bool) ThemeSupportsWidget(nsPresContext* aPresContext, - nsIFrame* aFrame, -- uint8_t aWidgetType) override; -+ WidgetType aWidgetType) override; - -- NS_IMETHOD_(bool) WidgetIsContainer(uint8_t aWidgetType) override; -+ NS_IMETHOD_(bool) WidgetIsContainer(WidgetType aWidgetType) override; - -- NS_IMETHOD_(bool) ThemeDrawsFocusForWidget(uint8_t aWidgetType) override; -+ NS_IMETHOD_(bool) ThemeDrawsFocusForWidget(WidgetType aWidgetType) override; - - virtual bool ThemeNeedsComboboxDropmarker() override; - - virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, -- uint8_t aWidgetType) override; -+ WidgetType aWidgetType) override; - nsNativeThemeGTK(); - - protected: -@@ -84,26 +84,27 @@ protected: - private: - GtkTextDirection GetTextDirection(nsIFrame* aFrame); - gint GetTabMarginPixels(nsIFrame* aFrame); -- bool GetGtkWidgetAndState(uint8_t aWidgetType, nsIFrame* aFrame, -+ bool GetGtkWidgetAndState(WidgetType aWidgetType, nsIFrame* aFrame, - WidgetNodeType& aGtkWidgetType, - GtkWidgetState* aState, gint* aWidgetFlags); -- bool GetExtraSizeForWidget(nsIFrame* aFrame, uint8_t aWidgetType, -+ bool GetExtraSizeForWidget(nsIFrame* aFrame, WidgetType aWidgetType, - nsIntMargin* aExtra); - - void RefreshWidgetWindow(nsIFrame* aFrame); -- WidgetNodeType NativeThemeToGtkTheme(uint8_t aWidgetType, nsIFrame* aFrame); -+ WidgetNodeType NativeThemeToGtkTheme(WidgetType aWidgetType, nsIFrame* aFrame); - -- uint8_t mDisabledWidgetTypes[(ThemeWidgetType_COUNT + 7) / 8]; -- uint8_t mSafeWidgetStates[ThemeWidgetType_COUNT * 4]; // 32 bits per widget -+ uint8_t mDisabledWidgetTypes[(static_cast(mozilla::StyleAppearance::Count) + 7) / 8]; -+ uint8_t mSafeWidgetStates[static_cast(mozilla::StyleAppearance::Count) * 4]; // 32 bits per widget - static const char* sDisabledEngines[]; - - // Because moz_gtk_get_widget_border can be slow, we cache its results - // by widget type. Each bit in mBorderCacheValid says whether the - // corresponding entry in mBorderCache is valid. -- void GetCachedWidgetBorder(nsIFrame* aFrame, uint8_t aWidgetType, -- GtkTextDirection aDirection, nsIntMargin* aResult); -+ void GetCachedWidgetBorder(nsIFrame* aFrame, WidgetType aWidgetType, -+ GtkTextDirection aDirection, -+ LayoutDeviceIntMargin* aResult); - uint8_t mBorderCacheValid[(MOZ_GTK_WIDGET_NODE_COUNT + 7) / 8]; -- nsIntMargin mBorderCache[MOZ_GTK_WIDGET_NODE_COUNT]; -+ LayoutDeviceIntMargin mBorderCache[MOZ_GTK_WIDGET_NODE_COUNT]; - }; - #endif diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp --- thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp 2018-11-20 12:04:43.739787343 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp 2018-11-21 13:45:42.405091067 +0100 @@ -24,7 +24,20 @@ #include "nsIBaseWindow.h" #include "nsIDocShellTreeItem.h" @@ -6075,7 +1946,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird- NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); GtkPrintSettings* settings = gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog)); -@@ -513,13 +526,522 @@ nsPrintDialogServiceGTK::Init() +@@ -513,13 +526,521 @@ nsPrintDialogServiceGTK::Init() return NS_OK; } @@ -6556,8 +2427,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird- + // Check for the flatpak portal first + nsCOMPtr giovfs = + do_GetService(NS_GIOSERVICE_CONTRACTID); -+ bool shouldUsePortal; -+ giovfs->ShouldUseFlatpakPortal(&shouldUsePortal); ++ bool shouldUsePortal = false; + if (shouldUsePortal && gtk_check_version(3, 22, 0) == nullptr) { + nsCOMPtr widget = WidgetUtils::DOMWindowToWidget(aParent); + NS_ASSERTION(widget, "Need a widget for dialog to be modal."); @@ -6600,7 +2470,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird- nsPrintDialogWidgetGTK printDialog(aParent, aSettings); nsresult rv = printDialog.ImportSettings(aSettings); -@@ -553,8 +1075,8 @@ NS_IMETHODIMP +@@ -553,8 +1074,8 @@ NS_IMETHODIMP nsPrintDialogServiceGTK::ShowPageSetup(nsPIDOMWindowOuter *aParent, nsIPrintSettings *aNSSettings) { @@ -6611,131 +2481,9 @@ diff -up thunderbird-60.3.0/widget/gtk/nsPrintDialogGTK.cpp.wayland thunderbird- NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); nsCOMPtr widget = WidgetUtils::DOMWindowToWidget(aParent); -diff -up thunderbird-60.3.0/widget/gtk/nsSound.cpp.wayland thunderbird-60.3.0/widget/gtk/nsSound.cpp ---- thunderbird-60.3.0/widget/gtk/nsSound.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsSound.cpp 2018-11-20 12:04:43.739787343 +0100 -@@ -417,43 +417,3 @@ NS_IMETHODIMP nsSound::PlayEventSound(ui - } - return NS_OK; - } -- --NS_IMETHODIMP nsSound::PlaySystemSound(const nsAString &aSoundAlias) --{ -- if (NS_IsMozAliasSound(aSoundAlias)) { -- NS_WARNING("nsISound::playSystemSound is called with \"_moz_\" events, they are obsolete, use nsISound::playEventSound instead"); -- uint32_t eventId; -- if (aSoundAlias.Equals(NS_SYSSOUND_ALERT_DIALOG)) -- eventId = EVENT_ALERT_DIALOG_OPEN; -- else if (aSoundAlias.Equals(NS_SYSSOUND_CONFIRM_DIALOG)) -- eventId = EVENT_CONFIRM_DIALOG_OPEN; -- else if (aSoundAlias.Equals(NS_SYSSOUND_MAIL_BEEP)) -- eventId = EVENT_NEW_MAIL_RECEIVED; -- else if (aSoundAlias.Equals(NS_SYSSOUND_MENU_EXECUTE)) -- eventId = EVENT_MENU_EXECUTE; -- else if (aSoundAlias.Equals(NS_SYSSOUND_MENU_POPUP)) -- eventId = EVENT_MENU_POPUP; -- else -- return NS_OK; -- return PlayEventSound(eventId); -- } -- -- nsresult rv; -- nsCOMPtr fileURI; -- -- // create a nsIFile and then a nsIFileURL from that -- nsCOMPtr soundFile; -- rv = NS_NewLocalFile(aSoundAlias, true, -- getter_AddRefs(soundFile)); -- NS_ENSURE_SUCCESS(rv,rv); -- -- rv = NS_NewFileURI(getter_AddRefs(fileURI), soundFile); -- NS_ENSURE_SUCCESS(rv,rv); -- -- nsCOMPtr fileURL = do_QueryInterface(fileURI,&rv); -- NS_ENSURE_SUCCESS(rv,rv); -- -- rv = Play(fileURL); -- -- return rv; --} -diff -up thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp.wayland thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp ---- thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsWidgetFactory.cpp 2018-11-20 12:04:43.739787343 +0100 -@@ -27,6 +27,7 @@ - #ifdef MOZ_WIDGET_GTK - #include "nsApplicationChooser.h" - #endif -+#include "TaskbarProgress.h" - #include "nsColorPicker.h" - #include "nsFilePicker.h" - #include "nsSound.h" -@@ -60,7 +61,6 @@ - using namespace mozilla; - using namespace mozilla::widget; - --NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) -@@ -72,6 +72,7 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR - NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISound, nsSound::GetInstance) - NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToPixbuf) -+NS_GENERIC_FACTORY_CONSTRUCTOR(TaskbarProgress) - - - // from nsWindow.cpp -@@ -196,14 +197,13 @@ nsClipboardConstructor(nsISupports *aOut - return inst->QueryInterface(aIID, aResult); - } - --NS_DEFINE_NAMED_CID(NS_WINDOW_CID); --NS_DEFINE_NAMED_CID(NS_CHILD_CID); - NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); - NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID); - NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); - #ifdef MOZ_WIDGET_GTK - NS_DEFINE_NAMED_CID(NS_APPLICATIONCHOOSER_CID); - #endif -+NS_DEFINE_NAMED_CID(NS_GTK_TASKBARPROGRESS_CID); - NS_DEFINE_NAMED_CID(NS_SOUND_CID); - NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID); - #ifdef MOZ_X11 -@@ -230,14 +230,13 @@ NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); - - - static const mozilla::Module::CIDEntry kWidgetCIDs[] = { -- { &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor }, -- { &kNS_CHILD_CID, false, nullptr, nsWindowConstructor }, - { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor, Module::ALLOW_IN_GPU_PROCESS }, - { &kNS_COLORPICKER_CID, false, nullptr, nsColorPickerConstructor, Module::MAIN_PROCESS_ONLY }, - { &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerConstructor, Module::MAIN_PROCESS_ONLY }, - #ifdef MOZ_WIDGET_GTK - { &kNS_APPLICATIONCHOOSER_CID, false, nullptr, nsApplicationChooserConstructor, Module::MAIN_PROCESS_ONLY }, - #endif -+ { &kNS_GTK_TASKBARPROGRESS_CID, false, nullptr, TaskbarProgressConstructor}, - { &kNS_SOUND_CID, false, nullptr, nsISoundConstructor, Module::MAIN_PROCESS_ONLY }, - { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor }, - #ifdef MOZ_X11 -@@ -266,14 +265,13 @@ static const mozilla::Module::CIDEntry k - }; - - static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { -- { "@mozilla.org/widget/window/gtk;1", &kNS_WINDOW_CID }, -- { "@mozilla.org/widgets/child_window/gtk;1", &kNS_CHILD_CID }, - { "@mozilla.org/widget/appshell/gtk;1", &kNS_APPSHELL_CID, Module::ALLOW_IN_GPU_PROCESS }, - { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::MAIN_PROCESS_ONLY }, - #ifdef MOZ_WIDGET_GTK - { "@mozilla.org/applicationchooser;1", &kNS_APPLICATIONCHOOSER_CID, Module::MAIN_PROCESS_ONLY }, - #endif -+ { "@mozilla.org/widget/taskbarprogress/gtk;1", &kNS_GTK_TASKBARPROGRESS_CID }, - { "@mozilla.org/sound;1", &kNS_SOUND_CID, Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID }, - #ifdef MOZ_X11 diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/widget/gtk/nsWindow.cpp --- thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsWindow.cpp 2018-11-20 12:04:43.741787337 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsWindow.cpp 2018-11-21 13:42:00.762025644 +0100 @@ -18,6 +18,7 @@ #include "mozilla/TouchEvents.h" #include "mozilla/UniquePtrExtensions.h" @@ -6832,41 +2580,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w this); nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); -@@ -838,11 +843,48 @@ nsWindow::GetDesktopToDeviceScale() - return DesktopToLayoutDeviceScale(1.0); - } - -+DesktopToLayoutDeviceScale -+nsWindow::GetDesktopToDeviceScaleByScreen() -+{ -+#ifdef MOZ_WAYLAND -+ GdkDisplay* gdkDisplay = gdk_display_get_default(); -+ // In Wayland there's no way to get absolute position of the window and use it to -+ // determine the screen factor of the monitor on which the window is placed. -+ // The window is notified of the current scale factor but not at this point, -+ // so the GdkScaleFactor can return wrong value which can lead to wrong popup -+ // placement. -+ // We need to use parent's window scale factor for the new one. -+ if (GDK_IS_WAYLAND_DISPLAY(gdkDisplay)) { -+ nsView* view = nsView::GetViewFor(this); -+ if (view) { -+ nsView* parentView = view->GetParent(); -+ if (parentView) { -+ nsIWidget* parentWidget = parentView->GetNearestWidget(nullptr); -+ if (parentWidget) { -+ return DesktopToLayoutDeviceScale(parentWidget->RoundsWidgetCoordinatesTo()); -+ } else { -+ NS_WARNING("Widget has no parent"); -+ } -+ } -+ } else { -+ NS_WARNING("Cannot find widget view"); -+ } -+ } -+#endif -+ return nsBaseWidget::GetDesktopToDeviceScale(); -+} -+ +@@ -841,8 +846,14 @@ nsWindow::GetDesktopToDeviceScale() void nsWindow::SetParent(nsIWidget *aNewParent) { @@ -6883,7 +2597,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w return; } -@@ -886,7 +928,7 @@ nsWindow::WidgetTypeSupportsAcceleration +@@ -886,7 +897,7 @@ nsWindow::WidgetTypeSupportsAcceleration void nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) { @@ -6892,7 +2606,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w NS_ASSERTION(!mIsDestroyed, ""); NS_ASSERTION(!static_cast(aNewParent)->mIsDestroyed, ""); -@@ -1517,7 +1559,7 @@ nsWindow::GetClientBounds() +@@ -1517,7 +1528,7 @@ nsWindow::GetClientBounds() void nsWindow::UpdateClientOffset() { @@ -6901,23 +2615,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w if (!mIsTopLevel || !mShell || !mIsX11Display || gtk_window_get_window_type(GTK_WINDOW(mShell)) == GTK_WINDOW_POPUP) { -@@ -1738,6 +1780,15 @@ nsWindow::GetNativeData(uint32_t aDataTy - case NS_NATIVE_COMPOSITOR_DISPLAY: - return gfxPlatformGtk::GetPlatform()->GetCompositorDisplay(); - #endif // MOZ_X11 -+ case NS_NATIVE_EGL_WINDOW: { -+ if (mIsX11Display) -+ return mGdkWindow ? (void*)GDK_WINDOW_XID(mGdkWindow) : nullptr; -+#ifdef MOZ_WAYLAND -+ if (mContainer) -+ return moz_container_get_wl_egl_window(mContainer); -+#endif -+ return nullptr; -+ } - default: - NS_WARNING("nsWindow::GetNativeData called with bad value"); - return nullptr; -@@ -2057,6 +2108,12 @@ nsWindow::OnExposeEvent(cairo_t *cr) +@@ -2057,6 +2068,12 @@ nsWindow::OnExposeEvent(cairo_t *cr) if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel) return FALSE; @@ -6930,174 +2628,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w nsIWidgetListener *listener = GetListener(); if (!listener) return FALSE; -@@ -2112,10 +2169,7 @@ nsWindow::OnExposeEvent(cairo_t *cr) - - bool shaped = false; - if (eTransparencyTransparent == GetTransparencyMode()) { -- GdkScreen *screen = gdk_window_get_screen(mGdkWindow); -- if (gdk_screen_is_composited(screen) && -- gdk_window_get_visual(mGdkWindow) == -- gdk_screen_get_rgba_visual(screen)) { -+ if (mHasAlphaVisual) { - // Remove possible shape mask from when window manger was not - // previously compositing. - static_cast(GetTopLevelWidget())-> -@@ -2216,12 +2270,9 @@ nsWindow::OnExposeEvent(cairo_t *cr) - bool painted = false; - { - if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { -- GdkScreen *screen = gdk_window_get_screen(mGdkWindow); - if (GetTransparencyMode() == eTransparencyTransparent && - layerBuffering == BufferMode::BUFFER_NONE && -- gdk_screen_is_composited(screen) && -- gdk_window_get_visual(mGdkWindow) == -- gdk_screen_get_rgba_visual(screen)) { -+ mHasAlphaVisual) { - // If our draw target is unbuffered and we use an alpha channel, - // clear the image beforehand to ensure we don't get artifacts from a - // reused SHM image. See bug 1258086. -@@ -2354,7 +2405,7 @@ nsWindow::OnConfigureEvent(GtkWidget *aW - // - // These windows should not be moved by the window manager, and so any - // change in position is a result of our direction. mBounds has -- // already been set in Move() or Resize(), and that is more -+ // already been set in std::move() or Resize(), and that is more - // up-to-date than the position in the ConfigureNotify event if the - // event is from an earlier window move. - // -@@ -2888,7 +2939,7 @@ nsWindow::OnContainerFocusOutEvent(GdkEv - bool shouldRollup = !dragSession; - if (!shouldRollup) { - // we also roll up when a drag is from a different application -- nsCOMPtr sourceNode; -+ nsCOMPtr sourceNode; - dragSession->GetSourceNode(getter_AddRefs(sourceNode)); - shouldRollup = (sourceNode == nullptr); - } -@@ -2915,8 +2966,8 @@ bool - nsWindow::DispatchCommandEvent(nsAtom* aCommand) - { - nsEventStatus status; -- WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, aCommand, this); -- DispatchEvent(&event, status); -+ WidgetCommandEvent appCommandEvent(true, aCommand, this); -+ DispatchEvent(&appCommandEvent, status); - return TRUE; - } - -@@ -2938,30 +2989,44 @@ IsCtrlAltTab(GdkEventKey *aEvent) - } - - bool --nsWindow::DispatchKeyDownEvent(GdkEventKey *aEvent, bool *aCancelled) -+nsWindow::DispatchKeyDownOrKeyUpEvent(GdkEventKey* aEvent, -+ bool aIsProcessedByIME, -+ bool* aIsCancelled) - { -- NS_PRECONDITION(aCancelled, "aCancelled must not be null"); -+ MOZ_ASSERT(aIsCancelled, "aIsCancelled must not be nullptr"); - -- *aCancelled = false; -+ *aIsCancelled = false; - -- if (IsCtrlAltTab(aEvent)) { -+ if (aEvent->type == GDK_KEY_PRESS && IsCtrlAltTab(aEvent)) { - return false; - } - -+ EventMessage message = -+ aEvent->type == GDK_KEY_PRESS ? eKeyDown : eKeyUp; -+ WidgetKeyboardEvent keyEvent(true, message, this); -+ KeymapWrapper::InitKeyEvent(keyEvent, aEvent, aIsProcessedByIME); -+ return DispatchKeyDownOrKeyUpEvent(keyEvent, aIsCancelled); -+} -+bool -+nsWindow::DispatchKeyDownOrKeyUpEvent(WidgetKeyboardEvent& aKeyboardEvent, -+ bool* aIsCancelled) -+{ -+ MOZ_ASSERT(aIsCancelled, "aIsCancelled must not be nullptr"); -+ -+ *aIsCancelled = false; -+ - RefPtr dispatcher = GetTextEventDispatcher(); - nsresult rv = dispatcher->BeginNativeInputTransaction(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return FALSE; - } - -- WidgetKeyboardEvent keydownEvent(true, eKeyDown, this); -- KeymapWrapper::InitKeyEvent(keydownEvent, aEvent); - nsEventStatus status = nsEventStatus_eIgnore; - bool dispatched = -- dispatcher->DispatchKeyboardEvent(eKeyDown, keydownEvent, -- status, aEvent); -- *aCancelled = (status == nsEventStatus_eConsumeNoDefault); -- return dispatched ? TRUE : FALSE; -+ dispatcher->DispatchKeyboardEvent(aKeyboardEvent.mMessage, -+ aKeyboardEvent, status, nullptr); -+ *aIsCancelled = (status == nsEventStatus_eConsumeNoDefault); -+ return dispatched; - } - - WidgetEventTime -@@ -3046,7 +3111,7 @@ nsWindow::OnKeyPressEvent(GdkEventKey *a - // KEYDOWN -> KEYPRESS -> KEYUP -> KEYDOWN -> KEYPRESS -> KEYUP... - - bool isKeyDownCancelled = false; -- if (DispatchKeyDownEvent(aEvent, &isKeyDownCancelled) && -+ if (DispatchKeyDownOrKeyUpEvent(aEvent, false, &isKeyDownCancelled) && - (MOZ_UNLIKELY(mIsDestroyed) || isKeyDownCancelled)) { - return TRUE; - } -@@ -3095,7 +3160,7 @@ nsWindow::OnKeyPressEvent(GdkEventKey *a - } - - WidgetKeyboardEvent keypressEvent(true, eKeyPress, this); -- KeymapWrapper::InitKeyEvent(keypressEvent, aEvent); -+ KeymapWrapper::InitKeyEvent(keypressEvent, aEvent, false); - - // before we dispatch a key, check if it's the context menu key. - // If so, send a context menu key event instead. -@@ -3179,7 +3244,7 @@ nsWindow::MaybeDispatchContextMenuEvent( - } - - gboolean --nsWindow::OnKeyReleaseEvent(GdkEventKey *aEvent) -+nsWindow::OnKeyReleaseEvent(GdkEventKey* aEvent) - { - LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this)); - -@@ -3187,17 +3252,11 @@ nsWindow::OnKeyReleaseEvent(GdkEventKey - return TRUE; - } - -- RefPtr dispatcher = GetTextEventDispatcher(); -- nsresult rv = dispatcher->BeginNativeInputTransaction(); -- if (NS_WARN_IF(NS_FAILED(rv))) { -- return false; -+ bool isCancelled = false; -+ if (NS_WARN_IF(!DispatchKeyDownOrKeyUpEvent(aEvent, false, &isCancelled))) { -+ return FALSE; - } - -- WidgetKeyboardEvent keyupEvent(true, eKeyUp, this); -- KeymapWrapper::InitKeyEvent(keyupEvent, aEvent); -- nsEventStatus status = nsEventStatus_eIgnore; -- dispatcher->DispatchKeyboardEvent(eKeyUp, keyupEvent, status, aEvent); -- - return TRUE; - } - -@@ -3214,7 +3273,7 @@ nsWindow::OnScrollEvent(GdkEventScroll * - return; - #endif - WidgetWheelEvent wheelEvent(true, eWheel, this); -- wheelEvent.mDeltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE; -+ wheelEvent.mDeltaMode = dom::WheelEvent_Binding::DOM_DELTA_LINE; - switch (aEvent->direction) { - #if GTK_CHECK_VERSION(3,4,0) - case GDK_SCROLL_SMOOTH: -@@ -3318,6 +3377,33 @@ nsWindow::OnWindowStateEvent(GtkWidget * +@@ -3318,6 +3335,33 @@ nsWindow::OnWindowStateEvent(GtkWidget * } // else the widget is a shell widget. @@ -7131,7 +2662,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w // We don't care about anything but changes in the maximized/icon/fullscreen // states if ((aEvent->changed_mask -@@ -3404,6 +3490,7 @@ nsWindow::OnDPIChanged() +@@ -3404,6 +3448,7 @@ nsWindow::OnDPIChanged() // Update menu's font size etc presShell->ThemeChanged(); } @@ -7139,81 +2670,26 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } } -@@ -3611,6 +3698,8 @@ nsWindow::Create(nsIWidget* aParent, +@@ -3611,6 +3656,7 @@ nsWindow::Create(nsIWidget* aParent, nsWindow *parentnsWindow = nullptr; GtkWidget *eventWidget = nullptr; bool drawToContainer = false; -+ bool needsAlphaVisual = (mWindowType == eWindowType_popup && -+ aInitData->mSupportTranslucency); ++ bool useAlphaVisual = false; if (aParent) { parentnsWindow = static_cast(aParent); -@@ -3661,23 +3750,47 @@ nsWindow::Create(nsIWidget* aParent, +@@ -3661,8 +3707,8 @@ nsWindow::Create(nsIWidget* aParent, } mShell = gtk_window_new(type); - bool useAlphaVisual = (mWindowType == eWindowType_popup && - aInitData->mSupportTranslucency); -- -- // mozilla.widget.use-argb-visuals is a hidden pref defaulting to false -- // to allow experimentation -- if (Preferences::GetBool("mozilla.widget.use-argb-visuals", false)) -- useAlphaVisual = true; -- -- // We need to select an ARGB visual here instead of in -- // SetTransparencyMode() because it has to be done before the -- // widget is realized. An ARGB visual is only useful if we -- // are on a compositing window manager. -- if (useAlphaVisual) { -- GdkScreen *screen = gtk_widget_get_screen(mShell); -- if (gdk_screen_is_composited(screen)) { -- GdkVisual *visual = gdk_screen_get_rgba_visual(screen); -- gtk_widget_set_visual(mShell, visual); -+#ifdef MOZ_X11 -+ // Ensure gfxPlatform is initialized, since that is what initializes -+ // gfxVars, used below. -+ Unused << gfxPlatform::GetPlatform(); -+ -+ bool useWebRender = gfx::gfxVars::UseWebRender() && -+ AllowWebRenderForThisWindow(); -+ -+ // If using WebRender on X11, we need to select a visual with a depth buffer, -+ // as well as an alpha channel if transparency is requested. This must be done -+ // before the widget is realized. -+ if (mIsX11Display && useWebRender) { -+ auto display = -+ GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(mShell)); -+ auto screen = gtk_widget_get_screen(mShell); -+ int screenNumber = GDK_SCREEN_XNUMBER(screen); -+ int visualId = 0; -+ if (GLContextGLX::FindVisual(display, screenNumber, -+ useWebRender, needsAlphaVisual, -+ &visualId)) { -+ // If we're using CSD, rendering will go through mContainer, but -+ // it will inherit this visual as it is a child of mShell. -+ gtk_widget_set_visual(mShell, -+ gdk_x11_screen_lookup_visual(screen, -+ visualId)); -+ mHasAlphaVisual = needsAlphaVisual; -+ } else { -+ NS_WARNING("We're missing X11 Visual for WebRender!"); -+ } -+ } else -+#endif // MOZ_X11 -+ { -+ if (needsAlphaVisual) { -+ GdkScreen *screen = gtk_widget_get_screen(mShell); -+ if (gdk_screen_is_composited(screen)) { -+ GdkVisual *visual = gdk_screen_get_rgba_visual(screen); -+ if (visual) { -+ gtk_widget_set_visual(mShell, visual); -+ mHasAlphaVisual = true; -+ } -+ } - } - } ++ useAlphaVisual = (mWindowType == eWindowType_popup && ++ aInitData->mSupportTranslucency); -@@ -3784,7 +3897,7 @@ nsWindow::Create(nsIWidget* aParent, + // mozilla.widget.use-argb-visuals is a hidden pref defaulting to false + // to allow experimentation +@@ -3784,7 +3830,7 @@ nsWindow::Create(nsIWidget* aParent, // it explicitly now. gtk_widget_realize(mShell); @@ -7222,7 +2698,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w * * 1) We're running on Gtk+ without client side decorations. * Content is rendered to mShell window and we listen -@@ -3859,17 +3972,7 @@ nsWindow::Create(nsIWidget* aParent, +@@ -3859,17 +3905,7 @@ nsWindow::Create(nsIWidget* aParent, // If the window were to get unredirected, there could be visible // tearing because Gecko does not align its framebuffer updates with // vblank. @@ -7241,7 +2717,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w #endif } break; -@@ -3949,10 +4052,13 @@ nsWindow::Create(nsIWidget* aParent, +@@ -3949,10 +3985,13 @@ nsWindow::Create(nsIWidget* aParent, GtkSettings* default_settings = gtk_settings_get_default(); g_signal_connect_after(default_settings, "notify::gtk-theme-name", @@ -7257,19 +2733,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } if (mContainer) { -@@ -4070,8 +4176,10 @@ nsWindow::Create(nsIWidget* aParent, - GdkVisual* gdkVisual = gdk_window_get_visual(mGdkWindow); - mXVisual = gdk_x11_visual_get_xvisual(gdkVisual); - mXDepth = gdk_visual_get_depth(gdkVisual); -+ bool shaped = needsAlphaVisual && !mHasAlphaVisual; - -- mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth); -+ mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth, -+ shaped); - } - #ifdef MOZ_WAYLAND - else if (!mIsX11Display) { -@@ -4083,60 +4191,70 @@ nsWindow::Create(nsIWidget* aParent, +@@ -4083,60 +4122,70 @@ nsWindow::Create(nsIWidget* aParent, } void @@ -7384,7 +2848,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } void -@@ -4162,6 +4280,8 @@ nsWindow::NativeResize() +@@ -4162,6 +4211,8 @@ nsWindow::NativeResize() size.width, size.height)); if (mIsTopLevel) { @@ -7393,7 +2857,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height); } else if (mContainer) { -@@ -4207,6 +4327,8 @@ nsWindow::NativeMoveResize() +@@ -4207,6 +4258,8 @@ nsWindow::NativeMoveResize() NativeShow(false); } NativeMove(); @@ -7402,7 +2866,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } GdkRectangle size = DevicePixelsToGdkSizeRoundUp(mBounds.Size()); -@@ -4219,6 +4341,8 @@ nsWindow::NativeMoveResize() +@@ -4219,6 +4272,8 @@ nsWindow::NativeMoveResize() // x and y give the position of the window manager frame top-left. gtk_window_move(GTK_WINDOW(mShell), topLeft.x, topLeft.y); // This sets the client window size. @@ -7411,7 +2875,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height); } else if (mContainer) { -@@ -4271,6 +4395,16 @@ nsWindow::NativeShow(bool aAction) +@@ -4271,6 +4326,16 @@ nsWindow::NativeShow(bool aAction) } } else { @@ -7428,7 +2892,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w if (mIsTopLevel) { // Workaround window freezes on GTK versions before 3.21.2 by // ensuring that configure events get dispatched to windows before -@@ -4946,6 +5080,8 @@ FullscreenTransitionWindow::FullscreenTr +@@ -4946,6 +5011,8 @@ FullscreenTransitionWindow::FullscreenTr gdk_screen_get_monitor_geometry(screen, monitorNum, &monitorRect); gtk_window_set_screen(gtkWin, screen); gtk_window_move(gtkWin, monitorRect.x, monitorRect.y); @@ -7437,7 +2901,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w gtk_window_resize(gtkWin, monitorRect.width, monitorRect.height); GdkColor bgColor; -@@ -5951,7 +6087,7 @@ window_state_event_cb (GtkWidget *widget +@@ -5951,7 +6018,7 @@ window_state_event_cb (GtkWidget *widget } static void @@ -7446,7 +2910,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w { RefPtr window = data; window->ThemeChanged(); -@@ -6032,13 +6168,13 @@ nsWindow::InitDragEvent(WidgetDragEvent +@@ -6032,13 +6099,13 @@ nsWindow::InitDragEvent(WidgetDragEvent KeymapWrapper::InitInputEvent(aEvent, modifierState); } @@ -7467,7 +2931,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w { RefPtr window = get_window_for_gtk_widget(aWidget); if (!window) -@@ -6063,15 +6199,24 @@ drag_motion_event_cb(GtkWidget *aWidget, +@@ -6063,15 +6130,24 @@ drag_motion_event_cb(GtkWidget *aWidget, RefPtr dragService = nsDragService::GetInstance(); return dragService-> @@ -7498,7 +2962,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w { RefPtr window = get_window_for_gtk_widget(aWidget); if (!window) -@@ -6104,14 +6249,22 @@ drag_leave_event_cb(GtkWidget *aWidget, +@@ -6104,14 +6180,22 @@ drag_leave_event_cb(GtkWidget *aWidget, dragService->ScheduleLeaveEvent(); } @@ -7528,7 +2992,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w { RefPtr window = get_window_for_gtk_widget(aWidget); if (!window) -@@ -6136,10 +6289,21 @@ drag_drop_event_cb(GtkWidget *aWidget, +@@ -6136,10 +6220,21 @@ drag_drop_event_cb(GtkWidget *aWidget, RefPtr dragService = nsDragService::GetInstance(); return dragService-> @@ -7551,7 +3015,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w static void drag_data_received_event_cb(GtkWidget *aWidget, GdkDragContext *aDragContext, -@@ -6554,12 +6718,6 @@ nsWindow::GetLayerManager(PLayerTransact +@@ -6554,12 +6649,6 @@ nsWindow::GetLayerManager(PLayerTransact return mLayerManager; } @@ -7564,7 +3028,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w return nsBaseWidget::GetLayerManager(aShadowManager, aBackendHint, aPersistence); } -@@ -6601,6 +6759,13 @@ nsWindow::ClearCachedResources() +@@ -6601,6 +6690,13 @@ nsWindow::ClearCachedResources() void nsWindow::UpdateClientOffsetForCSDWindow() { @@ -7578,7 +3042,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w // _NET_FRAME_EXTENTS is not set on client decorated windows, // so we need to read offset between mContainer and toplevel mShell // window. -@@ -6692,6 +6857,15 @@ nsWindow::SetDrawsInTitlebar(bool aState +@@ -6692,6 +6788,15 @@ nsWindow::SetDrawsInTitlebar(bool aState mNeedsShow = true; NativeResize(); @@ -7594,7 +3058,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w // When we use system titlebar setup managed by Gtk+ we also get // _NET_FRAME_EXTENTS property for our toplevel window so we can't // update the client offset it here. -@@ -6998,6 +7172,8 @@ nsWindow::GetSystemCSDSupportLevel() { +@@ -6998,6 +7103,8 @@ nsWindow::GetSystemCSDSupportLevel() { // KDE Plasma } else if (strstr(currentDesktop, "KDE") != nullptr) { sCSDSupportLevel = CSD_SUPPORT_CLIENT; @@ -7603,7 +3067,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } else if (strstr(currentDesktop, "LXDE") != nullptr) { sCSDSupportLevel = CSD_SUPPORT_CLIENT; } else if (strstr(currentDesktop, "openbox") != nullptr) { -@@ -7014,6 +7190,8 @@ nsWindow::GetSystemCSDSupportLevel() { +@@ -7014,6 +7121,8 @@ nsWindow::GetSystemCSDSupportLevel() { sCSDSupportLevel = CSD_SUPPORT_SYSTEM; } else if (strstr(currentDesktop, "LXQt") != nullptr) { sCSDSupportLevel = CSD_SUPPORT_SYSTEM; @@ -7612,7 +3076,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w } else { // Release or beta builds are not supposed to be broken // so disable titlebar rendering on untested/unknown systems. -@@ -7066,26 +7244,19 @@ nsWindow::RoundsWidgetCoordinatesTo() +@@ -7066,26 +7175,18 @@ nsWindow::RoundsWidgetCoordinatesTo() void nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) { @@ -7625,7 +3089,6 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w *aInitData = mozilla::widget::GtkCompositorWidgetInitData( (mXWindow != X11None) ? mXWindow : (uintptr_t)nullptr, mXDisplay ? nsCString(XDisplayString(mXDisplay)) : nsCString(), -+ mIsTransparent && !mHasAlphaVisual, GetClientSize()); } @@ -7646,7 +3109,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w #ifdef MOZ_WAYLAND wl_display* nsWindow::GetWaylandDisplay() -@@ -7110,3 +7281,120 @@ nsWindow::GetWaylandSurface() +@@ -7110,3 +7211,85 @@ nsWindow::GetWaylandSurface() return nullptr; } #endif @@ -7731,45 +3194,10 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.3.0/w +} +#endif + -+nsresult -+nsWindow::SetSystemFont(const nsCString& aFontName) -+{ -+ GtkSettings* settings = gtk_settings_get_default(); -+ g_object_set(settings, "gtk-font-name", aFontName.get(), nullptr); -+ return NS_OK; -+} + -+nsresult -+nsWindow::GetSystemFont(nsCString& aFontName) -+{ -+ GtkSettings* settings = gtk_settings_get_default(); -+ gchar* fontName = nullptr; -+ g_object_get(settings, -+ "gtk-font-name", &fontName, -+ nullptr); -+ if (fontName) { -+ aFontName.Assign(fontName); -+ g_free(fontName); -+ } -+ return NS_OK; -+} -+ -+already_AddRefed -+nsIWidget::CreateTopLevelWindow() -+{ -+ nsCOMPtr window = new nsWindow(); -+ return window.forget(); -+} -+ -+already_AddRefed -+nsIWidget::CreateChildWindow() -+{ -+ nsCOMPtr window = new nsWindow(); -+ return window.forget(); -+} diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/widget/gtk/nsWindow.h --- thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/nsWindow.h 2018-11-20 12:04:43.741787337 +0100 ++++ thunderbird-60.3.0/widget/gtk/nsWindow.h 2018-11-21 13:42:00.762025644 +0100 @@ -66,6 +66,21 @@ extern mozilla::LazyLogModule gWidgetDra #endif /* MOZ_LOGGING */ @@ -7800,15 +3228,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid typedef mozilla::widget::PlatformCompositorWidgetDelegate PlatformCompositorWidgetDelegate; nsWindow(); -@@ -108,6 +124,7 @@ public: - virtual float GetDPI() override; - virtual double GetDefaultScaleInternal() override; - mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override; -+ mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScaleByScreen() override; - virtual void SetParent(nsIWidget* aNewParent) override; - virtual void SetModal(bool aModal) override; - virtual bool IsVisible() const override; -@@ -115,8 +132,7 @@ public: +@@ -115,8 +131,7 @@ public: int32_t *aX, int32_t *aY) override; virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override; @@ -7818,7 +3238,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid virtual void Show (bool aState) override; virtual void Resize (double aWidth, double aHeight, -@@ -228,6 +244,8 @@ public: +@@ -228,6 +243,8 @@ public: virtual void EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aInvalidRegion) override; @@ -7827,54 +3247,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid private: void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface, nsIntRect aBoundsRect); -@@ -278,10 +296,32 @@ public: - guint aTime); - static void UpdateDragStatus (GdkDragContext *aDragContext, - nsIDragService *aDragService); -- // If this dispatched the keydown event actually, this returns TRUE, -- // otherwise, FALSE. -- bool DispatchKeyDownEvent(GdkEventKey *aEvent, -- bool *aIsCancelled); -+ /** -+ * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event. -+ * -+ * @param aEvent A native GDK_KEY_PRESS or GDK_KEY_RELEASE -+ * event. -+ * @param aProcessedByIME true if the event is handled by IME. -+ * @param aIsCancelled [Out] true if the default is prevented. -+ * @return true if eKeyDown event is actually dispatched. -+ * Otherwise, false. -+ */ -+ bool DispatchKeyDownOrKeyUpEvent(GdkEventKey* aEvent, -+ bool aProcessedByIME, -+ bool* aIsCancelled); -+ -+ /** -+ * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event. -+ * -+ * @param aEvent An eKeyDown or eKeyUp event. This will be -+ * dispatched as is. -+ * @param aIsCancelled [Out] true if the default is prevented. -+ * @return true if eKeyDown event is actually dispatched. -+ * Otherwise, false. -+ */ -+ bool DispatchKeyDownOrKeyUpEvent(WidgetKeyboardEvent& aEvent, -+ bool* aIsCancelled); -+ - WidgetEventTime GetWidgetEventTime(guint32 aEventTime); - mozilla::TimeStamp GetEventTimeStamp(guint32 aEventTime); - mozilla::CurrentX11TimeGetter* GetCurrentTimeGetter(); -@@ -375,6 +415,9 @@ public: - - virtual bool WidgetTypeSupportsAcceleration() override; - -+ nsresult SetSystemFont(const nsCString& aFontName) override; -+ nsresult GetSystemFont(nsCString& aFontName) override; -+ - typedef enum { CSD_SUPPORT_SYSTEM, // CSD including shadows - CSD_SUPPORT_CLIENT, // CSD without shadows - CSD_SUPPORT_NONE, // WM does not support CSD at all -@@ -452,13 +495,24 @@ private: +@@ -452,13 +469,24 @@ private: gint* aRootX, gint* aRootY); void ClearCachedResources(); nsIWidgetListener* GetListener(); @@ -7900,7 +3273,7 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid GtkWidget *mShell; MozContainer *mContainer; GdkWindow *mGdkWindow; -@@ -558,6 +612,9 @@ private: +@@ -558,6 +586,9 @@ private: // full translucency at this time; each pixel is either fully opaque // or fully transparent. gchar* mTransparencyBitmap; @@ -7910,96 +3283,9 @@ diff -up thunderbird-60.3.0/widget/gtk/nsWindow.h.wayland thunderbird-60.3.0/wid // all of our DND stuff void InitDragEvent(mozilla::WidgetDragEvent& aEvent); -diff -up thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh.wayland thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh ---- thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/PlatformWidgetTypes.ipdlh 2018-11-20 12:04:43.741787337 +0100 -@@ -15,6 +15,7 @@ struct GtkCompositorWidgetInitData - { - uintptr_t XWindow; - nsCString XDisplayString; -+ bool Shaped; - - LayoutDeviceIntSize InitialClientSize; - }; -diff -up thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp.wayland thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp ---- thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/ScreenHelperGTK.cpp 2018-11-20 12:04:43.741787337 +0100 -@@ -197,7 +197,7 @@ ScreenHelperGTK::RefreshScreens() - } - - ScreenManager& screenManager = ScreenManager::GetSingleton(); -- screenManager.Refresh(Move(screenList)); -+ screenManager.Refresh(std::move(screenList)); - } - - } // namespace widget -diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp ---- thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.cpp 2018-11-20 12:04:43.741787337 +0100 -@@ -31,6 +31,7 @@ WindowSurfaceProvider::WindowSurfaceProv - #ifdef MOZ_WAYLAND - , mWidget(nullptr) - #endif -+ , mIsShaped(false) - { - } - -@@ -38,7 +39,8 @@ void WindowSurfaceProvider::Initialize( - Display* aDisplay, - Window aWindow, - Visual* aVisual, -- int aDepth) -+ int aDepth, -+ bool aIsShaped) - { - // We should not be initialized - MOZ_ASSERT(!mXDisplay); -@@ -50,6 +52,7 @@ void WindowSurfaceProvider::Initialize( - mXWindow = aWindow; - mXVisual = aVisual; - mXDepth = aDepth; -+ mIsShaped = aIsShaped; - mIsX11Display = true; - } - -@@ -88,21 +91,22 @@ WindowSurfaceProvider::CreateWindowSurfa - // 3. XPutImage - - #ifdef MOZ_WIDGET_GTK -- if (gfxVars::UseXRender()) { -+ if (!mIsShaped && gfxVars::UseXRender()) { - LOGDRAW(("Drawing to nsWindow %p using XRender\n", (void*)this)); - return MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); - } - #endif // MOZ_WIDGET_GTK - - #ifdef MOZ_HAVE_SHMIMAGE -- if (nsShmImage::UseShm()) { -+ if (!mIsShaped && nsShmImage::UseShm()) { - LOGDRAW(("Drawing to nsWindow %p using MIT-SHM\n", (void*)this)); - return MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); - } - #endif // MOZ_HAVE_SHMIMAGE - - LOGDRAW(("Drawing to nsWindow %p using XPutImage\n", (void*)this)); -- return MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); -+ return MakeUnique(mXDisplay, mXWindow, mXVisual, -+ mXDepth, mIsShaped); - } - - already_AddRefed -@@ -125,7 +129,7 @@ WindowSurfaceProvider::StartRemoteDrawin - // We can't use WindowSurfaceX11Image fallback on Wayland but - // Lock() call on WindowSurfaceWayland should never fail. - gfxWarningOnce() << "Failed to lock WindowSurface, falling back to XPutImage backend."; -- mWindowSurface = MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth); -+ mWindowSurface = MakeUnique(mXDisplay, mXWindow, mXVisual, mXDepth, mIsShaped); - dt = mWindowSurface->Lock(aInvalidRegion); - } - return dt.forget(); diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h --- thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h.wayland 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h 2018-11-20 12:04:43.742787334 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h 2018-11-21 13:42:00.762025644 +0100 @@ -17,6 +17,7 @@ #include #endif @@ -8008,27 +3294,9 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceProvider.h.wayland thunderbi class nsWindow; -@@ -43,7 +44,8 @@ public: - Display* aDisplay, - Window aWindow, - Visual* aVisual, -- int aDepth); -+ int aDepth, -+ bool aIsShaped); - - #ifdef MOZ_WAYLAND - void Initialize(nsWindow *aWidget); -@@ -75,6 +77,7 @@ private: - #ifdef MOZ_WAYLAND - nsWindow* mWidget; - #endif -+ bool mIsShaped; - }; - - } // namespace widget diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp --- thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp 2018-11-20 12:04:43.742787334 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp 2018-11-21 13:42:00.763025640 +0100 @@ -151,8 +151,9 @@ static nsWaylandDisplay* WaylandDisplayG static void WaylandDisplayRelease(wl_display *aDisplay); static void WaylandDisplayLoop(wl_display *aDisplay); @@ -8072,16 +3340,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb return gfxPlatform::CreateDrawTargetForData(static_cast(mShmPool.GetImageData()), lockSize, BUFFER_BPP * mWidth, -@@ -551,6 +551,8 @@ frame_callback_handler(void *data, struc - { - auto surface = reinterpret_cast(data); - surface->FrameCallbackHandler(); -+ -+ gfxPlatformGtk::GetPlatform()->SetWaylandLastVsync(time); - } - - static const struct wl_callback_listener frame_listener = { -@@ -560,26 +562,40 @@ static const struct wl_callback_listener +@@ -560,26 +560,40 @@ static const struct wl_callback_listener WindowSurfaceWayland::WindowSurfaceWayland(nsWindow *aWindow) : mWindow(aWindow) , mWaylandDisplay(WaylandDisplayGet(aWindow->GetWaylandDisplay())) @@ -8129,7 +3388,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb if (!mIsMainThread) { // We can be destroyed from main thread even though we was created/used // in compositor thread. We have to unref/delete WaylandDisplay in compositor -@@ -593,162 +609,309 @@ WindowSurfaceWayland::~WindowSurfaceWayl +@@ -593,162 +607,309 @@ WindowSurfaceWayland::~WindowSurfaceWayl } } @@ -8216,13 +3475,14 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + WindowBackBuffer* buffer = GetWaylandBufferToDraw(aWidth, aHeight); + if (buffer) { + return buffer->Lock(); -+ } -+ + } + +- return mFrontBuffer; + NS_WARNING("WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); + return nullptr; -+} -+ -+already_AddRefed + } + + already_AddRefed +WindowSurfaceWayland::LockImageSurface(const gfx::IntSize& aLockSize) +{ + if (!mImageSurface || mImageSurface->CairoStatus() || @@ -8232,15 +3492,14 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + if (mImageSurface->CairoStatus()) { + return nullptr; + } - } - -- return mFrontBuffer; ++ } ++ + return gfxPlatform::CreateDrawTargetForData(mImageSurface->Data(), + mImageSurface->GetSize(), + mImageSurface->Stride(), + mWaylandDisplay->GetSurfaceFormat()); - } - ++} ++ +/* + There are some situations which can happen here: + @@ -8254,7 +3513,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + B) Lock() is requested for part(s) of screen. We need to provide temporary + surface to draw into and copy result (clipped) to target wl_surface. + */ - already_AddRefed ++already_AddRefed WindowSurfaceWayland::Lock(const LayoutDeviceIntRegion& aRegion) { MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); @@ -8287,9 +3546,8 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + // We don't have any front buffer available. Try indirect drawing + // to mImageSurface which is mirrored to front buffer at commit. + mDrawToWaylandBufferDirectly = false; - } - -- return buffer->Lock(aRegion); ++ } ++ + return LockImageSurface(lockSize); +} + @@ -8314,8 +3572,9 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb + mImageSurface->Format()); + if (!dt || !surf) { + return false; -+ } -+ + } + +- return buffer->Lock(aRegion); + uint32_t numRects = aRegion.GetNumRects(); + if (numRects != 1) { + AutoTArray rects; @@ -8529,7 +3788,7 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.cpp.wayland thunderb diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h --- thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h 2018-11-20 12:04:43.742787334 +0100 ++++ thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h 2018-11-21 13:42:00.763025640 +0100 @@ -8,6 +8,7 @@ #define _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H @@ -8594,238 +3853,4 @@ diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceWayland.h.wayland thunderbir + bool mNeedScaleFactorUpdate; }; - } // namespace widget -diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp ---- thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.cpp 2018-11-20 12:04:43.743787331 +0100 -@@ -12,19 +12,42 @@ - #include "gfxPlatform.h" - #include "gfx2DGlue.h" - -+#include -+ - namespace mozilla { - namespace widget { - -+// gfxImageSurface pixel format configuration. -+#define SHAPED_IMAGE_SURFACE_BPP 4 -+#ifdef IS_BIG_ENDIAN -+ #define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 0 -+#else -+ #define SHAPED_IMAGE_SURFACE_ALPHA_INDEX 3 -+#endif -+ - WindowSurfaceX11Image::WindowSurfaceX11Image(Display* aDisplay, - Window aWindow, - Visual* aVisual, -- unsigned int aDepth) -+ unsigned int aDepth, -+ bool aIsShaped) - : WindowSurfaceX11(aDisplay, aWindow, aVisual, aDepth) -+ , mTransparencyBitmap(nullptr) -+ , mTransparencyBitmapWidth(0) -+ , mTransparencyBitmapHeight(0) -+ , mIsShaped(aIsShaped) - { - } - - WindowSurfaceX11Image::~WindowSurfaceX11Image() - { -+ if (mTransparencyBitmap) { -+ delete[] mTransparencyBitmap; -+ -+ Display* xDisplay = mWindowSurface->XDisplay(); -+ Window xDrawable = mWindowSurface->XDrawable(); -+ -+ XShapeCombineMask(xDisplay, xDrawable, ShapeBounding, 0, 0, X11None, ShapeSet); -+ } - } - - already_AddRefed -@@ -50,6 +73,13 @@ WindowSurfaceX11Image::Lock(const Layout - gfx::SurfaceFormat::X8R8G8B8_UINT32; - } - -+ // Use alpha image format for shaped window as we derive -+ // the shape bitmap from alpha channel. Must match SHAPED_IMAGE_SURFACE_BPP -+ // and SHAPED_IMAGE_SURFACE_ALPHA_INDEX. -+ if (mIsShaped) { -+ format = gfx::SurfaceFormat::A8R8G8B8_UINT32; -+ } -+ - mImageSurface = new gfxImageSurface(size, format); - if (mImageSurface->CairoStatus()) { - return nullptr; -@@ -82,6 +112,132 @@ WindowSurfaceX11Image::Lock(const Layout - ImageFormatToSurfaceFormat(format)); - } - -+// The transparency bitmap routines are derived form the ones at nsWindow.cpp. -+// The difference here is that we compose to RGBA image and then create -+// the shape mask from final image alpha channel. -+static inline int32_t -+GetBitmapStride(int32_t width) -+{ -+ return (width+7)/8; -+} -+ -+static bool -+ChangedMaskBits(gchar* aMaskBits, int32_t aMaskWidth, int32_t aMaskHeight, -+ const nsIntRect& aRect, uint8_t* aImageData) -+{ -+ int32_t stride = aMaskWidth*SHAPED_IMAGE_SURFACE_BPP; -+ int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost(); -+ int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth); -+ for (y = aRect.y; y < yMax; y++) { -+ gchar* maskBytes = aMaskBits + y*maskBytesPerRow; -+ uint8_t* alphas = aImageData; -+ for (x = aRect.x; x < xMax; x++) { -+ bool newBit = *(alphas+SHAPED_IMAGE_SURFACE_ALPHA_INDEX) > 0x7f; -+ alphas += SHAPED_IMAGE_SURFACE_BPP; -+ -+ gchar maskByte = maskBytes[x >> 3]; -+ bool maskBit = (maskByte & (1 << (x & 7))) != 0; -+ -+ if (maskBit != newBit) { -+ return true; -+ } -+ } -+ aImageData += stride; -+ } -+ -+ return false; -+} -+ -+static void -+UpdateMaskBits(gchar* aMaskBits, int32_t aMaskWidth, int32_t aMaskHeight, -+ const nsIntRect& aRect, uint8_t* aImageData) -+{ -+ int32_t stride = aMaskWidth*SHAPED_IMAGE_SURFACE_BPP; -+ int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost(); -+ int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth); -+ for (y = aRect.y; y < yMax; y++) { -+ gchar* maskBytes = aMaskBits + y*maskBytesPerRow; -+ uint8_t* alphas = aImageData; -+ for (x = aRect.x; x < xMax; x++) { -+ bool newBit = *(alphas+SHAPED_IMAGE_SURFACE_ALPHA_INDEX) > 0x7f; -+ alphas += SHAPED_IMAGE_SURFACE_BPP; -+ -+ gchar mask = 1 << (x & 7); -+ gchar maskByte = maskBytes[x >> 3]; -+ // Note: '-newBit' turns 0 into 00...00 and 1 into 11...11 -+ maskBytes[x >> 3] = (maskByte & ~mask) | (-newBit & mask); -+ } -+ aImageData += stride; -+ } -+} -+ -+void -+WindowSurfaceX11Image::ResizeTransparencyBitmap(int aWidth, int aHeight) -+{ -+ int32_t actualSize = -+ GetBitmapStride(mTransparencyBitmapWidth)*mTransparencyBitmapHeight; -+ int32_t newSize = GetBitmapStride(aWidth)*aHeight; -+ -+ if (actualSize < newSize) { -+ delete[] mTransparencyBitmap; -+ mTransparencyBitmap = new gchar[newSize]; -+ } -+ -+ mTransparencyBitmapWidth = aWidth; -+ mTransparencyBitmapHeight = aHeight; -+} -+ -+void -+WindowSurfaceX11Image::ApplyTransparencyBitmap() -+{ -+ gfx::IntSize size = mWindowSurface->GetSize(); -+ bool maskChanged = true; -+ -+ if (!mTransparencyBitmap) { -+ mTransparencyBitmapWidth = size.width; -+ mTransparencyBitmapHeight = size.height; -+ -+ int32_t byteSize = -+ GetBitmapStride(mTransparencyBitmapWidth)*mTransparencyBitmapHeight; -+ mTransparencyBitmap = new gchar[byteSize]; -+ } else { -+ bool sizeChanged = (size.width != mTransparencyBitmapWidth || -+ size.height != mTransparencyBitmapHeight); -+ -+ if (sizeChanged) { -+ ResizeTransparencyBitmap(size.width, size.height); -+ } else { -+ maskChanged = ChangedMaskBits(mTransparencyBitmap, -+ mTransparencyBitmapWidth, mTransparencyBitmapHeight, -+ nsIntRect(0, 0, size.width, size.height), -+ (uint8_t*)mImageSurface->Data()); -+ } -+ } -+ -+ if (maskChanged) { -+ UpdateMaskBits(mTransparencyBitmap, -+ mTransparencyBitmapWidth, -+ mTransparencyBitmapHeight, -+ nsIntRect(0, 0, size.width, size.height), -+ (uint8_t*)mImageSurface->Data()); -+ -+ // We use X11 calls where possible, because GDK handles expose events -+ // for shaped windows in a way that's incompatible with us (Bug 635903). -+ // It doesn't occur when the shapes are set through X. -+ Display* xDisplay = mWindowSurface->XDisplay(); -+ Window xDrawable = mWindowSurface->XDrawable(); -+ Pixmap maskPixmap = XCreateBitmapFromData(xDisplay, -+ xDrawable, -+ mTransparencyBitmap, -+ mTransparencyBitmapWidth, -+ mTransparencyBitmapHeight); -+ XShapeCombineMask(xDisplay, xDrawable, -+ ShapeBounding, 0, 0, -+ maskPixmap, ShapeSet); -+ XFreePixmap(xDisplay, maskPixmap); -+ } -+} -+ - void - WindowSurfaceX11Image::Commit(const LayoutDeviceIntRegion& aInvalidRegion) - { -@@ -112,6 +268,10 @@ WindowSurfaceX11Image::Commit(const Layo - dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); - } - -+ if (mIsShaped) { -+ ApplyTransparencyBitmap(); -+ } -+ - dt->DrawSurface(surf, rect, rect); - - if (numRects != 1) { -diff -up thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h.wayland thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h ---- thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h.wayland 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/gtk/WindowSurfaceX11Image.h 2018-11-20 12:04:43.743787331 +0100 -@@ -19,7 +19,7 @@ namespace widget { - class WindowSurfaceX11Image : public WindowSurfaceX11 { - public: - WindowSurfaceX11Image(Display* aDisplay, Window aWindow, Visual* aVisual, -- unsigned int aDepth); -+ unsigned int aDepth, bool aIsShaped); - ~WindowSurfaceX11Image(); - - already_AddRefed Lock(const LayoutDeviceIntRegion& aRegion) override; -@@ -27,8 +27,16 @@ public: - bool IsFallback() const override { return true; } - - private: -+ void ResizeTransparencyBitmap(int aWidth, int aHeight); -+ void ApplyTransparencyBitmap(); -+ - RefPtr mWindowSurface; - RefPtr mImageSurface; -+ -+ gchar* mTransparencyBitmap; -+ int32_t mTransparencyBitmapWidth; -+ int32_t mTransparencyBitmapHeight; -+ bool mIsShaped; - }; - } // namespace widget diff --git a/thunderbird.spec b/thunderbird.spec index 0f8882c..4fb592a 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -84,7 +84,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.3.0 -Release: 4%{?dist} +Release: 5%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -128,6 +128,7 @@ Patch309: mozilla-1460871-ldap-query.patch Patch310: disable-dbus-remote.patch Patch311: firefox-wayland.patch Patch312: thunderbird-dbus-remote.patch +Patch313: firefox-wayland-crash-mozbz1507475.patch # Upstream patches @@ -189,8 +190,6 @@ BuildRequires: dbus-glib-devel Obsoletes: thunderbird-lightning Provides: thunderbird-lightning Obsoletes: thunderbird-lightning-gdata <= 1:3.3.0.14 -#Conflicts: thunderbird-lightning-gdata <= 1:3.3.0.14 -#Obsoletes: thunderbird-52.9.1 BuildRequires: rust BuildRequires: cargo BuildRequires: clang-devel @@ -271,9 +270,9 @@ debug %{name}, you want to install %{name}-debuginfo instead. #cd .. # TODO - needs fixes -#%patch311 -p1 -b .wayland +%patch311 -p1 -b .wayland #%patch312 -p1 -b .thunderbird-dbus-remote - +%patch313 -p1 -b .mozbz1507475 %if %{official_branding} # Required by Mozilla Corporation @@ -693,6 +692,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Nov 21 2018 Martin Stransky - 60.3.0-5 +- Backported Wayland related code from Firefox 63 +- Added fix for mozbz#1507475 - crash when display changes + * Tue Nov 20 2018 Martin Stransky - 60.3.0-4 - Build with Wayland support - Enabled DBus remote for Wayland From 2831738e921dbfc42e92508eb2f93e7d5876ea38 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Thu, 22 Nov 2018 10:54:11 +0100 Subject: [PATCH 020/402] Enabled DBus remote --- thunderbird-dbus-remote.patch | 26 +++++++++++++++++++++++++- thunderbird-wayland.desktop | 2 +- thunderbird.spec | 7 +++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/thunderbird-dbus-remote.patch b/thunderbird-dbus-remote.patch index 856e64e..83a5da5 100644 --- a/thunderbird-dbus-remote.patch +++ b/thunderbird-dbus-remote.patch @@ -75,7 +75,6 @@ diff -up thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.cpp.old thunde return NS_OK; } -diff -up thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.h.old thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.h diff -up thunderbird-60.3.0/widget/xremoteclient/moz.build.old thunderbird-60.3.0/widget/xremoteclient/moz.build --- thunderbird-60.3.0/widget/xremoteclient/moz.build.old 2018-10-31 01:08:14.000000000 +0100 +++ thunderbird-60.3.0/widget/xremoteclient/moz.build 2018-11-14 13:37:32.244714628 +0100 @@ -186,3 +185,28 @@ diff -up thunderbird-60.3.0/widget/xremoteclient/XRemoteClient.cpp.old thunderbi // If there's a profile compare it with what we have if (data_return) { +diff -up thunderbird-60.3.0/toolkit/xre/nsAppRunner.cpp.old thunderbird-60.3.0/toolkit/xre/nsAppRunner.cpp +--- thunderbird-60.3.0/toolkit/xre/nsAppRunner.cpp.old 2018-11-22 10:24:36.980367239 +0100 ++++ thunderbird-60.3.0/toolkit/xre/nsAppRunner.cpp 2018-11-22 10:23:22.702553710 +0100 +@@ -1830,18 +1830,13 @@ StartRemoteClient(const char* aDesktopSt + { + nsAutoPtr client; + +- if (aIsX11Display) { +- client = new XRemoteClient(); +- } else { + #if defined(MOZ_ENABLE_DBUS) && defined(MOZ_WAYLAND) +- client = new DBusRemoteClient(); ++ client = new DBusRemoteClient(); + #else +- MOZ_ASSERT(false, "Missing remote implementation!"); +- return REMOTE_NOT_FOUND; ++ client = new XRemoteClient(); + #endif +- } + +- nsresult rv = client->Init(); ++ nsresult rv = client ? client->Init() : NS_ERROR_FAILURE; + if (NS_FAILED(rv)) + return REMOTE_NOT_FOUND; + diff --git a/thunderbird-wayland.desktop b/thunderbird-wayland.desktop index 23a7c24..e65deaf 100644 --- a/thunderbird-wayland.desktop +++ b/thunderbird-wayland.desktop @@ -3,7 +3,7 @@ Version=1.0 Name=Thunderbird on Wayland GenericName=Email Comment=Send and Receive Email -Exec=thunderbird %u +Exec=thunderbird-wayland %u TryExec=thunderbird-wayland Icon=thunderbird Terminal=false diff --git a/thunderbird.spec b/thunderbird.spec index 4fb592a..b479f96 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -84,7 +84,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.3.0 -Release: 5%{?dist} +Release: 6%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -271,7 +271,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. # TODO - needs fixes %patch311 -p1 -b .wayland -#%patch312 -p1 -b .thunderbird-dbus-remote +%patch312 -p1 -b .thunderbird-dbus-remote %patch313 -p1 -b .mozbz1507475 %if %{official_branding} @@ -692,6 +692,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Nov 22 2018 Martin Stransky - 60.3.0-6 +- Enabled DBus remote. + * Wed Nov 21 2018 Martin Stransky - 60.3.0-5 - Backported Wayland related code from Firefox 63 - Added fix for mozbz#1507475 - crash when display changes From e14a525a3d5867794baf12739656693c3ee59dbe Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 22 Nov 2018 14:24:37 +0100 Subject: [PATCH 021/402] Update to 60.3.1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 53a1369..c5d3c33 100644 --- a/.gitignore +++ b/.gitignore @@ -217,3 +217,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.3.0.source.tar.xz /thunderbird-langpacks-60.3.0-20181030.tar.xz /lightning-langpacks-60.3.0.tar.xz +/thunderbird-60.3.1.source.tar.xz +/thunderbird-langpacks-60.3.1-20181122.tar.xz +/lightning-langpacks-60.3.1.tar.xz diff --git a/sources b/sources index 62ce96c..39968f0 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.3.0.source.tar.xz) = 6cc390129dd2ce30c4685748bc5cdbf07c1326bf1ba4727d34b105f800ee3d0c7344a1bda3b8f6a666f635eb6d2fba7da5afb1222aac05a536d2dd77afb3a8d3 -SHA512 (thunderbird-langpacks-60.3.0-20181030.tar.xz) = 61e8a37ea8c17636f55b52d76bcdef412061dfa494a4d3e7dce6bbc7a699995f277912595f367c2146c231742147df6c7334a7a3d26e143a1cae24f02cd8bd41 -SHA512 (lightning-langpacks-60.3.0.tar.xz) = 5cf4fe7d75124210726536eeb39c774b831ef0c8edbca0afd1ffcc6ed622704535fb063718b1af88e77cbe52b20d5d45b8283b7131051363bb387cbe3dddfe0f +SHA512 (thunderbird-60.3.1.source.tar.xz) = d52a8acee19b0acaee3c23dd76aa966c7eb4b04ebefd0bc81305b6af6a90c25c6d60d7b64f5b94c2b53eeb548d5d0d903899a468f6c80726fe0079ec7c926a8c +SHA512 (thunderbird-langpacks-60.3.1-20181122.tar.xz) = f4c96c3b22532a3291c94b8081c3a8c1c5a69bd057ea55b362a8b4dc0f1eda2ae56e97d28b240b8ae7120fdc20fe3d62d343cc3bd4e3771c9f4ddc1ba67489d1 +SHA512 (lightning-langpacks-60.3.1.tar.xz) = f8ee97e8d03cc6b360b28bc82692718bd96a6d670d1876222fd64c06f485112dc6fc721bdedff3b49bac4a379047b461b0299ef226413193c9de08c1c1301780 diff --git a/thunderbird.spec b/thunderbird.spec index b479f96..c577b31 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -83,14 +83,14 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.3.0 -Release: 6%{?dist} +Version: 60.3.1 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20181030.tar.xz +Source1: thunderbird-langpacks-%{version}-20181122.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -692,6 +692,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Nov 22 2018 Jan Horak - 60.3.1-1 +- Update to 60.3.1 + * Thu Nov 22 2018 Martin Stransky - 60.3.0-6 - Enabled DBus remote. From 8a87d849da954d7a5afc25df691e0e0b47f6aaae Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 6 Dec 2018 11:57:36 +0100 Subject: [PATCH 022/402] Update to 60.3.3 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index c5d3c33..c5445d6 100644 --- a/.gitignore +++ b/.gitignore @@ -220,3 +220,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.3.1.source.tar.xz /thunderbird-langpacks-60.3.1-20181122.tar.xz /lightning-langpacks-60.3.1.tar.xz +/thunderbird-60.3.3.source.tar.xz +/thunderbird-langpacks-60.3.3-20181205.tar.xz +/lightning-langpacks-60.3.3.tar.xz diff --git a/sources b/sources index 39968f0..7f2eab1 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.3.1.source.tar.xz) = d52a8acee19b0acaee3c23dd76aa966c7eb4b04ebefd0bc81305b6af6a90c25c6d60d7b64f5b94c2b53eeb548d5d0d903899a468f6c80726fe0079ec7c926a8c -SHA512 (thunderbird-langpacks-60.3.1-20181122.tar.xz) = f4c96c3b22532a3291c94b8081c3a8c1c5a69bd057ea55b362a8b4dc0f1eda2ae56e97d28b240b8ae7120fdc20fe3d62d343cc3bd4e3771c9f4ddc1ba67489d1 -SHA512 (lightning-langpacks-60.3.1.tar.xz) = f8ee97e8d03cc6b360b28bc82692718bd96a6d670d1876222fd64c06f485112dc6fc721bdedff3b49bac4a379047b461b0299ef226413193c9de08c1c1301780 +SHA512 (thunderbird-60.3.3.source.tar.xz) = 30cffd9234d4b0820a4e3b966ebc3646780ebe455d06b6132d312169bd209d298c5e10d6721331645a9de6af646e96c4d75985aad0c09ece0e6c9d25f5555309 +SHA512 (thunderbird-langpacks-60.3.3-20181205.tar.xz) = eea80dd18e8bf725985b12de57bd11e1d9eed7e93c04b17566667f321ab77664244cfe8186176b8a3b9048981fcf572e684885a8013ebffc9b32107dbdd1188a +SHA512 (lightning-langpacks-60.3.3.tar.xz) = 7c144f273097a0a5195865baf9ad8f769f7031d2165a7190f837437cf935c8042df899f0183687445bf83f8105691eb87046fc67bb2440b50e374858dcf7a593 diff --git a/thunderbird.spec b/thunderbird.spec index c577b31..d95e392 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -83,14 +83,14 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.3.1 +Version: 60.3.3 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20181122.tar.xz +Source1: thunderbird-langpacks-%{version}-20181205.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -692,6 +692,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Dec 5 2018 Jan Horak - 60.3.3-1 +- Update to 60.3.3 + * Thu Nov 22 2018 Jan Horak - 60.3.1-1 - Update to 60.3.1 From 98d45999960a5b07c42343abfe2323219d5acf41 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 2 Jan 2019 18:50:19 +0100 Subject: [PATCH 023/402] Update to 60.4.0 --- .gitignore | 3 + mozbz-1500850-missing-dbus-header.patch | 12 ++ sources | 6 +- thunderbird-dbus-remote.patch | 212 ------------------------ thunderbird.spec | 11 +- 5 files changed, 25 insertions(+), 219 deletions(-) create mode 100644 mozbz-1500850-missing-dbus-header.patch delete mode 100644 thunderbird-dbus-remote.patch diff --git a/.gitignore b/.gitignore index c5445d6..dff1d79 100644 --- a/.gitignore +++ b/.gitignore @@ -223,3 +223,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.3.3.source.tar.xz /thunderbird-langpacks-60.3.3-20181205.tar.xz /lightning-langpacks-60.3.3.tar.xz +/thunderbird-60.4.0.source.tar.xz +/thunderbird-langpacks-60.4.0-20190102.tar.xz +/lightning-langpacks-60.4.0.tar.xz diff --git a/mozbz-1500850-missing-dbus-header.patch b/mozbz-1500850-missing-dbus-header.patch new file mode 100644 index 0000000..9940e06 --- /dev/null +++ b/mozbz-1500850-missing-dbus-header.patch @@ -0,0 +1,12 @@ +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/sources b/sources index 7f2eab1..87a910c 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.3.3.source.tar.xz) = 30cffd9234d4b0820a4e3b966ebc3646780ebe455d06b6132d312169bd209d298c5e10d6721331645a9de6af646e96c4d75985aad0c09ece0e6c9d25f5555309 -SHA512 (thunderbird-langpacks-60.3.3-20181205.tar.xz) = eea80dd18e8bf725985b12de57bd11e1d9eed7e93c04b17566667f321ab77664244cfe8186176b8a3b9048981fcf572e684885a8013ebffc9b32107dbdd1188a -SHA512 (lightning-langpacks-60.3.3.tar.xz) = 7c144f273097a0a5195865baf9ad8f769f7031d2165a7190f837437cf935c8042df899f0183687445bf83f8105691eb87046fc67bb2440b50e374858dcf7a593 +SHA512 (thunderbird-60.4.0.source.tar.xz) = 084becec870ad1449196110ecd2d2cc397c32d9d5a682f3cf45a170b7bdf5c2197299a72034965e838af62534df870de5a46d49fd0d05a9c4c7fdf5e408e471d +SHA512 (thunderbird-langpacks-60.4.0-20190102.tar.xz) = 321e78494ae503578e6828d54e3c6d4da6944679d58f6b65c9270d6721fb4714c81e828cabb566e565c884cc20ec4dc098110ca86b872a99160abd47be4453a8 +SHA512 (lightning-langpacks-60.4.0.tar.xz) = fb3f7928ffa45263b76d584a7c15abb56fdf6d8f5276eb8c8b7ec758e481a32f51d3406503ff987f1c3da31009d0e5f4d2d679ca5d51d7bc2c3608c0f73f3826 diff --git a/thunderbird-dbus-remote.patch b/thunderbird-dbus-remote.patch deleted file mode 100644 index 83a5da5..0000000 --- a/thunderbird-dbus-remote.patch +++ /dev/null @@ -1,212 +0,0 @@ -diff -up thunderbird-60.3.0/toolkit/components/remote/nsDBusRemoteService.cpp.old thunderbird-60.3.0/toolkit/components/remote/nsDBusRemoteService.cpp ---- thunderbird-60.3.0/toolkit/components/remote/nsDBusRemoteService.cpp.old 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/toolkit/components/remote/nsDBusRemoteService.cpp 2018-11-14 13:37:32.223714689 +0100 -@@ -174,6 +174,7 @@ nsDBusRemoteService::Startup(const char* - return NS_ERROR_FAILURE; - } - dbus_connection_set_exit_on_disconnect(mConnection, false); -+ dbus_connection_setup_with_g_main(mConnection, nullptr); - - mAppName = aAppName; - ToLowerCase(mAppName); -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-20 10:55:35.584756422 +0100 -+++ thunderbird-60.3.0/toolkit/components/remote/nsRemoteService.cpp 2018-11-14 13:37:32.244714628 +0100 -@@ -34,20 +34,18 @@ NS_IMPL_ISUPPORTS(nsRemoteService, - NS_IMETHODIMP - nsRemoteService::Startup(const char* aAppName, const char* aProfileName) - { --#if 0 -+#if defined(MOZ_ENABLE_DBUS) && defined(MOZ_WAYLAND) - nsresult rv; - mDBusRemoteService = new nsDBusRemoteService(); - rv = mDBusRemoteService->Startup(aAppName, aProfileName); - if (NS_FAILED(rv)) { - mDBusRemoteService = nullptr; - } -+#elif !defined(MOZ_WAYLAND) -+ mGtkRemoteService = new nsGTKRemoteService(); -+ mGtkRemoteService->Startup(aAppName, aProfileName); - #endif - -- if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) { -- mGtkRemoteService = new nsGTKRemoteService(); -- mGtkRemoteService->Startup(aAppName, aProfileName); -- } -- - if (!mDBusRemoteService && !mGtkRemoteService) - return NS_ERROR_FAILURE; - -@@ -73,7 +71,7 @@ nsRemoteService::RegisterWindow(mozIDOMW - NS_IMETHODIMP - nsRemoteService::Shutdown() - { --#if defined(MOZ_ENABLE_DBUS) -+#if defined(MOZ_ENABLE_DBUS) && defined(MOZ_WAYLAND) - if (mDBusRemoteService) { - mDBusRemoteService->Shutdown(); - mDBusRemoteService = nullptr; -diff -up thunderbird-60.3.0/toolkit/components/remote/nsXRemoteService.cpp.old thunderbird-60.3.0/toolkit/components/remote/nsXRemoteService.cpp ---- thunderbird-60.3.0/toolkit/components/remote/nsXRemoteService.cpp.old 2018-10-30 12:45:34.000000000 +0100 -+++ thunderbird-60.3.0/toolkit/components/remote/nsXRemoteService.cpp 2018-10-31 01:08:14.000000000 +0100 -@@ -192,5 +192,5 @@ nsXRemoteService::EnsureAtoms(void) - sMozUserAtom = XAtoms[i++]; - sMozProfileAtom = XAtoms[i++]; - sMozProgramAtom = XAtoms[i++]; -- sMozCommandLineAtom = XAtoms[i++]; -+ sMozCommandLineAtom = XAtoms[i]; - } -diff -up thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.cpp.old thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.cpp ---- thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.cpp.old 2018-10-30 12:45:35.000000000 +0100 -+++ thunderbird-60.3.0/widget/xremoteclient/DBusRemoteClient.cpp 2018-11-14 13:37:32.224714686 +0100 -@@ -12,6 +12,7 @@ - #include "mozilla/Base64.h" - #include "nsPrintfCString.h" - -+#include - #include - - using mozilla::LogLevel; -@@ -43,6 +44,7 @@ DBusRemoteClient::Init() - return NS_ERROR_FAILURE; - - dbus_connection_set_exit_on_disconnect(mConnection, false); -+ dbus_connection_setup_with_g_main(mConnection, nullptr); - - return NS_OK; - } -diff -up thunderbird-60.3.0/widget/xremoteclient/moz.build.old thunderbird-60.3.0/widget/xremoteclient/moz.build ---- thunderbird-60.3.0/widget/xremoteclient/moz.build.old 2018-10-31 01:08:14.000000000 +0100 -+++ thunderbird-60.3.0/widget/xremoteclient/moz.build 2018-11-14 13:37:32.244714628 +0100 -@@ -11,7 +11,6 @@ FINAL_LIBRARY = 'xul' - - SOURCES += [ - 'RemoteUtils.cpp', -- 'XRemoteClient.cpp', - ] - - if CONFIG['MOZ_ENABLE_DBUS'] and CONFIG['MOZ_WAYLAND']: -@@ -20,3 +19,7 @@ if CONFIG['MOZ_ENABLE_DBUS'] and CONFIG[ - ] - CXXFLAGS += CONFIG['TK_CFLAGS'] - CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] -+else: -+ SOURCES += [ -+ 'XRemoteClient.cpp', -+ ] -diff -up thunderbird-60.3.0/widget/xremoteclient/XRemoteClient.cpp.old thunderbird-60.3.0/widget/xremoteclient/XRemoteClient.cpp ---- thunderbird-60.3.0/widget/xremoteclient/XRemoteClient.cpp.old 2018-10-30 12:45:37.000000000 +0100 -+++ thunderbird-60.3.0/widget/xremoteclient/XRemoteClient.cpp 2018-10-31 01:08:15.000000000 +0100 -@@ -9,6 +9,7 @@ - #include "mozilla/ArrayUtils.h" - #include "mozilla/IntegerPrintfMacros.h" - #include "mozilla/Sprintf.h" -+#include "mozilla/Unused.h" - #include "XRemoteClient.h" - #include "RemoteUtils.h" - #include "plstr.h" -@@ -41,7 +42,7 @@ - #else - #define TO_LITTLE_ENDIAN32(x) (x) - #endif -- -+ - #ifndef MAX_PATH - #ifdef PATH_MAX - #define MAX_PATH PATH_MAX -@@ -51,6 +52,7 @@ - #endif - - using mozilla::LogLevel; -+using mozilla::Unused; - - static mozilla::LazyLogModule sRemoteLm("XRemoteClient"); - -@@ -118,7 +120,7 @@ XRemoteClient::Init() - mMozUserAtom = XAtoms[i++]; - mMozProfileAtom = XAtoms[i++]; - mMozProgramAtom = XAtoms[i++]; -- mMozCommandLineAtom = XAtoms[i++]; -+ mMozCommandLineAtom = XAtoms[i]; - - mInitialized = true; - -@@ -472,12 +474,12 @@ XRemoteClient::FindBestWindow(const char - // pass in a program name and this window doesn't support that - // protocol, we don't include it in our list. - if (aProgram && strcmp(aProgram, "any")) { -- status = XGetWindowProperty(mDisplay, w, mMozProgramAtom, -- 0, (65536 / sizeof(long)), -- False, XA_STRING, -- &type, &format, &nitems, &bytesafter, -- &data_return); -- -+ Unused << XGetWindowProperty(mDisplay, w, mMozProgramAtom, -+ 0, (65536 / sizeof(long)), -+ False, XA_STRING, -+ &type, &format, &nitems, &bytesafter, -+ &data_return); -+ - // If the return name is not the same as what someone passed in, - // we don't want this window. - if (data_return) { -@@ -507,11 +509,11 @@ XRemoteClient::FindBestWindow(const char - } - - if (username) { -- status = XGetWindowProperty(mDisplay, w, mMozUserAtom, -- 0, (65536 / sizeof(long)), -- False, XA_STRING, -- &type, &format, &nitems, &bytesafter, -- &data_return); -+ Unused << XGetWindowProperty(mDisplay, w, mMozUserAtom, -+ 0, (65536 / sizeof(long)), -+ False, XA_STRING, -+ &type, &format, &nitems, &bytesafter, -+ &data_return); - - // if there's a username compare it with what we have - if (data_return) { -@@ -529,11 +531,11 @@ XRemoteClient::FindBestWindow(const char - // there is, then we need to make sure it matches what someone - // passed in. - if (aProfile) { -- status = XGetWindowProperty(mDisplay, w, mMozProfileAtom, -- 0, (65536 / sizeof(long)), -- False, XA_STRING, -- &type, &format, &nitems, &bytesafter, -- &data_return); -+ Unused << XGetWindowProperty(mDisplay, w, mMozProfileAtom, -+ 0, (65536 / sizeof(long)), -+ False, XA_STRING, -+ &type, &format, &nitems, &bytesafter, -+ &data_return); - - // If there's a profile compare it with what we have - if (data_return) { - -diff -up thunderbird-60.3.0/toolkit/xre/nsAppRunner.cpp.old thunderbird-60.3.0/toolkit/xre/nsAppRunner.cpp ---- thunderbird-60.3.0/toolkit/xre/nsAppRunner.cpp.old 2018-11-22 10:24:36.980367239 +0100 -+++ thunderbird-60.3.0/toolkit/xre/nsAppRunner.cpp 2018-11-22 10:23:22.702553710 +0100 -@@ -1830,18 +1830,13 @@ StartRemoteClient(const char* aDesktopSt - { - nsAutoPtr client; - -- if (aIsX11Display) { -- client = new XRemoteClient(); -- } else { - #if defined(MOZ_ENABLE_DBUS) && defined(MOZ_WAYLAND) -- client = new DBusRemoteClient(); -+ client = new DBusRemoteClient(); - #else -- MOZ_ASSERT(false, "Missing remote implementation!"); -- return REMOTE_NOT_FOUND; -+ client = new XRemoteClient(); - #endif -- } - -- nsresult rv = client->Init(); -+ nsresult rv = client ? client->Init() : NS_ERROR_FAILURE; - if (NS_FAILED(rv)) - return REMOTE_NOT_FOUND; - diff --git a/thunderbird.spec b/thunderbird.spec index d95e392..7df5e4e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -83,14 +83,14 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.3.3 +Version: 60.4.0 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20181205.tar.xz +Source1: thunderbird-langpacks-%{version}-20190102.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -123,11 +123,11 @@ 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 -Patch312: thunderbird-dbus-remote.patch Patch313: firefox-wayland-crash-mozbz1507475.patch # Upstream patches @@ -245,6 +245,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %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 @@ -271,7 +272,6 @@ debug %{name}, you want to install %{name}-debuginfo instead. # TODO - needs fixes %patch311 -p1 -b .wayland -%patch312 -p1 -b .thunderbird-dbus-remote %patch313 -p1 -b .mozbz1507475 %if %{official_branding} @@ -692,6 +692,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Jan 2 2019 Jan Horak - 60.4.0-1 +- Update to 60.4.0 + * Wed Dec 5 2018 Jan Horak - 60.3.3-1 - Update to 60.3.3 From 008304da84b1b6866de35e6f1e79a45a50b32196 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 30 Jan 2019 11:10:12 +0100 Subject: [PATCH 024/402] Update to 60.5.0 --- .gitignore | 3 +++ build-jit-atomic-always-lucky.patch | 34 ++++++------------------- sources | 6 ++--- thunderbird.spec | 39 +++++++++++++---------------- 4 files changed, 32 insertions(+), 50 deletions(-) diff --git a/.gitignore b/.gitignore index dff1d79..546f6fc 100644 --- a/.gitignore +++ b/.gitignore @@ -226,3 +226,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.4.0.source.tar.xz /thunderbird-langpacks-60.4.0-20190102.tar.xz /lightning-langpacks-60.4.0.tar.xz +/thunderbird-60.5.0.source.tar.xz +/lightning-langpacks-60.5.0.tar.xz +/thunderbird-langpacks-60.5.0-20190129.tar.xz diff --git a/build-jit-atomic-always-lucky.patch b/build-jit-atomic-always-lucky.patch index 31bc5ec..ab99524 100644 --- a/build-jit-atomic-always-lucky.patch +++ b/build-jit-atomic-always-lucky.patch @@ -1,30 +1,12 @@ -diff -up firefox-57.0b5/js/src/jit/AtomicOperations.h.jit-atomic-lucky firefox-57.0b5/js/src/jit/AtomicOperations.h ---- firefox-57.0b5/js/src/jit/AtomicOperations.h.jit-atomic-lucky 2017-10-06 12:34:02.338973607 +0200 -+++ firefox-57.0b5/js/src/jit/AtomicOperations.h 2017-10-06 12:38:24.632622215 +0200 -@@ -415,7 +415,7 @@ AtomicOperations::isLockfreeJS(int32_t s +diff -up firefox-60.5.0/js/src/jit/AtomicOperations.h.jit-atomic-lucky firefox-60.5.0/js/src/jit/AtomicOperations.h +--- firefox-60.5.0/js/src/jit/AtomicOperations.h.jit-atomic-lucky 2019-01-22 10:20:27.993697161 +0100 ++++ firefox-60.5.0/js/src/jit/AtomicOperations.h 2019-01-22 10:23:15.337873762 +0100 +@@ -394,7 +394,7 @@ inline bool AtomicOperations::isLockfree #elif defined(__s390__) || defined(__s390x__) - # include "jit/none/AtomicOperations-feeling-lucky.h" + #include "jit/none/AtomicOperations-feeling-lucky.h" #else --# error "No AtomicOperations support provided for this platform" -+# include "jit/none/AtomicOperations-feeling-lucky.h" +-#error "No AtomicOperations support provided for this platform" ++#include "jit/none/AtomicOperations-feeling-lucky.h" #endif - #endif // jit_AtomicOperations_h -diff -up firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h.jit-atomic-lucky firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h ---- firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h.jit-atomic-lucky 2017-09-19 06:18:28.000000000 +0200 -+++ firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h 2017-10-06 12:34:02.338973607 +0200 -@@ -79,6 +79,14 @@ - # define GNUC_COMPATIBLE - #endif - -+#ifdef __s390__ -+# define GNUC_COMPATIBLE -+#endif -+ -+#ifdef __s390x__ -+# define GNUC_COMPATIBLE -+#endif -+ - // The default implementation tactic for gcc/clang is to use the newer - // __atomic intrinsics added for use in C++11 . Where that - // isn't available, we use GCC's older __sync functions instead. + #endif // jit_AtomicOperations_h diff --git a/sources b/sources index 87a910c..c6da8cd 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.4.0.source.tar.xz) = 084becec870ad1449196110ecd2d2cc397c32d9d5a682f3cf45a170b7bdf5c2197299a72034965e838af62534df870de5a46d49fd0d05a9c4c7fdf5e408e471d -SHA512 (thunderbird-langpacks-60.4.0-20190102.tar.xz) = 321e78494ae503578e6828d54e3c6d4da6944679d58f6b65c9270d6721fb4714c81e828cabb566e565c884cc20ec4dc098110ca86b872a99160abd47be4453a8 -SHA512 (lightning-langpacks-60.4.0.tar.xz) = fb3f7928ffa45263b76d584a7c15abb56fdf6d8f5276eb8c8b7ec758e481a32f51d3406503ff987f1c3da31009d0e5f4d2d679ca5d51d7bc2c3608c0f73f3826 +SHA512 (thunderbird-60.5.0.source.tar.xz) = b18bad3d0ec33a813ec8f2f7f539a9ba08bd05432a16b1838671a101a85d66b2acdd2573d9fc3117cecaa9aa1429c178d4ddbae987a3ce6e4e4211981eecb8d2 +SHA512 (lightning-langpacks-60.5.0.tar.xz) = 7aa2d3ac455ca52a5400841654ae896ac34f987d781ba0d713cb2a860c3865ef595e341c116d0e45521b1c13092fe53cca2f070a1f3e824d0a37b9dd574d5be1 +SHA512 (thunderbird-langpacks-60.5.0-20190129.tar.xz) = 677661a1cb6b25b6b819e98a98ca7ab2bbdb3c631aeb44c160c7aff4bb57386338af27a13a3755778720b038bf1c2edda41aa0eb73a74f39d298267c78fb0edf diff --git a/thunderbird.spec b/thunderbird.spec index 7df5e4e..abe174e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -58,8 +58,6 @@ %global libvpx_version 1.4.0 %endif -%define tb_version 45.6.0 - %define thunderbird_app_id \{3550f703-e582-4d05-9a08-453d09bdfdc6\} %global langpackdir %{mozappdir}/distribution/extensions @@ -83,14 +81,14 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.4.0 +Version: 60.5.0 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190102.tar.xz +Source1: thunderbird-langpacks-%{version}-20190129.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -111,11 +109,11 @@ 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 +#Patch417: bug1375074-save-restore-x28.patch # Build patches Patch103: rhbz-1219542-s390-build.patch -Patch104: firefox-gcc-6.0.patch +#Patch104: firefox-gcc-6.0.patch # PPC fix Patch304: mozilla-1245783.patch @@ -123,10 +121,10 @@ 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 +#Patch314: mozbz-1500850-missing-dbus-header.patch # Fedora specific patches -Patch310: disable-dbus-remote.patch +#Patch310: disable-dbus-remote.patch Patch311: firefox-wayland.patch Patch313: firefox-wayland-crash-mozbz1507475.patch @@ -228,10 +226,6 @@ debug %{name}, you want to install %{name}-debuginfo instead. %defattr(-,root,root) %endif -%global tb_version %{version} - - - %prep %setup -q @@ -241,17 +235,17 @@ debug %{name}, you want to install %{name}-debuginfo instead. %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build %endif -%patch104 -p1 -b .gcc6 +#%patch104 -p1 -b .gcc6 %patch304 -p1 -b .1245783 %patch309 -p1 -b .1460871-ldap-query -%patch314 -p1 -b .1500850-missing-dbus-header +#%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 +#%patch310 -p1 -b .disable-dbus-remote %patch37 -p1 -b .jit-atomic-lucky %patch40 -p1 -b .aarch64-skia @@ -262,7 +256,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %ifarch %{arm} %patch415 -p1 -b .mozilla-1238661 %endif -%patch417 -p1 -b .bug1375074-save-restore-x28 +#%patch417 -p1 -b .bug1375074-save-restore-x28 %patch306 -p1 -b .1353817 %if 0%{?disable_elfhack} @@ -270,9 +264,9 @@ debug %{name}, you want to install %{name}-debuginfo instead. %endif #cd .. -# TODO - needs fixes -%patch311 -p1 -b .wayland -%patch313 -p1 -b .mozbz1507475 +#TODO - needs fixes +#%patch311 -p1 -b .wayland +#%patch313 -p1 -b .mozbz1507475 %if %{official_branding} # Required by Mozilla Corporation @@ -507,7 +501,7 @@ rm -f $RPM_BUILD_ROOT/%{_bindir}/thunderbird %{__chmod} 755 %{buildroot}%{_bindir}/thunderbird-wayland # set up our default preferences -%{__cat} %{SOURCE12} | %{__sed} -e 's,THUNDERBIRD_RPM_VR,%{tb_version}-%{release},g' > \ +%{__cat} %{SOURCE12} | %{__sed} -e 's,THUNDERBIRD_RPM_VR,%{version}-%{release},g' > \ $RPM_BUILD_ROOT/rh-default-prefs %{__install} -D $RPM_BUILD_ROOT/rh-default-prefs $RPM_BUILD_ROOT/%{mozappdir}/greprefs/all-redhat.js %{__install} -D $RPM_BUILD_ROOT/rh-default-prefs $RPM_BUILD_ROOT/%{mozappdir}/defaults/pref/all-redhat.js @@ -553,7 +547,7 @@ cd - %endif # build_langpacks # Get rid of devel package and its debugsymbols -%{__rm} -rf $RPM_BUILD_ROOT%{_libdir}/%{name}-devel-%{tb_version} +%{__rm} -rf $RPM_BUILD_ROOT%{_libdir}/%{name}-devel-%{version} # Copy over the LICENSE install -c -m 644 LICENSE $RPM_BUILD_ROOT%{mozappdir} @@ -692,6 +686,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Jan 30 2019 Martin Stransky - 60.5.0-1 +- Update to 60.5.0 + * Wed Jan 2 2019 Jan Horak - 60.4.0-1 - Update to 60.4.0 From d22e57232e4f3d76621b0582ff19cb7853ea27cf Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 30 Jan 2019 11:41:01 +0100 Subject: [PATCH 025/402] Build fixes for arm/aarch64 --- ...fix-mozillaSignalTrampoline-to-work-.patch | 25 +++++++------------ rhbz-1354671.patch | 14 +++++------ 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch b/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch index 70e45ff..0663ffe 100644 --- a/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch +++ b/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch @@ -1,19 +1,12 @@ -diff -up firefox-60.0/mfbt/LinuxSignal.h.mozilla-1238661 firefox-60.0/mfbt/LinuxSignal.h ---- firefox-60.0/mfbt/LinuxSignal.h.mozilla-1238661 2018-04-27 08:55:38.848241768 +0200 -+++ firefox-60.0/mfbt/LinuxSignal.h 2018-04-27 09:06:47.946769859 +0200 -@@ -25,10 +25,13 @@ SignalTrampoline(int aSignal, siginfo_t* - "nop; nop; nop; nop" - : : : "memory"); +diff -up thunderbird-60.5.0/mfbt/LinuxSignal.h.mozilla-1238661 thunderbird-60.5.0/mfbt/LinuxSignal.h +--- thunderbird-60.5.0/mfbt/LinuxSignal.h.mozilla-1238661 2019-01-30 11:33:21.447003175 +0100 ++++ thunderbird-60.5.0/mfbt/LinuxSignal.h 2019-01-30 11:35:13.848537051 +0100 +@@ -22,7 +22,7 @@ __attribute__((naked)) void SignalTrampo + void* aContext) { + asm volatile("nop; nop; nop; nop" : : : "memory"); -+ // Because the assembler may generate additional insturctions below, we -+ // need to ensure NOPs are inserted first by separating them out above. -+ - asm volatile ( -- "b %0" -+ "bx %0" - : -- : "X"(H) -+ : "r"(H), "l"(aSignal), "l"(aInfo), "l"(aContext) - : "memory"); +- asm volatile("b %0" : : "X"(H) : "memory"); ++ asm volatile("bx %0" : : "r"(H), "l"(aSignal), "l"(aInfo), "l"(aContext) : "memory"); } + #define MOZ_SIGNAL_TRAMPOLINE(h) (mozilla::SignalTrampoline) diff --git a/rhbz-1354671.patch b/rhbz-1354671.patch index 6ee89b7..7660f14 100644 --- a/rhbz-1354671.patch +++ b/rhbz-1354671.patch @@ -1,12 +1,12 @@ -diff -up firefox-53.0/layout/base/nsIPresShell.h.1354671 firefox-53.0/layout/base/nsIPresShell.h ---- firefox-53.0/layout/base/nsIPresShell.h.1354671 2017-04-27 13:07:43.808653320 +0200 -+++ firefox-53.0/layout/base/nsIPresShell.h 2017-04-27 13:09:40.404427641 +0200 -@@ -212,7 +212,7 @@ public: +diff -up firefox-60.5.0/layout/base/nsIPresShell.h.1354671 firefox-60.5.0/layout/base/nsIPresShell.h +--- firefox-60.5.0/layout/base/nsIPresShell.h.1354671 2019-01-22 16:08:40.796539950 +0100 ++++ firefox-60.5.0/layout/base/nsIPresShell.h 2019-01-22 16:10:25.106069228 +0100 +@@ -204,7 +204,7 @@ class nsIPresShell : public nsStubDocume * to the same aSize value. AllocateFrame is infallible and will abort * on out-of-memory. */ -- void* AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) -+ void* __attribute__((optimize("no-lifetime-dse"))) AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) - { +- void* AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) { ++ void* __attribute__((optimize("no-lifetime-dse"))) AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) { void* result = mFrameArena.AllocateByFrameID(aID, aSize); RecordAlloc(result); + return result; From 3b76d3a3ed48bfc0eb955ceab4f79b65d06e218e Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 30 Jan 2019 13:11:23 +0100 Subject: [PATCH 026/402] spec build fix --- thunderbird.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/thunderbird.spec b/thunderbird.spec index abe174e..7717b22 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -659,6 +659,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{mozappdir}/platform.ini %{mozappdir}/application.ini %{mozappdir}/blocklist.xml +%{mozappdir}/features/*.xpi %exclude %{mozappdir}/removed-files %{_datadir}/icons/hicolor/16x16/apps/thunderbird.png %{_datadir}/icons/hicolor/22x22/apps/thunderbird.png From e1232d8eb2c7f3e2e4dd70c5f6218fdcb2d73a3c Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sun, 3 Feb 2019 09:48:57 +0000 Subject: [PATCH 027/402] - Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 7717b22..a1f8676 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -82,7 +82,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.5.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -687,6 +687,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Sun Feb 03 2019 Fedora Release Engineering - 60.5.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + * Wed Jan 30 2019 Martin Stransky - 60.5.0-1 - Update to 60.5.0 From 7b002e873e9e45f7aef355670f346621a7bfa9a4 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 5 Feb 2019 15:49:40 +0100 Subject: [PATCH 028/402] 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 From 308bbb8c32d177dc50a60c56d1a7c7b9631077b4 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 5 Feb 2019 15:51:37 +0100 Subject: [PATCH 029/402] Changelog update --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 4826178..fa6a8d9 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -82,7 +82,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.5.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -676,6 +676,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Jan 5 2019 Martin Stransky - 60.5.0-2 +- Updated Wayland patches + * Wed Jan 30 2019 Martin Stransky - 60.5.0-1 - Update to 60.5.0 From d32e6e9da7b5c53c78b228766b28d7c8d23a862a Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 5 Feb 2019 15:55:56 +0100 Subject: [PATCH 030/402] Changelog fix --- thunderbird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 924edba..d8f5fed 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -676,7 +676,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog -* Tue Jan 5 2019 Martin Stransky - 60.5.0-3 +* Tue Feb 05 2019 Martin Stransky - 60.5.0-3 - Updated Wayland patches * Sun Feb 03 2019 Fedora Release Engineering - 60.5.0-2 From d96601547dc1b054f405b8e530a3d7cf58be410f Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 5 Feb 2019 21:34:04 +0100 Subject: [PATCH 031/402] Use MOZ_ENABLE_WAYLAND for Wayland launcher --- mozilla-1522780.patch | 42 +++++++++++++++++++++++++++++++++++++++ thunderbird-wayland.sh.in | 7 ++++++- thunderbird.sh.in | 7 ------- thunderbird.spec | 7 ++++++- 4 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 mozilla-1522780.patch diff --git a/mozilla-1522780.patch b/mozilla-1522780.patch new file mode 100644 index 0000000..701f43b --- /dev/null +++ b/mozilla-1522780.patch @@ -0,0 +1,42 @@ +diff -up thunderbird-60.5.0/toolkit/xre/nsAppRunner.cpp.1522780 thunderbird-60.5.0/toolkit/xre/nsAppRunner.cpp +--- thunderbird-60.5.0/toolkit/xre/nsAppRunner.cpp.1522780 2019-02-05 20:57:28.384820067 +0100 ++++ thunderbird-60.5.0/toolkit/xre/nsAppRunner.cpp 2019-02-05 21:05:27.623511428 +0100 +@@ -3872,10 +3872,26 @@ int XREMain::XRE_mainStartup(bool* aExit + saveDisplayArg = true; + } + +- // On Wayland disabled builds read X11 DISPLAY env exclusively +- // and don't care about different displays. +-#if !defined(MOZ_WAYLAND) +- if (!display_name) { ++ bool disableWayland = true; ++#if defined(MOZ_WAYLAND) ++ // Make X11 backend the default one. ++ // Enable Wayland backend only when GDK_BACKEND is set and ++ // Gtk+ >= 3.22 where we can expect recent enough ++ // compositor & libwayland interface. ++ disableWayland = (PR_GetEnv("GDK_BACKEND") == nullptr) || ++ (gtk_check_version(3, 22, 0) != nullptr); ++ // Enable Wayland on Gtk+ >= 3.22 where we can expect recent enough ++ disableWayland = (gtk_check_version(3, 22, 0) != nullptr); ++ if (!disableWayland) { ++ // Make X11 backend the default one unless MOZ_ENABLE_WAYLAND or ++ // GDK_BACKEND are specified. ++ disableWayland = (PR_GetEnv("GDK_BACKEND") == nullptr) && ++ (PR_GetEnv("MOZ_ENABLE_WAYLAND") == nullptr); ++ } ++#endif ++ // On Wayland disabled builds read X11 DISPLAY env exclusively ++ // and don't care about different displays. ++ if (disableWayland && !display_name) { + display_name = PR_GetEnv("DISPLAY"); + if (!display_name) { + PR_fprintf(PR_STDERR, +@@ -3883,7 +3899,6 @@ int XREMain::XRE_mainStartup(bool* aExit + return 1; + } + } +-#endif + + if (display_name) { + mGdkDisplay = gdk_display_open(display_name); diff --git a/thunderbird-wayland.sh.in b/thunderbird-wayland.sh.in index 0bbbd9c..6eb8f7f 100644 --- a/thunderbird-wayland.sh.in +++ b/thunderbird-wayland.sh.in @@ -3,5 +3,10 @@ # Run Thunderbird under Wayland # -export GDK_BACKEND=wayland +## +## Enable Wayland backend? +## +if [ "$XDG_CURRENT_DESKTOP" == "GNOME" ]; then + export MOZ_ENABLE_WAYLAND=1 +fi exec /usr/bin/thunderbird "$@" diff --git a/thunderbird.sh.in b/thunderbird.sh.in index c178d2f..b0ff04d 100644 --- a/thunderbird.sh.in +++ b/thunderbird.sh.in @@ -36,13 +36,6 @@ MOZ_LANGPACKS_DIR="$MOZ_DIST_BIN/langpacks" MOZ_EXTENSIONS_PROFILE_DIR="$HOME/.mozilla/extensions/{3550f703-e582-4d05-9a08-453d09bdfdc6}" MOZ_LAUNCHER="$MOZ_DIST_BIN/thunderbird" -## -## Enable X11 backend by default? -## -if ! [ "$GDK_BACKEND" ]; then - export GDK_BACKEND=x11 -fi - ## ## Set MOZ_ENABLE_PANGO is no longer used because Pango is enabled by default ## you may use MOZ_DISABLE_PANGO=1 to force disabling of pango diff --git a/thunderbird.spec b/thunderbird.spec index d8f5fed..457e607 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -82,7 +82,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.5.0 -Release: 3%{?dist} +Release: 4%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -122,6 +122,7 @@ Patch309: mozilla-1460871-ldap-query.patch # Fedora specific patches Patch311: firefox-wayland.patch +Patch312: mozilla-1522780.patch # Upstream patches @@ -256,6 +257,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. #cd .. %patch311 -p1 -b .wayland +%patch312 -p1 -b .1522780 %if %{official_branding} # Required by Mozilla Corporation @@ -676,6 +678,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Feb 05 2019 Martin Stransky - 60.5.0-4 +- Use MOZ_ENABLE_WAYLAND for Wayland launcher. + * Tue Feb 05 2019 Martin Stransky - 60.5.0-3 - Updated Wayland patches From b863ac84d97ed632d8de4db19c796727dd784bfe Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 18 Feb 2019 13:42:06 +0100 Subject: [PATCH 032/402] Update to 60.5.1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 546f6fc..b887915 100644 --- a/.gitignore +++ b/.gitignore @@ -229,3 +229,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.5.0.source.tar.xz /lightning-langpacks-60.5.0.tar.xz /thunderbird-langpacks-60.5.0-20190129.tar.xz +/thunderbird-60.5.1.source.tar.xz +/thunderbird-langpacks-60.5.1-20190218.tar.xz +/lightning-langpacks-60.5.1.tar.xz diff --git a/sources b/sources index c6da8cd..3a37538 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.5.0.source.tar.xz) = b18bad3d0ec33a813ec8f2f7f539a9ba08bd05432a16b1838671a101a85d66b2acdd2573d9fc3117cecaa9aa1429c178d4ddbae987a3ce6e4e4211981eecb8d2 -SHA512 (lightning-langpacks-60.5.0.tar.xz) = 7aa2d3ac455ca52a5400841654ae896ac34f987d781ba0d713cb2a860c3865ef595e341c116d0e45521b1c13092fe53cca2f070a1f3e824d0a37b9dd574d5be1 -SHA512 (thunderbird-langpacks-60.5.0-20190129.tar.xz) = 677661a1cb6b25b6b819e98a98ca7ab2bbdb3c631aeb44c160c7aff4bb57386338af27a13a3755778720b038bf1c2edda41aa0eb73a74f39d298267c78fb0edf +SHA512 (thunderbird-60.5.1.source.tar.xz) = dafb7c81568b96285aa367fdac3db65aa0972a8224385714b14b67abdd5b17df963aec63608538a566f20c655cf0eb6784ba2b304151b2cc9b9dc3fdd9a48c7c +SHA512 (thunderbird-langpacks-60.5.1-20190218.tar.xz) = 68db7b6134a5eee8a8bc08b4a3c35823664072a65913ce138c1b0e969967f890655592f01ccfe4295a9a6ec83fe2f4e56bac70690867f638dfd90528af8b05b5 +SHA512 (lightning-langpacks-60.5.1.tar.xz) = 0e769a9e611b552584181f6403a1cb99209d2f5e7326c5e698e28b52f4580abd6e6272333cc7e9fbca23079f15760b77ec1bb9118da36857ebd2d12865804dd3 diff --git a/thunderbird.spec b/thunderbird.spec index 457e607..d68c4f7 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -81,8 +81,8 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.5.0 -Release: 4%{?dist} +Version: 60.5.1 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -678,6 +678,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Mon Feb 18 2019 Martin Stransky - 60.5.1-1 +- Update to 60.5.1 + * Tue Feb 05 2019 Martin Stransky - 60.5.0-4 - Use MOZ_ENABLE_WAYLAND for Wayland launcher. From 1bb9684a5f7848b77df1a009ae12bfdae0a84f5e Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 18 Feb 2019 14:03:47 +0100 Subject: [PATCH 033/402] Updated langpack date --- thunderbird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index d68c4f7..e4edf3f 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -88,7 +88,7 @@ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190129.tar.xz +Source1: thunderbird-langpacks-%{version}-20190218.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif From 832da562018fa8ee6a94de43e20b335679fdfea8 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Thu, 21 Feb 2019 13:45:05 +0100 Subject: [PATCH 034/402] Avoid hardcoding /usr in launcher scripts This fixes the launcher scripts to work when thunderbird is built with a prefix that is not /usr, such as is the case with flatpak builds when it's built with prefix=/app. --- thunderbird-wayland.sh.in | 2 +- thunderbird.sh.in | 10 +++++----- thunderbird.spec | 11 ++++++++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/thunderbird-wayland.sh.in b/thunderbird-wayland.sh.in index 6eb8f7f..028bb50 100644 --- a/thunderbird-wayland.sh.in +++ b/thunderbird-wayland.sh.in @@ -9,4 +9,4 @@ if [ "$XDG_CURRENT_DESKTOP" == "GNOME" ]; then export MOZ_ENABLE_WAYLAND=1 fi -exec /usr/bin/thunderbird "$@" +exec __PREFIX__/bin/thunderbird "$@" diff --git a/thunderbird.sh.in b/thunderbird.sh.in index b0ff04d..f25f264 100644 --- a/thunderbird.sh.in +++ b/thunderbird.sh.in @@ -10,12 +10,12 @@ MOZ_ARCH=$(uname -m) case $MOZ_ARCH in x86_64 | s390x | sparc64 ) - MOZ_LIB_DIR="/usr/lib64" - SECONDARY_LIB_DIR="/usr/lib" + MOZ_LIB_DIR="__PREFIX__/lib64" + SECONDARY_LIB_DIR="__PREFIX__/lib" ;; * ) - MOZ_LIB_DIR="/usr/lib" - SECONDARY_LIB_DIR="/usr/lib64" + MOZ_LIB_DIR="__PREFIX__/lib" + SECONDARY_LIB_DIR="__PREFIX__/lib64" ;; esac @@ -46,7 +46,7 @@ MOZ_LAUNCHER="$MOZ_DIST_BIN/thunderbird" ## ## Set MOZ_APP_LAUNCHER for gnome-session ## -export MOZ_APP_LAUNCHER="/usr/bin/thunderbird" +export MOZ_APP_LAUNCHER="__PREFIX__/bin/thunderbird" ## ## Disable the GNOME crash dialog, Moz has it's own diff --git a/thunderbird.spec b/thunderbird.spec index e4edf3f..3126bc0 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -82,7 +82,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.5.1 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -486,9 +486,11 @@ desktop-file-install --vendor mozilla \ # set up the thunderbird start script rm -f $RPM_BUILD_ROOT/%{_bindir}/thunderbird -%{__cat} %{SOURCE21} > $RPM_BUILD_ROOT%{_bindir}/thunderbird +%{__cat} %{SOURCE21} | %{__sed} -e 's,__PREFIX__,%{_prefix},g' > \ + $RPM_BUILD_ROOT%{_bindir}/thunderbird %{__chmod} 755 $RPM_BUILD_ROOT/%{_bindir}/thunderbird -%{__cat} %{SOURCE28} > %{buildroot}%{_bindir}/thunderbird-wayland +%{__cat} %{SOURCE28} | %{__sed} -e 's,__PREFIX__,%{_prefix},g' > \ + %{buildroot}%{_bindir}/thunderbird-wayland %{__chmod} 755 %{buildroot}%{_bindir}/thunderbird-wayland # set up our default preferences @@ -678,6 +680,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Feb 21 2019 Kalev Lember - 60.5.1-2 +- Avoid hardcoding /usr in launcher scripts + * Mon Feb 18 2019 Martin Stransky - 60.5.1-1 - Update to 60.5.1 From 74d7494df06290561280cdb44e0c064b906a1607 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Sat, 2 Mar 2019 11:06:06 +0100 Subject: [PATCH 035/402] Fix hunspell dictionary symlink when built for flatpak We can't assume that the prefix where thunderbird is installed is the same where hunspell is: when building for flatpak, thunderbird is in /app, but hunspell dictionaries are in /usr. Fix this by asking hunspell pkg-config file where it is installed, instead of assuming it's in the same prefix as thunderbird. --- thunderbird.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index 3126bc0..3b78f70 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -82,7 +82,7 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.5.1 -Release: 2%{?dist} +Release: 3%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -547,7 +547,7 @@ install -c -m 644 LICENSE $RPM_BUILD_ROOT%{mozappdir} # Use the system hunspell dictionaries %{__rm} -rf $RPM_BUILD_ROOT/%{mozappdir}/dictionaries -ln -s %{_datadir}/myspell $RPM_BUILD_ROOT%{mozappdir}/dictionaries +ln -s $(pkg-config --variable prefix hunspell)/share/myspell $RPM_BUILD_ROOT%{mozappdir}/dictionaries # ghost files %{__mkdir_p} $RPM_BUILD_ROOT%{mozappdir}/components @@ -680,6 +680,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Sat Mar 02 2019 Kalev Lember - 60.5.1-3 +- Fix hunspell dictionary symlink when built for flatpak + * Thu Feb 21 2019 Kalev Lember - 60.5.1-2 - Avoid hardcoding /usr in launcher scripts From 7217bebaff1b1afc222039d6a291f11f7dd6a321 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 6 Mar 2019 13:30:53 +0100 Subject: [PATCH 036/402] Update to 60.5.3 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index b887915..316eb36 100644 --- a/.gitignore +++ b/.gitignore @@ -232,3 +232,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.5.1.source.tar.xz /thunderbird-langpacks-60.5.1-20190218.tar.xz /lightning-langpacks-60.5.1.tar.xz +/thunderbird-60.5.3.source.tar.xz +/lightning-langpacks-60.5.3.tar.xz +/thunderbird-langpacks-60.5.3-20190306.tar.xz diff --git a/sources b/sources index 3a37538..4480c91 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.5.1.source.tar.xz) = dafb7c81568b96285aa367fdac3db65aa0972a8224385714b14b67abdd5b17df963aec63608538a566f20c655cf0eb6784ba2b304151b2cc9b9dc3fdd9a48c7c -SHA512 (thunderbird-langpacks-60.5.1-20190218.tar.xz) = 68db7b6134a5eee8a8bc08b4a3c35823664072a65913ce138c1b0e969967f890655592f01ccfe4295a9a6ec83fe2f4e56bac70690867f638dfd90528af8b05b5 -SHA512 (lightning-langpacks-60.5.1.tar.xz) = 0e769a9e611b552584181f6403a1cb99209d2f5e7326c5e698e28b52f4580abd6e6272333cc7e9fbca23079f15760b77ec1bb9118da36857ebd2d12865804dd3 +SHA512 (thunderbird-60.5.3.source.tar.xz) = 0b647988e711be9a113b6c520d889200898a675391e61916a4d16578d5b1335263c9ebc623369b4f5160abf08fd1be5954ede42bc17f03f1b2937d8b9fd565c9 +SHA512 (lightning-langpacks-60.5.3.tar.xz) = 320a468c2aef56a7071c87cd122746bbcbd2a1fcf071375b50b3d37b9fb7d8a8e062dc75a69f2e7fe2bd4aa5a17d0f4a65705b7a2c44e8c4d630efda5e93f4ca +SHA512 (thunderbird-langpacks-60.5.3-20190306.tar.xz) = a07d2f47be9919e7d2af2e541b4f39c2d66ef73f7804a69192c36de23424b996331538504b522c6a92094626dfe4bc1024c3c93e52bac22b6e5aa73acd9fc42f diff --git a/thunderbird.spec b/thunderbird.spec index 3b78f70..eb7a3e0 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -81,14 +81,14 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.5.1 -Release: 3%{?dist} +Version: 60.5.3 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190218.tar.xz +Source1: thunderbird-langpacks-%{version}-20190306.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -680,6 +680,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Mon Mar 6 2019 Martin Stransky - 60.5.3-1 +- Update to 60.5.3 + * Sat Mar 02 2019 Kalev Lember - 60.5.1-3 - Fix hunspell dictionary symlink when built for flatpak From 4bfc3f1f8e57a107881f11ae1dc63c23dffae6a4 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 6 Mar 2019 13:33:02 +0100 Subject: [PATCH 037/402] Fixed changelog --- thunderbird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index eb7a3e0..754eefc 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -680,7 +680,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog -* Mon Mar 6 2019 Martin Stransky - 60.5.3-1 +* Wed Mar 6 2019 Martin Stransky - 60.5.3-1 - Update to 60.5.3 * Sat Mar 02 2019 Kalev Lember - 60.5.1-3 From 77e071ad5ef8f7a0599d67764839ae5d46c143c9 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Fri, 8 Mar 2019 16:07:49 +0100 Subject: [PATCH 038/402] Disabled system vpx on Fedora 31/30 --- thunderbird.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index 754eefc..8772787 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -35,8 +35,12 @@ %define libnotify_version 0.4 %define _default_patch_fuzz 2 -# Use system libvpx? -%define system_libvpx 1 +# libvpx is too new for Firefox 65 +%if 0%{?fedora} < 30 +%global system_libvpx 1 +%else +%global system_libvpx 0 +%endif %define system_jpeg 1 From 5740202b87cf2b6d9caf2edf5e121a1e5df6248d Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Fri, 8 Mar 2019 20:17:26 +0100 Subject: [PATCH 039/402] Build fixes --- thunderbird.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 8772787..3140466 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -413,8 +413,12 @@ find ./ -name config.guess -exec cp /usr/lib/rpm/config.guess {} ';' # MOZ_OPT_FLAGS=$(echo "$RPM_OPT_FLAGS -fpermissive" | \ %{__sed} -e 's/-Wall//') -#rhbz#1037353 +%if 0%{?fedora} < 30 MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -Wformat-security -Wformat -Werror=format-security" +%else +# Workaround for mozbz#1531309 +MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-Werror=format-security//') +%endif # Disable null pointer gcc6 optimization (rhbz#1311886) MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fno-delete-null-pointer-checks" # Use hardened build? From 0f15451c7e463fbde4e6c4557f97378605216029 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 11 Mar 2019 09:53:12 +0100 Subject: [PATCH 040/402] libvpc spec tweaks --- thunderbird.spec | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index 3140466..2650638 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -178,7 +178,9 @@ BuildRequires: autoconf213 BuildRequires: desktop-file-utils BuildRequires: libcurl-devel BuildRequires: mesa-libGL-devel +%if %{?system_libvpx} BuildRequires: libvpx-devel >= %{libvpx_version} +%endif BuildRequires: pulseaudio-libs-devel BuildRequires: libicu-devel BuildRequires: GConf2-devel @@ -351,12 +353,6 @@ echo "ac_add_options --with-float-abi=soft" >> .mozconfig echo "ac_add_options --disable-yarr-jit" >> .mozconfig %endif -%if %{?system_libvpx} -echo "ac_add_options --with-system-libvpx" >> .mozconfig -%else -echo "ac_add_options --without-system-libvpx" >> .mozconfig -%endif - %if %{?system_libicu} echo "ac_add_options --with-system-icu" >> .mozconfig %else @@ -374,6 +370,7 @@ echo "ac_add_options --with-system-libvpx" >> .mozconfig %else echo "ac_add_options --without-system-libvpx" >> .mozconfig %endif + %if %{enable_mozilla_crashreporter} echo "ac_add_options --enable-crashreporter" >> .mozconfig %else From a3aebc6feae6b4c5fcba8dfdb54327f27782b55c Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 12 Mar 2019 12:13:13 +0100 Subject: [PATCH 041/402] Added rust 1.33 build fixes --- rust-1.33-build.patch | 60 +++++++++++++++++++++++++++++++++++++++++++ thunderbird.spec | 9 +++---- 2 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 rust-1.33-build.patch diff --git a/rust-1.33-build.patch b/rust-1.33-build.patch new file mode 100644 index 0000000..bd939fd --- /dev/null +++ b/rust-1.33-build.patch @@ -0,0 +1,60 @@ +diff -up thunderbird-60.5.3/servo/components/style_traits/Cargo.toml.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/Cargo.toml +--- thunderbird-60.5.3/servo/components/style_traits/Cargo.toml.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 ++++ thunderbird-60.5.3/servo/components/style_traits/Cargo.toml 2019-03-12 12:09:28.754720164 +0100 +@@ -19,7 +19,7 @@ cssparser = "0.23.0" + bitflags = "1.0" + euclid = "0.17" + malloc_size_of = { path = "../malloc_size_of" } +-malloc_size_of_derive = { path = "../malloc_size_of_derive" } ++malloc_size_of_derive = "0.1" + selectors = { path = "../selectors" } + serde = {version = "1.0", optional = true} + webrender_api = {git = "https://github.com/servo/webrender", optional = true} +diff -up thunderbird-60.5.3/servo/components/style_traits/lib.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/lib.rs +--- thunderbird-60.5.3/servo/components/style_traits/lib.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 ++++ thunderbird-60.5.3/servo/components/style_traits/lib.rs 2019-03-12 12:10:04.596635368 +0100 +@@ -72,7 +72,6 @@ pub enum CSSPixel {} + // / hidpi_ratio => DeviceIndependentPixel + // / desktop_zoom => CSSPixel + +-pub mod cursor; + #[macro_use] + pub mod values; + #[macro_use] +diff -up thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/values.rs +--- thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 ++++ thunderbird-60.5.3/servo/components/style_traits/values.rs 2019-03-12 12:10:04.596635368 +0100 +@@ -135,24 +135,6 @@ where + } + } + +-#[macro_export] +-macro_rules! serialize_function { +- ($dest: expr, $name: ident($( $arg: expr, )+)) => { +- serialize_function!($dest, $name($($arg),+)) +- }; +- ($dest: expr, $name: ident($first_arg: expr $( , $arg: expr )*)) => { +- { +- $dest.write_str(concat!(stringify!($name), "("))?; +- $first_arg.to_css($dest)?; +- $( +- $dest.write_str(", ")?; +- $arg.to_css($dest)?; +- )* +- $dest.write_char(')') +- } +- } +-} +- + /// Convenience wrapper to serialise CSS values separated by a given string. + pub struct SequenceWriter<'a, 'b: 'a, W: 'b> { + inner: &'a mut CssWriter<'b, W>, +@@ -404,7 +386,7 @@ impl_to_css_for_predefined_type!(::csspa + impl_to_css_for_predefined_type!(::cssparser::Color); + impl_to_css_for_predefined_type!(::cssparser::UnicodeRange); + +-#[macro_export] ++/// Define an enum type with unit variants that each correspond to a CSS keyword. + macro_rules! define_css_keyword_enum { + (pub enum $name:ident { $($variant:ident = $css:expr,)+ }) => { + #[allow(missing_docs)] diff --git a/thunderbird.spec b/thunderbird.spec index 2650638..a0f84dc 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -106,15 +106,14 @@ Source21: thunderbird.sh.in Source28: thunderbird-wayland.sh.in Source29: thunderbird-wayland.desktop -# Mozilla (XULRunner) patches +# Build patches +Patch1: rust-1.33-build.patch Patch9: mozilla-build-arm.patch Patch26: build-icu-big-endian.patch Patch37: build-jit-atomic-always-lucky.patch Patch40: build-aarch64-skia.patch Patch226: rhbz-1354671.patch Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch - -# Build patches Patch103: rhbz-1219542-s390-build.patch # PPC fix @@ -231,8 +230,8 @@ debug %{name}, you want to install %{name}-debuginfo instead. %prep %setup -q -# Mozilla (XULRunner) patches -#cd mozilla +# Build patches +%patch1 -p1 -b .rust-1.33-build %patch9 -p2 -b .arm %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build From 35c879447bdbcd859c9c4d31640b872523f46078 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 12 Mar 2019 15:17:56 +0100 Subject: [PATCH 042/402] Rust 1.33 build fixes --- rust-1.33-build.patch | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/rust-1.33-build.patch b/rust-1.33-build.patch index bd939fd..1011a10 100644 --- a/rust-1.33-build.patch +++ b/rust-1.33-build.patch @@ -1,15 +1,3 @@ -diff -up thunderbird-60.5.3/servo/components/style_traits/Cargo.toml.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/Cargo.toml ---- thunderbird-60.5.3/servo/components/style_traits/Cargo.toml.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 -+++ thunderbird-60.5.3/servo/components/style_traits/Cargo.toml 2019-03-12 12:09:28.754720164 +0100 -@@ -19,7 +19,7 @@ cssparser = "0.23.0" - bitflags = "1.0" - euclid = "0.17" - malloc_size_of = { path = "../malloc_size_of" } --malloc_size_of_derive = { path = "../malloc_size_of_derive" } -+malloc_size_of_derive = "0.1" - selectors = { path = "../selectors" } - serde = {version = "1.0", optional = true} - webrender_api = {git = "https://github.com/servo/webrender", optional = true} diff -up thunderbird-60.5.3/servo/components/style_traits/lib.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/lib.rs --- thunderbird-60.5.3/servo/components/style_traits/lib.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 +++ thunderbird-60.5.3/servo/components/style_traits/lib.rs 2019-03-12 12:10:04.596635368 +0100 From 555907180020cb8e32aa17ecbc97f1f1614c4ebf Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 12 Mar 2019 21:34:49 +0100 Subject: [PATCH 043/402] Rust build fix --- rust-1.33-build.patch | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/rust-1.33-build.patch b/rust-1.33-build.patch index 1011a10..86bcb59 100644 --- a/rust-1.33-build.patch +++ b/rust-1.33-build.patch @@ -1,14 +1,3 @@ -diff -up thunderbird-60.5.3/servo/components/style_traits/lib.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/lib.rs ---- thunderbird-60.5.3/servo/components/style_traits/lib.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 -+++ thunderbird-60.5.3/servo/components/style_traits/lib.rs 2019-03-12 12:10:04.596635368 +0100 -@@ -72,7 +72,6 @@ pub enum CSSPixel {} - // / hidpi_ratio => DeviceIndependentPixel - // / desktop_zoom => CSSPixel - --pub mod cursor; - #[macro_use] - pub mod values; - #[macro_use] diff -up thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/values.rs --- thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 +++ thunderbird-60.5.3/servo/components/style_traits/values.rs 2019-03-12 12:10:04.596635368 +0100 From dc9319309b15c8a37542e833cc1df530651ac395 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 13 Mar 2019 15:38:40 +0100 Subject: [PATCH 044/402] Updated rust 1.33 patch --- rust-1.33-build.patch | 85 ++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 26 deletions(-) diff --git a/rust-1.33-build.patch b/rust-1.33-build.patch index 86bcb59..30da243 100644 --- a/rust-1.33-build.patch +++ b/rust-1.33-build.patch @@ -1,32 +1,65 @@ -diff -up thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/values.rs ---- thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 -+++ thunderbird-60.5.3/servo/components/style_traits/values.rs 2019-03-12 12:10:04.596635368 +0100 -@@ -135,24 +135,6 @@ where +diff -up thunderbird-60.5.3/servo/components/style/gecko/regen_atoms.py.rust-1.33-build thunderbird-60.5.3/servo/components/style/gecko/regen_atoms.py +--- thunderbird-60.5.3/servo/components/style/gecko/regen_atoms.py.rust-1.33-build 2019-03-04 19:17:31.000000000 +0100 ++++ thunderbird-60.5.3/servo/components/style/gecko/regen_atoms.py 2019-03-13 15:05:58.965726109 +0100 +@@ -202,6 +202,7 @@ RULE_TEMPLATE = ('("{atom}") =>\n ' + ' }}}};') + + MACRO = ''' ++/// Returns a static atom by passing the literal string it represents. + #[macro_export] + macro_rules! atom {{ + {} +diff -up thunderbird-60.5.3/servo/components/style/gecko_string_cache/namespace.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style/gecko_string_cache/namespace.rs +--- thunderbird-60.5.3/servo/components/style/gecko_string_cache/namespace.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 ++++ thunderbird-60.5.3/servo/components/style/gecko_string_cache/namespace.rs 2019-03-13 15:05:58.966726107 +0100 +@@ -11,6 +11,7 @@ use std::fmt; + use std::ops::Deref; + use string_cache::{Atom, WeakAtom}; + ++/// Macro text + #[macro_export] + macro_rules! ns { + () => { $crate::string_cache::Namespace(atom!("")) }; +diff -up thunderbird-60.5.3/servo/components/style/properties/properties.mako.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style/properties/properties.mako.rs +--- thunderbird-60.5.3/servo/components/style/properties/properties.mako.rs.rust-1.33-build 2019-03-04 19:17:30.000000000 +0100 ++++ thunderbird-60.5.3/servo/components/style/properties/properties.mako.rs 2019-03-13 15:05:58.966726107 +0100 +@@ -55,6 +55,7 @@ use style_adjuster::StyleAdjuster; + + pub use self::declaration_block::*; + ++/// Generated + #[cfg(feature = "gecko")] + #[macro_export] + macro_rules! property_name { +@@ -3852,7 +3853,7 @@ impl fmt::Debug for AliasId { } } --#[macro_export] --macro_rules! serialize_function { -- ($dest: expr, $name: ident($( $arg: expr, )+)) => { -- serialize_function!($dest, $name($($arg),+)) -- }; -- ($dest: expr, $name: ident($first_arg: expr $( , $arg: expr )*)) => { -- { -- $dest.write_str(concat!(stringify!($name), "("))?; -- $first_arg.to_css($dest)?; -- $( -- $dest.write_str(", ")?; -- $arg.to_css($dest)?; -- )* -- $dest.write_char(')') -- } -- } --} -- - /// Convenience wrapper to serialise CSS values separated by a given string. - pub struct SequenceWriter<'a, 'b: 'a, W: 'b> { - inner: &'a mut CssWriter<'b, W>, -@@ -404,7 +386,7 @@ impl_to_css_for_predefined_type!(::csspa +-// NOTE(emilio): Callers are responsible to deal with prefs. ++/// Callers are responsible to deal with prefs. + #[macro_export] + macro_rules! css_properties_accessors { + ($macro_name: ident) => { +@@ -3875,6 +3876,7 @@ macro_rules! css_properties_accessors { + } + } + ++/// Neco + #[macro_export] + macro_rules! longhand_properties_idents { + ($macro_name: ident) => { +diff -up thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/values.rs +--- thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 ++++ thunderbird-60.5.3/servo/components/style_traits/values.rs 2019-03-13 15:37:34.077560034 +0100 +@@ -135,6 +135,7 @@ where + } + } + ++/// Neco + #[macro_export] + macro_rules! serialize_function { + ($dest: expr, $name: ident($( $arg: expr, )+)) => { +@@ -404,7 +405,7 @@ impl_to_css_for_predefined_type!(::csspa impl_to_css_for_predefined_type!(::cssparser::Color); impl_to_css_for_predefined_type!(::cssparser::UnicodeRange); From ed1dc1f6d3b5da01287acffd2ec8712a9c956e1e Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 18 Mar 2019 13:42:14 +0100 Subject: [PATCH 045/402] Update to 60.6.0 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 316eb36..6cd5eb0 100644 --- a/.gitignore +++ b/.gitignore @@ -235,3 +235,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.5.3.source.tar.xz /lightning-langpacks-60.5.3.tar.xz /thunderbird-langpacks-60.5.3-20190306.tar.xz +/thunderbird-langpacks-60.6.0-20190318.tar.xz +/thunderbird-60.6.0.source.tar.xz +/lightning-langpacks-60.6.0.tar.xz diff --git a/sources b/sources index 4480c91..51980da 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.5.3.source.tar.xz) = 0b647988e711be9a113b6c520d889200898a675391e61916a4d16578d5b1335263c9ebc623369b4f5160abf08fd1be5954ede42bc17f03f1b2937d8b9fd565c9 -SHA512 (lightning-langpacks-60.5.3.tar.xz) = 320a468c2aef56a7071c87cd122746bbcbd2a1fcf071375b50b3d37b9fb7d8a8e062dc75a69f2e7fe2bd4aa5a17d0f4a65705b7a2c44e8c4d630efda5e93f4ca -SHA512 (thunderbird-langpacks-60.5.3-20190306.tar.xz) = a07d2f47be9919e7d2af2e541b4f39c2d66ef73f7804a69192c36de23424b996331538504b522c6a92094626dfe4bc1024c3c93e52bac22b6e5aa73acd9fc42f +SHA512 (thunderbird-langpacks-60.6.0-20190318.tar.xz) = 8b6c19e6008ac4e4b0bf4e42cc4db00823363d209734324e673a3e487ea7c1682dc2d3018462255e01dd6a22f0d3403b563f913b9dfb5a8e678cd3707f8c6016 +SHA512 (thunderbird-60.6.0.source.tar.xz) = 9f58ca34b7b1ea9643db1bd3f370176d9439a38db5aec41b68e118041f6c5cfbc94750ac1b8333d2e20d2f376fb97a0c97deadc87a597896b24cfdcce31b88b4 +SHA512 (lightning-langpacks-60.6.0.tar.xz) = d0c683d86318c466e0b1a78c8cdf0ba7a9b41490c09e9445bd0f4027664b42b4ee4ab592c24cdf6ea46ad157bd194da386ea2d770bf5820c82cc474a619b1bc4 diff --git a/thunderbird.spec b/thunderbird.spec index a0f84dc..0ea6343 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -85,14 +85,14 @@ Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.5.3 +Version: 60.6.0 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190306.tar.xz +Source1: thunderbird-langpacks-%{version}-20190318.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -684,6 +684,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Mon Mar 18 2019 Martin Stransky - 60.6.0-1 +- Update to 60.6.0 + * Wed Mar 6 2019 Martin Stransky - 60.5.3-1 - Update to 60.5.3 From b4a8b84bc1ffeee2351ebb9db02ca32059dd2105 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 19 Mar 2019 10:33:43 +0100 Subject: [PATCH 046/402] Disabled s390x due to https://pagure.io/fedora-infrastructure/issue/7581 --- thunderbird.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/thunderbird.spec b/thunderbird.spec index 0ea6343..75e046e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -1,3 +1,6 @@ +# Disabled due to https://pagure.io/fedora-infrastructure/issue/7581 +ExcludeArch: s390x + # Use system nspr/nss? %define system_nss 1 From 70fc64a64fe2d78d0cecf9e06c253accd243b797 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 25 Mar 2019 17:11:55 +0100 Subject: [PATCH 047/402] Update to 60.6.1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 6cd5eb0..beb9444 100644 --- a/.gitignore +++ b/.gitignore @@ -238,3 +238,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-langpacks-60.6.0-20190318.tar.xz /thunderbird-60.6.0.source.tar.xz /lightning-langpacks-60.6.0.tar.xz +/thunderbird-60.6.1.source.tar.xz +/lightning-langpacks-60.6.1.tar.xz +/thunderbird-langpacks-60.6.1-20190325.tar.xz diff --git a/sources b/sources index 51980da..6d142c9 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-langpacks-60.6.0-20190318.tar.xz) = 8b6c19e6008ac4e4b0bf4e42cc4db00823363d209734324e673a3e487ea7c1682dc2d3018462255e01dd6a22f0d3403b563f913b9dfb5a8e678cd3707f8c6016 -SHA512 (thunderbird-60.6.0.source.tar.xz) = 9f58ca34b7b1ea9643db1bd3f370176d9439a38db5aec41b68e118041f6c5cfbc94750ac1b8333d2e20d2f376fb97a0c97deadc87a597896b24cfdcce31b88b4 -SHA512 (lightning-langpacks-60.6.0.tar.xz) = d0c683d86318c466e0b1a78c8cdf0ba7a9b41490c09e9445bd0f4027664b42b4ee4ab592c24cdf6ea46ad157bd194da386ea2d770bf5820c82cc474a619b1bc4 +SHA512 (thunderbird-60.6.1.source.tar.xz) = 78e96aeb235a07ea3f53c4212a764e9b92dacd0e5d5561e454008a56d165a1e235ed05a8ecdb77efecf80f4c7f7ba2cf7a682c775047d7c175dfb50a1d9a42d2 +SHA512 (lightning-langpacks-60.6.1.tar.xz) = 720c73fa44b4ab085c12f2a570f57d31878912696afaf936d155882622395480952cd10cf245c3b589d93227f57427e5ae6cb0878f706e877e10272abe78ed1e +SHA512 (thunderbird-langpacks-60.6.1-20190325.tar.xz) = da8cda7b4777658e461c71679785e2253c42cd8109b15c5232c3226261ad1be584fe8d89e5ebabf94d87de9d732388c67c195876cbf800a1a4ac0dcd7f381793 diff --git a/thunderbird.spec b/thunderbird.spec index 75e046e..3a618e4 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -88,14 +88,14 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.6.0 +Version: 60.6.1 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190318.tar.xz +Source1: thunderbird-langpacks-%{version}-20190325.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -687,6 +687,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Mon Mar 25 2019 Martin Stransky - 60.6.1-1 +- Update to 60.6.1 + * Mon Mar 18 2019 Martin Stransky - 60.6.0-1 - Update to 60.6.0 From a0760b353104506383ef4761a014be282e38a4d1 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 26 Mar 2019 12:58:04 +0100 Subject: [PATCH 048/402] Added rawhide build fix - mozilla-1533969 --- mozilla-1533969.patch | 18 ++++++++++++++++++ thunderbird.spec | 7 ++++++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 mozilla-1533969.patch diff --git a/mozilla-1533969.patch b/mozilla-1533969.patch new file mode 100644 index 0000000..f84d77a --- /dev/null +++ b/mozilla-1533969.patch @@ -0,0 +1,18 @@ +diff -up thunderbird-60.6.1/js/src/util/NativeStack.cpp.1533969 thunderbird-60.6.1/js/src/util/NativeStack.cpp +diff -up thunderbird-60.6.1/tools/profiler/core/platform.h.1533969 thunderbird-60.6.1/tools/profiler/core/platform.h +--- thunderbird-60.6.1/tools/profiler/core/platform.h.1533969 2019-03-26 12:51:50.138988424 +0100 ++++ thunderbird-60.6.1/tools/profiler/core/platform.h 2019-03-26 12:54:57.576579732 +0100 +@@ -47,11 +47,11 @@ + #if defined(__GLIBC__) + #include + #include +-static inline pid_t gettid() { return (pid_t)syscall(SYS_gettid); } ++# define gettid() static_cast(syscall(SYS_gettid)) + #elif defined(GP_OS_darwin) + #include + #include +-static inline pid_t gettid() { return (pid_t)syscall(SYS_thread_selfid); } ++# define gettid() static_cast(syscall(SYS_thread_selfid)) + #elif defined(GP_OS_android) + #include + #elif defined(GP_OS_windows) diff --git a/thunderbird.spec b/thunderbird.spec index 3a618e4..05dfb4e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -89,7 +89,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.6.1 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -118,6 +118,7 @@ Patch40: build-aarch64-skia.patch Patch226: rhbz-1354671.patch Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch Patch103: rhbz-1219542-s390-build.patch +Patch104: mozilla-1533969.patch # PPC fix Patch304: mozilla-1245783.patch @@ -239,6 +240,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build %endif +%patch104 -p1 -b .1533969 %patch304 -p1 -b .1245783 %patch309 -p1 -b .1460871-ldap-query @@ -687,6 +689,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Mar 26 2019 Martin Stransky - 60.6.1-2 +- Added rawhide build fix + * Mon Mar 25 2019 Martin Stransky - 60.6.1-1 - Update to 60.6.1 From 36eed645e1710423de63dcf8ecf01e2e12e6c79e Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 3 Apr 2019 15:10:38 +0200 Subject: [PATCH 049/402] Added fixes for mozbz#1526243, mozbz#1540145, mozbz#526293 --- mozilla-1526243.patch | 340 ++++++++++++++++++++++++++++++++++++++++++ mozilla-1540145.patch | 168 +++++++++++++++++++++ mozilla-526293.patch | 14 ++ thunderbird.spec | 12 +- 4 files changed, 533 insertions(+), 1 deletion(-) create mode 100644 mozilla-1526243.patch create mode 100644 mozilla-1540145.patch create mode 100644 mozilla-526293.patch diff --git a/mozilla-1526243.patch b/mozilla-1526243.patch new file mode 100644 index 0000000..2d12378 --- /dev/null +++ b/mozilla-1526243.patch @@ -0,0 +1,340 @@ +changeset: 465480:a86f3560fb17 +parent: 465477:26d9b7ffbd6b +user: Martin Stransky +date: Fri Mar 29 15:30:15 2019 +0100 +summary: Bug 1526243 - [Linux] Don't use nsGConfService in nsGNOMEShellService.cpp, r=glandium + +diff --git a/browser/components/shell/nsGNOMEShellService.cpp b/browser/components/shell/nsGNOMEShellService.cpp +--- a/browser/components/shell/nsGNOMEShellService.cpp ++++ b/browser/components/shell/nsGNOMEShellService.cpp +@@ -10,17 +10,16 @@ + #include "nsShellService.h" + #include "nsIServiceManager.h" + #include "nsIFile.h" + #include "nsIProperties.h" + #include "nsDirectoryServiceDefs.h" + #include "nsIPrefService.h" + #include "prenv.h" + #include "nsString.h" +-#include "nsIGConfService.h" + #include "nsIGIOService.h" + #include "nsIGSettingsService.h" + #include "nsIStringBundle.h" + #include "nsIOutputStream.h" + #include "nsIProcess.h" + #include "nsServiceManagerUtils.h" + #include "nsComponentManagerUtils.h" + #include "nsIImageLoadingContent.h" +@@ -65,48 +64,39 @@ static const ProtocolAssociation appProt + + static const MimeTypeAssociation appTypes[] = { + // clang-format off + { "text/html", "htm html shtml" }, + { "application/xhtml+xml", "xhtml xht" } + // clang-format on + }; + +-// GConf registry key constants +-#define DG_BACKGROUND "/desktop/gnome/background" +- +-#define kDesktopImageKey DG_BACKGROUND "/picture_filename" +-#define kDesktopOptionsKey DG_BACKGROUND "/picture_options" +-#define kDesktopDrawBGKey DG_BACKGROUND "/draw_background" +-#define kDesktopColorKey DG_BACKGROUND "/primary_color" +- + #define kDesktopBGSchema "org.gnome.desktop.background" + #define kDesktopImageGSKey "picture-uri" + #define kDesktopOptionGSKey "picture-options" + #define kDesktopDrawBGGSKey "draw-background" + #define kDesktopColorGSKey "primary-color" + + static bool IsRunningAsASnap() { return (PR_GetEnv("SNAP") != nullptr); } + + nsresult nsGNOMEShellService::Init() { + nsresult rv; + + if (gfxPlatform::IsHeadless()) { + return NS_ERROR_NOT_AVAILABLE; + } + +- // GConf, GSettings or GIO _must_ be available, or we do not allow ++ // GSettings or GIO _must_ be available, or we do not allow + // CreateInstance to succeed. + +- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); + nsCOMPtr gsettings = + do_GetService(NS_GSETTINGSSERVICE_CONTRACTID); + +- if (!gconf && !giovfs && !gsettings) return NS_ERROR_NOT_AVAILABLE; ++ if (!giovfs && !gsettings) return NS_ERROR_NOT_AVAILABLE; + + // Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use + // the locale encoding. If it's not set, they use UTF-8. + mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nullptr; + + if (GetAppPathFromLauncher()) return NS_OK; + + nsCOMPtr dirSvc( +@@ -212,35 +202,23 @@ nsGNOMEShellService::IsDefaultBrowser(bo + } + if (strcmp(output, "yes\n") == 0) { + *aIsDefaultBrowser = true; + } + g_free(output); + return NS_OK; + } + +- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); +- +- bool enabled; + nsAutoCString handler; + nsCOMPtr gioApp; + + for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) { + if (!appProtocols[i].essential) continue; + +- if (gconf) { +- handler.Truncate(); +- gconf->GetAppForProtocol(nsDependentCString(appProtocols[i].name), +- &enabled, handler); +- +- if (!CheckHandlerMatchesAppName(handler) || !enabled) +- return NS_OK; // the handler is disabled or set to another app +- } +- + if (giovfs) { + handler.Truncate(); + nsCOMPtr handlerApp; + giovfs->GetAppForURIScheme(nsDependentCString(appProtocols[i].name), + getter_AddRefs(handlerApp)); + gioApp = do_QueryInterface(handlerApp); + if (!gioApp) return NS_OK; + +@@ -270,39 +248,17 @@ nsGNOMEShellService::SetDefaultBrowser(b + GSpawnFlags flags = static_cast(G_SPAWN_SEARCH_PATH | + G_SPAWN_STDOUT_TO_DEV_NULL | + G_SPAWN_STDERR_TO_DEV_NULL); + g_spawn_sync(nullptr, (gchar **)argv, nullptr, flags, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr); + return NS_OK; + } + +- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); +- if (gconf) { +- nsAutoCString appKeyValue; +- if (mAppIsInPath) { +- // mAppPath is in the users path, so use only the basename as the launcher +- gchar *tmp = g_path_get_basename(mAppPath.get()); +- appKeyValue = tmp; +- g_free(tmp); +- } else { +- appKeyValue = mAppPath; +- } +- +- appKeyValue.AppendLiteral(" %s"); +- +- for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) { +- if (appProtocols[i].essential || aClaimAllTypes) { +- gconf->SetAppForProtocol(nsDependentCString(appProtocols[i].name), +- appKeyValue); +- } +- } +- } +- + if (giovfs) { + nsresult rv; + nsCOMPtr bundleService = + do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr brandBundle; + rv = bundleService->CreateBundle(BRAND_PROPERTIES, +@@ -353,19 +309,21 @@ nsGNOMEShellService::SetDefaultBrowser(b + } + + return NS_OK; + } + + NS_IMETHODIMP + nsGNOMEShellService::GetCanSetDesktopBackground(bool *aResult) { + // setting desktop background is currently only supported +- // for Gnome or desktops using the same GSettings and GConf keys +- const char *gnomeSession = getenv("GNOME_DESKTOP_SESSION_ID"); +- if (gnomeSession) { ++ // for Gnome or desktops using the same GSettings keys ++ const char *currentDesktop = getenv("XDG_CURRENT_DESKTOP"); ++ if (currentDesktop && ++ (strstr(currentDesktop, "GNOME-Flashback:GNOME") != nullptr || ++ strstr(currentDesktop, "GNOME") != nullptr)) { + *aResult = true; + } else { + *aResult = false; + } + + return NS_OK; + } + +@@ -439,20 +397,16 @@ nsGNOMEShellService::SetDesktopBackgroun + filePath.Append('/'); + filePath.Append(NS_ConvertUTF16toUTF8(brandName)); + filePath.AppendLiteral("_wallpaper.png"); + + // write the image to a file in the home dir + rv = WriteImage(filePath, container); + NS_ENSURE_SUCCESS(rv, rv); + +- // Try GSettings first. If we don't have GSettings or the right schema, fall +- // back to using GConf instead. Note that if GSettings works ok, the changes +- // get mirrored to GConf by the gsettings->gconf bridge in +- // gnome-settings-daemon + nsCOMPtr gsettings = + do_GetService(NS_GSETTINGSSERVICE_CONTRACTID); + if (gsettings) { + nsCOMPtr background_settings; + gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(kDesktopBGSchema), + getter_AddRefs(background_settings)); + if (background_settings) { + gchar *file_uri = g_filename_to_uri(filePath.get(), nullptr, nullptr); +@@ -465,32 +419,17 @@ nsGNOMEShellService::SetDesktopBackgroun + nsDependentCString(file_uri)); + g_free(file_uri); + background_settings->SetBoolean(NS_LITERAL_CSTRING(kDesktopDrawBGGSKey), + true); + return rv; + } + } + +- // if the file was written successfully, set it as the system wallpaper +- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); +- +- if (gconf) { +- gconf->SetString(NS_LITERAL_CSTRING(kDesktopOptionsKey), options); +- +- // Set the image to an empty string first to force a refresh +- // (since we could be writing a new image on top of an existing +- // Firefox_wallpaper.png and nautilus doesn't monitor the file for changes) +- gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), EmptyCString()); +- +- gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), filePath); +- gconf->SetBool(NS_LITERAL_CSTRING(kDesktopDrawBGKey), true); +- } +- +- return rv; ++ return NS_ERROR_FAILURE; + } + + #define COLOR_16_TO_8_BIT(_c) ((_c) >> 8) + #define COLOR_8_TO_16_BIT(_c) ((_c) << 8 | (_c)) + + NS_IMETHODIMP + nsGNOMEShellService::GetDesktopBackgroundColor(uint32_t *aColor) { + nsCOMPtr gsettings = +@@ -502,22 +441,16 @@ nsGNOMEShellService::GetDesktopBackgroun + gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(kDesktopBGSchema), + getter_AddRefs(background_settings)); + if (background_settings) { + background_settings->GetString(NS_LITERAL_CSTRING(kDesktopColorGSKey), + background); + } + } + +- if (!background_settings) { +- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); +- if (gconf) +- gconf->GetString(NS_LITERAL_CSTRING(kDesktopColorKey), background); +- } +- + if (background.IsEmpty()) { + *aColor = 0; + return NS_OK; + } + + GdkColor color; + gboolean success = gdk_color_parse(background.get(), &color); + +@@ -555,23 +488,17 @@ nsGNOMEShellService::SetDesktopBackgroun + getter_AddRefs(background_settings)); + if (background_settings) { + background_settings->SetString(NS_LITERAL_CSTRING(kDesktopColorGSKey), + colorString); + return NS_OK; + } + } + +- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); +- +- if (gconf) { +- gconf->SetString(NS_LITERAL_CSTRING(kDesktopColorKey), colorString); +- } +- +- return NS_OK; ++ return NS_ERROR_FAILURE; + } + + NS_IMETHODIMP + nsGNOMEShellService::OpenApplication(int32_t aApplication) { + nsAutoCString scheme; + if (aApplication == APPLICATION_MAIL) + scheme.AssignLiteral("mailto"); + else if (aApplication == APPLICATION_NEWS) +@@ -581,55 +508,17 @@ nsGNOMEShellService::OpenApplication(int + + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); + if (giovfs) { + nsCOMPtr handlerApp; + giovfs->GetAppForURIScheme(scheme, getter_AddRefs(handlerApp)); + if (handlerApp) return handlerApp->LaunchWithURI(nullptr, nullptr); + } + +- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); +- if (!gconf) return NS_ERROR_FAILURE; +- +- bool enabled; +- nsAutoCString appCommand; +- gconf->GetAppForProtocol(scheme, &enabled, appCommand); +- +- if (!enabled) return NS_ERROR_FAILURE; +- +- // XXX we don't currently handle launching a terminal window. +- // If the handler requires a terminal, bail. +- bool requiresTerminal; +- gconf->HandlerRequiresTerminal(scheme, &requiresTerminal); +- if (requiresTerminal) return NS_ERROR_FAILURE; +- +- // Perform shell argument expansion +- int argc; +- char **argv; +- if (!g_shell_parse_argv(appCommand.get(), &argc, &argv, nullptr)) +- return NS_ERROR_FAILURE; +- +- char **newArgv = new char *[argc + 1]; +- int newArgc = 0; +- +- // Run through the list of arguments. Copy all of them to the new +- // argv except for %s, which we skip. +- for (int i = 0; i < argc; ++i) { +- if (strcmp(argv[i], "%s") != 0) newArgv[newArgc++] = argv[i]; +- } +- +- newArgv[newArgc] = nullptr; +- +- gboolean err = g_spawn_async(nullptr, newArgv, nullptr, G_SPAWN_SEARCH_PATH, +- nullptr, nullptr, nullptr, nullptr); +- +- g_strfreev(argv); +- delete[] newArgv; +- +- return err ? NS_OK : NS_ERROR_FAILURE; ++ return NS_ERROR_FAILURE; + } + + NS_IMETHODIMP + nsGNOMEShellService::OpenApplicationWithURI(nsIFile *aApplication, + const nsACString &aURI) { + nsresult rv; + nsCOMPtr process = + do_CreateInstance("@mozilla.org/process/util;1", &rv); + diff --git a/mozilla-1540145.patch b/mozilla-1540145.patch new file mode 100644 index 0000000..efdf89d --- /dev/null +++ b/mozilla-1540145.patch @@ -0,0 +1,168 @@ +diff -up firefox-66.0.1/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.mozilla-1540145 firefox-66.0.1/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp +--- firefox-66.0.1/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.mozilla-1540145 2019-03-22 06:06:07.000000000 +0100 ++++ firefox-66.0.1/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp 2019-04-01 09:33:18.621166482 +0200 +@@ -6,7 +6,6 @@ + #include "nsISystemProxySettings.h" + #include "mozilla/ModuleUtils.h" + #include "nsIServiceManager.h" +-#include "nsIGConfService.h" + #include "nsIURI.h" + #include "nsReadableUtils.h" + #include "nsArrayUtils.h" +@@ -32,16 +31,10 @@ class nsUnixSystemProxySettings final : + private: + ~nsUnixSystemProxySettings() = default; + +- nsCOMPtr mGConf; +- nsCOMPtr mGSettings; ++ nsCOMPtr mGSettings; + nsCOMPtr mProxySettings; + nsInterfaceHashtable + mSchemeProxySettings; +- bool IsProxyMode(const char* aMode); +- nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, +- nsACString& aResult); +- nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, +- int32_t aPort, nsACString& aResult); + nsresult GetProxyFromGSettings(const nsACString& aScheme, + const nsACString& aHost, int32_t aPort, + nsACString& aResult); +@@ -66,20 +59,10 @@ nsresult nsUnixSystemProxySettings::Init + NS_LITERAL_CSTRING("org.gnome.system.proxy"), + getter_AddRefs(mProxySettings)); + } +- if (!mProxySettings) { +- mGConf = do_GetService(NS_GCONFSERVICE_CONTRACTID); +- } + + return NS_OK; + } + +-bool nsUnixSystemProxySettings::IsProxyMode(const char* aMode) { +- nsAutoCString mode; +- return NS_SUCCEEDED(mGConf->GetString( +- NS_LITERAL_CSTRING("/system/proxy/mode"), mode)) && +- mode.EqualsASCII(aMode); +-} +- + nsresult nsUnixSystemProxySettings::GetPACURI(nsACString& aResult) { + if (mProxySettings) { + nsCString proxyMode; +@@ -92,14 +75,8 @@ nsresult nsUnixSystemProxySettings::GetP + } + /* The org.gnome.system.proxy schema has been found, but auto mode is not + * set. Don't try the GConf and return empty string. */ +- aResult.Truncate(); +- return NS_OK; + } + +- if (mGConf && IsProxyMode("auto")) { +- return mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/autoconfig_url"), +- aResult); +- } + // Return an empty string when auto mode is not set. + aResult.Truncate(); + return NS_OK; +@@ -217,30 +194,6 @@ static nsresult GetProxyFromEnvironment( + return NS_OK; + } + +-nsresult nsUnixSystemProxySettings::SetProxyResultFromGConf( +- const char* aKeyBase, const char* aType, nsACString& aResult) { +- nsAutoCString hostKey; +- hostKey.AppendASCII(aKeyBase); +- hostKey.AppendLiteral("host"); +- nsAutoCString host; +- nsresult rv = mGConf->GetString(hostKey, host); +- NS_ENSURE_SUCCESS(rv, rv); +- if (host.IsEmpty()) return NS_ERROR_FAILURE; +- +- nsAutoCString portKey; +- portKey.AppendASCII(aKeyBase); +- portKey.AppendLiteral("port"); +- int32_t port; +- rv = mGConf->GetInt(portKey, &port); +- NS_ENSURE_SUCCESS(rv, rv); +- +- /* When port is 0, proxy is not considered as enabled even if host is set. */ +- if (port == 0) return NS_ERROR_FAILURE; +- +- SetProxyResult(aType, host, port, aResult); +- return NS_OK; +-} +- + nsresult nsUnixSystemProxySettings::SetProxyResultFromGSettings( + const char* aKeyBase, const char* aType, nsACString& aResult) { + nsDependentCString key(aKeyBase); +@@ -366,63 +319,6 @@ static bool HostIgnoredByProxy(const nsA + return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0; + } + +-nsresult nsUnixSystemProxySettings::GetProxyFromGConf(const nsACString& aScheme, +- const nsACString& aHost, +- int32_t aPort, +- nsACString& aResult) { +- bool masterProxySwitch = false; +- mGConf->GetBool(NS_LITERAL_CSTRING("/system/http_proxy/use_http_proxy"), +- &masterProxySwitch); +- // if no proxy is set in GConf return NS_ERROR_FAILURE +- if (!(IsProxyMode("manual") || masterProxySwitch)) { +- return NS_ERROR_FAILURE; +- } +- +- nsCOMPtr ignoreList; +- if (NS_SUCCEEDED(mGConf->GetStringList( +- NS_LITERAL_CSTRING("/system/http_proxy/ignore_hosts"), +- getter_AddRefs(ignoreList))) && +- ignoreList) { +- uint32_t len = 0; +- ignoreList->GetLength(&len); +- for (uint32_t i = 0; i < len; ++i) { +- nsCOMPtr str = do_QueryElementAt(ignoreList, i); +- if (str) { +- nsAutoString s; +- if (NS_SUCCEEDED(str->GetData(s)) && !s.IsEmpty()) { +- if (HostIgnoredByProxy(NS_ConvertUTF16toUTF8(s), aHost)) { +- aResult.AppendLiteral("DIRECT"); +- return NS_OK; +- } +- } +- } +- } +- } +- +- bool useHttpProxyForAll = false; +- // This setting sometimes doesn't exist, don't bail on failure +- mGConf->GetBool(NS_LITERAL_CSTRING("/system/http_proxy/use_same_proxy"), +- &useHttpProxyForAll); +- +- nsresult rv; +- if (!useHttpProxyForAll) { +- rv = SetProxyResultFromGConf("/system/proxy/socks_", "SOCKS", aResult); +- if (NS_SUCCEEDED(rv)) return rv; +- } +- +- if (aScheme.LowerCaseEqualsLiteral("http") || useHttpProxyForAll) { +- rv = SetProxyResultFromGConf("/system/http_proxy/", "PROXY", aResult); +- } else if (aScheme.LowerCaseEqualsLiteral("https")) { +- rv = SetProxyResultFromGConf("/system/proxy/secure_", "PROXY", aResult); +- } else if (aScheme.LowerCaseEqualsLiteral("ftp")) { +- rv = SetProxyResultFromGConf("/system/proxy/ftp_", "PROXY", aResult); +- } else { +- rv = NS_ERROR_FAILURE; +- } +- +- return rv; +-} +- + nsresult nsUnixSystemProxySettings::GetProxyFromGSettings( + const nsACString& aScheme, const nsACString& aHost, int32_t aPort, + nsACString& aResult) { +@@ -494,7 +390,6 @@ nsresult nsUnixSystemProxySettings::GetP + nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult); + if (NS_SUCCEEDED(rv)) return rv; + } +- if (mGConf) return GetProxyFromGConf(aScheme, aHost, aPort, aResult); + + return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult); + } diff --git a/mozilla-526293.patch b/mozilla-526293.patch new file mode 100644 index 0000000..a03796a --- /dev/null +++ b/mozilla-526293.patch @@ -0,0 +1,14 @@ +diff -up firefox-60.6.0/widget/gtk/nsFilePicker.cpp.old firefox-60.6.0/widget/gtk/nsFilePicker.cpp +--- firefox-60.6.0/widget/gtk/nsFilePicker.cpp.old 2019-03-27 10:29:47.918560620 +0100 ++++ firefox-60.6.0/widget/gtk/nsFilePicker.cpp 2019-03-27 10:30:08.384491717 +0100 +@@ -366,9 +366,7 @@ nsFilePicker::Open(nsIFilePickerShownCal + // If we have --enable-proxy-bypass-protection, then don't allow + // remote URLs to be used. + #ifndef MOZ_PROXY_BYPASS_PROTECTION +- if (mAllowURLs) { +- gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(file_chooser), FALSE); +- } ++ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(file_chooser), FALSE); + #endif + + if (action == GTK_FILE_CHOOSER_ACTION_OPEN || diff --git a/thunderbird.spec b/thunderbird.spec index 05dfb4e..eb393bb 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -89,7 +89,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.6.1 -Release: 2%{?dist} +Release: 3%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -132,6 +132,9 @@ Patch311: firefox-wayland.patch Patch312: mozilla-1522780.patch # Upstream patches +Patch400: mozilla-1526243.patch +Patch401: mozilla-1540145.patch +Patch402: mozilla-526293.patch %if %{official_branding} # Required by Mozilla Corporation @@ -269,6 +272,10 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch311 -p1 -b .wayland %patch312 -p1 -b .1522780 +%patch400 -p1 -b .1526243 +%patch401 -p1 -b .1540145 +%patch402 -p1 -b .526293 + %if %{official_branding} # Required by Mozilla Corporation @@ -689,6 +696,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Apr 3 2019 Martin Stransky - 60.6.1-3 +- Added fixes for mozbz#1526243, mozbz#1540145, mozbz#526293 + * Tue Mar 26 2019 Martin Stransky - 60.6.1-2 - Added rawhide build fix From 5452cc1d74f4a5763c343175e0ed08a449ed5e82 Mon Sep 17 00:00:00 2001 From: Jason Tibbitts Date: Tue, 9 Apr 2019 17:55:09 -0500 Subject: [PATCH 050/402] Remove obsolete Group: tags. --- thunderbird.spec | 2 -- 1 file changed, 2 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index eb393bb..b6d47d4 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -92,7 +92,6 @@ Version: 60.6.1 Release: 3%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ -Group: Applications/Internet Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} Source1: thunderbird-langpacks-%{version}-20190325.tar.xz @@ -225,7 +224,6 @@ to run Thunderbird natively on Wayland. %global crashreporter_pkg_name mozilla-crashreporter-%{name}-debuginfo %package -n %{crashreporter_pkg_name} Summary: Debugging symbols used by Mozilla's crash reporter servers -Group: Development/Debug %description -n %{crashreporter_pkg_name} This package provides debug information for XULRunner, for use by Mozilla's crash reporter servers. If you are trying to locally From 1fdaf2db884a4de1d4623c04711c4b5482d91634 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Fri, 12 Apr 2019 09:29:27 +0200 Subject: [PATCH 051/402] Addef fix for mozbz#1508378 --- mozilla-1508378.patch | 55 +++++++++++++++++++++++++++++++++++++++++++ thunderbird.spec | 7 +++++- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 mozilla-1508378.patch diff --git a/mozilla-1508378.patch b/mozilla-1508378.patch new file mode 100644 index 0000000..127256e --- /dev/null +++ b/mozilla-1508378.patch @@ -0,0 +1,55 @@ +diff -up thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.cpp.1508378 thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.cpp +--- thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.cpp.1508378 2019-04-12 09:23:26.846503741 +0200 ++++ thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.cpp 2019-04-12 09:25:45.661937077 +0200 +@@ -567,6 +567,23 @@ static void WaylandBufferDelayCommitHand + } + } + ++void WindowSurfaceWayland::CalcRectScale(LayoutDeviceIntRect& aRect, int aScale) { ++ if (aRect.x & 0x1) { ++ aRect.width += 1; ++ } ++ aRect.x = aRect.x / aScale; ++ ++ if (aRect.y & 0x1) { ++ aRect.height += 1; ++ } ++ aRect.y = aRect.y / aScale; ++ ++ aRect.width = (aRect.width & 0x1) ? aRect.width / aScale + 1 : ++ aRect.width / aScale; ++ aRect.height = (aRect.height & 0x1) ? aRect.height / aScale + 1 : ++ aRect.height / aScale; ++} ++ + void WindowSurfaceWayland::CommitWaylandBuffer() { + MOZ_ASSERT(mPendingCommit, "Committing empty surface!"); + +@@ -617,11 +634,13 @@ void WindowSurfaceWayland::CommitWayland + gint scaleFactor = mWindow->GdkScaleFactor(); + for (auto iter = mWaylandBufferDamage.RectIter(); !iter.Done(); + iter.Next()) { +- const mozilla::LayoutDeviceIntRect& r = iter.Get(); ++ 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); ++ if (scaleFactor > 1) { ++ CalcRectScale(r, scaleFactor); ++ } ++ wl_surface_damage(waylandSurface, r.x, r.y, r.width, r.height); + } + } + +diff -up thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.h.1508378 thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.h +--- thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.h.1508378 2019-04-12 09:23:26.817503860 +0200 ++++ thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.h 2019-04-12 09:23:26.846503741 +0200 +@@ -101,6 +101,7 @@ class WindowSurfaceWayland : public Wind + const gfx::IntSize& aLockSize); + bool CommitImageSurfaceToWaylandBuffer(const LayoutDeviceIntRegion& aRegion); + void CommitWaylandBuffer(); ++ void CalcRectScale(LayoutDeviceIntRect& aRect, int scale); + + // TODO: Do we need to hold a reference to nsWindow object? + nsWindow* mWindow; diff --git a/thunderbird.spec b/thunderbird.spec index eb393bb..e6155bc 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -89,7 +89,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.6.1 -Release: 3%{?dist} +Release: 4%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -135,6 +135,7 @@ Patch312: mozilla-1522780.patch Patch400: mozilla-1526243.patch Patch401: mozilla-1540145.patch Patch402: mozilla-526293.patch +Patch403: mozilla-1508378.patch %if %{official_branding} # Required by Mozilla Corporation @@ -275,6 +276,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch400 -p1 -b .1526243 %patch401 -p1 -b .1540145 %patch402 -p1 -b .526293 +%patch403 -p1 -b .1508378 %if %{official_branding} # Required by Mozilla Corporation @@ -696,6 +698,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Fri Apr 12 2019 Martin Stransky - 60.6.1-4 +- Addef fix for mozbz#1508378 + * Wed Apr 3 2019 Martin Stransky - 60.6.1-3 - Added fixes for mozbz#1526243, mozbz#1540145, mozbz#526293 From 5dfec457dff5cfd0995cd09f06c6b74c7d900af6 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 7 May 2019 11:52:20 +0200 Subject: [PATCH 052/402] get-calendar-langpacks.sh: Fixed wrong version in calendar langpack manifest which prohibited the update of the langpack during startup. --- get-calendar-langpacks.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/get-calendar-langpacks.sh b/get-calendar-langpacks.sh index d3f5e86..854cae2 100755 --- a/get-calendar-langpacks.sh +++ b/get-calendar-langpacks.sh @@ -100,7 +100,7 @@ for lang in $LOCALES; do } }, "langpack_id": "$lang", - "version": "$LIGHTNING_VERSION$BUILD_ID", + "version": "7.$LIGHTNING_VERSION.$BUILD_ID", "name": "$lang Language Pack Calendar", "manifest_version": 2, "sources": { From 95a956f30d6c3a909cd5ba5552b0ed661909598c Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 15 May 2019 11:13:04 +0200 Subject: [PATCH 053/402] Fixed startup crashes (rhbz#1709373, rhbz#1685276, rhbz#1708611) --- firefox-wayland.patch | 17 +++++++++++++++-- thunderbird.spec | 7 ++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/firefox-wayland.patch b/firefox-wayland.patch index d08ae4c..ec42d9f 100644 --- a/firefox-wayland.patch +++ b/firefox-wayland.patch @@ -2956,7 +2956,7 @@ diff -up thunderbird-60.5.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.5.0/w + // 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); ++ // SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED); + } } #ifdef MOZ_WAYLAND @@ -3179,7 +3179,7 @@ diff -up thunderbird-60.5.0/widget/gtk/nsWindow.cpp.wayland thunderbird-60.5.0/w + g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)), "nsWindow", + this); +#ifdef MOZ_X11 -+ SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED); ++ // SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED); +#endif + RefreshWindowClass(); + @@ -4426,3 +4426,16 @@ diff -up thunderbird-60.5.0/widget/gtk/WindowSurfaceWayland.h.wayland thunderbir }; } // namespace widget +diff -up thunderbird-60.6.1/widget/gtk/WindowSurfaceProvider.cpp.old thunderbird-60.6.1/widget/gtk/WindowSurfaceProvider.cpp +--- thunderbird-60.6.1/widget/gtk/WindowSurfaceProvider.cpp.old 2019-05-14 21:11:50.219841534 +0200 ++++ thunderbird-60.6.1/widget/gtk/WindowSurfaceProvider.cpp 2019-05-14 21:11:58.228755117 +0200 +@@ -52,9 +52,6 @@ void WindowSurfaceProvider::Initialize(D + + #ifdef MOZ_WAYLAND + void WindowSurfaceProvider::Initialize(nsWindow* aWidget) { +- MOZ_ASSERT(aWidget->GetWaylandDisplay(), +- "We are supposed to have a Wayland display!"); +- + mWidget = aWidget; + mIsX11Display = false; + } diff --git a/thunderbird.spec b/thunderbird.spec index ff9b4a6..9f4b2d0 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -89,7 +89,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.6.1 -Release: 4%{?dist} +Release: 5%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -118,6 +118,7 @@ Patch226: rhbz-1354671.patch Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch Patch103: rhbz-1219542-s390-build.patch Patch104: mozilla-1533969.patch +Patch105: thunderbird-debug.patch # PPC fix Patch304: mozilla-1245783.patch @@ -243,6 +244,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch103 -p1 -b .rhbz-1219542-s390-build %endif %patch104 -p1 -b .1533969 +%patch105 -p1 -b .debug %patch304 -p1 -b .1245783 %patch309 -p1 -b .1460871-ldap-query @@ -696,6 +698,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* May Wed 15 2019 Martin Stransky - 60.6.1-5 +- Fixed startup crashes (rhbz#1709373, rhbz#1685276, rhbz#1708611) + * Fri Apr 12 2019 Martin Stransky - 60.6.1-4 - Addef fix for mozbz#1508378 From b6d472b5213fb7f3fd09cb7bf5f8add2ba045e56 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 15 May 2019 11:15:37 +0200 Subject: [PATCH 054/402] Fixed changelog --- thunderbird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 9f4b2d0..f05865e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -698,7 +698,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog -* May Wed 15 2019 Martin Stransky - 60.6.1-5 +* Wed May 15 2019 Martin Stransky - 60.6.1-5 - Fixed startup crashes (rhbz#1709373, rhbz#1685276, rhbz#1708611) * Fri Apr 12 2019 Martin Stransky - 60.6.1-4 From d3a2d2cb7eaf006802ddda9055c4527be6e4fe54 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 15 May 2019 11:23:15 +0200 Subject: [PATCH 055/402] Added missing patch --- thunderbird-debug.patch | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 thunderbird-debug.patch diff --git a/thunderbird-debug.patch b/thunderbird-debug.patch new file mode 100644 index 0000000..c502851 --- /dev/null +++ b/thunderbird-debug.patch @@ -0,0 +1,12 @@ +diff -up thunderbird-60.6.1/intl/locale/LocaleService.cpp.debug thunderbird-60.6.1/intl/locale/LocaleService.cpp +--- thunderbird-60.6.1/intl/locale/LocaleService.cpp.debug 2019-05-15 08:15:14.602872505 +0200 ++++ thunderbird-60.6.1/intl/locale/LocaleService.cpp 2019-05-15 08:15:53.717635322 +0200 +@@ -643,8 +643,6 @@ LocaleService::GetDefaultLocale(nsACStri + // just use our hard-coded default below. + GetGREFileContents("update.locale", &locale); + locale.Trim(" \t\n\r"); +- // This should never be empty. +- MOZ_ASSERT(!locale.IsEmpty()); + if (SanitizeForBCP47(locale, true)) { + mDefaultLocale.Assign(locale); + } From 8f0984234ade823403e69d1a152369b083aac31b Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 20 May 2019 09:51:05 +0200 Subject: [PATCH 056/402] Update to 60.7.0 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index beb9444..8222fc3 100644 --- a/.gitignore +++ b/.gitignore @@ -241,3 +241,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.6.1.source.tar.xz /lightning-langpacks-60.6.1.tar.xz /thunderbird-langpacks-60.6.1-20190325.tar.xz +/thunderbird-60.7.0.source.tar.xz +/thunderbird-langpacks-60.7.0-20190520.tar.xz +/lightning-langpacks-60.7.0.tar.xz diff --git a/sources b/sources index 6d142c9..8234363 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.6.1.source.tar.xz) = 78e96aeb235a07ea3f53c4212a764e9b92dacd0e5d5561e454008a56d165a1e235ed05a8ecdb77efecf80f4c7f7ba2cf7a682c775047d7c175dfb50a1d9a42d2 -SHA512 (lightning-langpacks-60.6.1.tar.xz) = 720c73fa44b4ab085c12f2a570f57d31878912696afaf936d155882622395480952cd10cf245c3b589d93227f57427e5ae6cb0878f706e877e10272abe78ed1e -SHA512 (thunderbird-langpacks-60.6.1-20190325.tar.xz) = da8cda7b4777658e461c71679785e2253c42cd8109b15c5232c3226261ad1be584fe8d89e5ebabf94d87de9d732388c67c195876cbf800a1a4ac0dcd7f381793 +SHA512 (thunderbird-60.7.0.source.tar.xz) = 60428b652bed985f463a6ebf765a384e3ef875b193a60e4b14de8bb96658adf471c7af0f0709d8edbbb014c7ab54f03ca72f2cea1b49cd05a49fe74c748d7328 +SHA512 (thunderbird-langpacks-60.7.0-20190520.tar.xz) = 62ac3ca761e7c637b4d0cad9ff24bbb4d34f5d92db91d8ffa408d5585eab5843c86b06bdbe6664fccbbc0248e2f3b66b96876350c3a428fc3ed639e9887b4c49 +SHA512 (lightning-langpacks-60.7.0.tar.xz) = 630a2a7642520ece42dc0c495bdf55078a1216ba52e5d6a108a60a75f0e71b6d904e80010fb32783b12b6a680eb4244d93c03a23d4c32dfbeefe964c3402c408 diff --git a/thunderbird.spec b/thunderbird.spec index f05865e..e281d42 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -88,13 +88,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.6.1 -Release: 5%{?dist} +Version: 60.7.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190325.tar.xz +Source1: thunderbird-langpacks-%{version}-20190520.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -698,6 +698,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Mon May 20 2019 Martin Stransky - 60.7.0-1 +- Update to 60.7.0 + * Wed May 15 2019 Martin Stransky - 60.6.1-5 - Fixed startup crashes (rhbz#1709373, rhbz#1685276, rhbz#1708611) From fd07a4007abbc86f98796c1400f7a98dfd36d5fc Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 20 May 2019 11:18:53 +0200 Subject: [PATCH 057/402] Removed obosoletted build patch --- rust-1.33-build.patch | 70 ------------------------------------------- thunderbird.spec | 2 -- 2 files changed, 72 deletions(-) delete mode 100644 rust-1.33-build.patch diff --git a/rust-1.33-build.patch b/rust-1.33-build.patch deleted file mode 100644 index 30da243..0000000 --- a/rust-1.33-build.patch +++ /dev/null @@ -1,70 +0,0 @@ -diff -up thunderbird-60.5.3/servo/components/style/gecko/regen_atoms.py.rust-1.33-build thunderbird-60.5.3/servo/components/style/gecko/regen_atoms.py ---- thunderbird-60.5.3/servo/components/style/gecko/regen_atoms.py.rust-1.33-build 2019-03-04 19:17:31.000000000 +0100 -+++ thunderbird-60.5.3/servo/components/style/gecko/regen_atoms.py 2019-03-13 15:05:58.965726109 +0100 -@@ -202,6 +202,7 @@ RULE_TEMPLATE = ('("{atom}") =>\n ' - ' }}}};') - - MACRO = ''' -+/// Returns a static atom by passing the literal string it represents. - #[macro_export] - macro_rules! atom {{ - {} -diff -up thunderbird-60.5.3/servo/components/style/gecko_string_cache/namespace.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style/gecko_string_cache/namespace.rs ---- thunderbird-60.5.3/servo/components/style/gecko_string_cache/namespace.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 -+++ thunderbird-60.5.3/servo/components/style/gecko_string_cache/namespace.rs 2019-03-13 15:05:58.966726107 +0100 -@@ -11,6 +11,7 @@ use std::fmt; - use std::ops::Deref; - use string_cache::{Atom, WeakAtom}; - -+/// Macro text - #[macro_export] - macro_rules! ns { - () => { $crate::string_cache::Namespace(atom!("")) }; -diff -up thunderbird-60.5.3/servo/components/style/properties/properties.mako.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style/properties/properties.mako.rs ---- thunderbird-60.5.3/servo/components/style/properties/properties.mako.rs.rust-1.33-build 2019-03-04 19:17:30.000000000 +0100 -+++ thunderbird-60.5.3/servo/components/style/properties/properties.mako.rs 2019-03-13 15:05:58.966726107 +0100 -@@ -55,6 +55,7 @@ use style_adjuster::StyleAdjuster; - - pub use self::declaration_block::*; - -+/// Generated - #[cfg(feature = "gecko")] - #[macro_export] - macro_rules! property_name { -@@ -3852,7 +3853,7 @@ impl fmt::Debug for AliasId { - } - } - --// NOTE(emilio): Callers are responsible to deal with prefs. -+/// Callers are responsible to deal with prefs. - #[macro_export] - macro_rules! css_properties_accessors { - ($macro_name: ident) => { -@@ -3875,6 +3876,7 @@ macro_rules! css_properties_accessors { - } - } - -+/// Neco - #[macro_export] - macro_rules! longhand_properties_idents { - ($macro_name: ident) => { -diff -up thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build thunderbird-60.5.3/servo/components/style_traits/values.rs ---- thunderbird-60.5.3/servo/components/style_traits/values.rs.rust-1.33-build 2019-03-04 19:17:27.000000000 +0100 -+++ thunderbird-60.5.3/servo/components/style_traits/values.rs 2019-03-13 15:37:34.077560034 +0100 -@@ -135,6 +135,7 @@ where - } - } - -+/// Neco - #[macro_export] - macro_rules! serialize_function { - ($dest: expr, $name: ident($( $arg: expr, )+)) => { -@@ -404,7 +405,7 @@ impl_to_css_for_predefined_type!(::csspa - impl_to_css_for_predefined_type!(::cssparser::Color); - impl_to_css_for_predefined_type!(::cssparser::UnicodeRange); - --#[macro_export] -+/// Define an enum type with unit variants that each correspond to a CSS keyword. - macro_rules! define_css_keyword_enum { - (pub enum $name:ident { $($variant:ident = $css:expr,)+ }) => { - #[allow(missing_docs)] diff --git a/thunderbird.spec b/thunderbird.spec index e281d42..b8cf833 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -109,7 +109,6 @@ Source28: thunderbird-wayland.sh.in Source29: thunderbird-wayland.desktop # Build patches -Patch1: rust-1.33-build.patch Patch9: mozilla-build-arm.patch Patch26: build-icu-big-endian.patch Patch37: build-jit-atomic-always-lucky.patch @@ -238,7 +237,6 @@ debug %{name}, you want to install %{name}-debuginfo instead. %setup -q # Build patches -%patch1 -p1 -b .rust-1.33-build %patch9 -p2 -b .arm %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build From 362c4c8e432d572310f8d584a2dac99d5a8371bc Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 20 May 2019 15:04:54 +0200 Subject: [PATCH 058/402] Added rust build patch --- rust-1.33-build.patch | 39 +++++++++++++++++++++++++++++++++++++++ thunderbird.spec | 2 ++ 2 files changed, 41 insertions(+) create mode 100644 rust-1.33-build.patch diff --git a/rust-1.33-build.patch b/rust-1.33-build.patch new file mode 100644 index 0000000..7fc4131 --- /dev/null +++ b/rust-1.33-build.patch @@ -0,0 +1,39 @@ +diff -up thunderbird-60.7.0/servo/components/style/gecko/regen_atoms.py.rust-1.33-build thunderbird-60.7.0/servo/components/style/gecko/regen_atoms.py +--- thunderbird-60.7.0/servo/components/style/gecko/regen_atoms.py.rust-1.33-build 2019-05-17 14:05:38.000000000 +0200 ++++ thunderbird-60.7.0/servo/components/style/gecko/regen_atoms.py 2019-05-20 15:01:06.284881858 +0200 +@@ -202,6 +202,7 @@ RULE_TEMPLATE = ('("{atom}") =>\n ' + ' }}}};') + + MACRO = ''' ++/// Returns a static atom by passing the literal string it represents. + #[macro_export] + macro_rules! atom {{ + {} +diff -up thunderbird-60.7.0/servo/components/style/properties/properties.mako.rs.rust-1.33-build thunderbird-60.7.0/servo/components/style/properties/properties.mako.rs +--- thunderbird-60.7.0/servo/components/style/properties/properties.mako.rs.rust-1.33-build 2019-05-17 14:05:38.000000000 +0200 ++++ thunderbird-60.7.0/servo/components/style/properties/properties.mako.rs 2019-05-20 15:01:06.286881852 +0200 +@@ -55,6 +55,7 @@ use style_adjuster::StyleAdjuster; + + pub use self::declaration_block::*; + ++/// Generated + #[cfg(feature = "gecko")] + #[macro_export] + macro_rules! property_name { +@@ -3852,7 +3853,7 @@ impl fmt::Debug for AliasId { + } + } + +-// NOTE(emilio): Callers are responsible to deal with prefs. ++/// Callers are responsible to deal with prefs. + #[macro_export] + macro_rules! css_properties_accessors { + ($macro_name: ident) => { +@@ -3875,6 +3876,7 @@ macro_rules! css_properties_accessors { + } + } + ++/// Neco + #[macro_export] + macro_rules! longhand_properties_idents { + ($macro_name: ident) => { diff --git a/thunderbird.spec b/thunderbird.spec index b8cf833..e281d42 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -109,6 +109,7 @@ Source28: thunderbird-wayland.sh.in Source29: thunderbird-wayland.desktop # Build patches +Patch1: rust-1.33-build.patch Patch9: mozilla-build-arm.patch Patch26: build-icu-big-endian.patch Patch37: build-jit-atomic-always-lucky.patch @@ -237,6 +238,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %setup -q # Build patches +%patch1 -p1 -b .rust-1.33-build %patch9 -p2 -b .arm %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build From 1fc071eddc33fe06019dff422e9efc28fe4a83e0 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 18 Jun 2019 13:21:52 +0200 Subject: [PATCH 059/402] Update to latest upstream version --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 8222fc3..4383944 100644 --- a/.gitignore +++ b/.gitignore @@ -244,3 +244,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.7.0.source.tar.xz /thunderbird-langpacks-60.7.0-20190520.tar.xz /lightning-langpacks-60.7.0.tar.xz +/thunderbird-60.7.1.source.tar.xz +/thunderbird-langpacks-60.7.1-20190618.tar.xz +/lightning-langpacks-60.7.1.tar.xz diff --git a/sources b/sources index 8234363..b178d30 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.7.0.source.tar.xz) = 60428b652bed985f463a6ebf765a384e3ef875b193a60e4b14de8bb96658adf471c7af0f0709d8edbbb014c7ab54f03ca72f2cea1b49cd05a49fe74c748d7328 -SHA512 (thunderbird-langpacks-60.7.0-20190520.tar.xz) = 62ac3ca761e7c637b4d0cad9ff24bbb4d34f5d92db91d8ffa408d5585eab5843c86b06bdbe6664fccbbc0248e2f3b66b96876350c3a428fc3ed639e9887b4c49 -SHA512 (lightning-langpacks-60.7.0.tar.xz) = 630a2a7642520ece42dc0c495bdf55078a1216ba52e5d6a108a60a75f0e71b6d904e80010fb32783b12b6a680eb4244d93c03a23d4c32dfbeefe964c3402c408 +SHA512 (thunderbird-60.7.1.source.tar.xz) = 181d4aec12bb7bb910e24b0cfbc6e909df7bc8b14833ae76add54f9f0aca9cb88b0f9d53d5c3cfd81f8a4f297b0ac8ba8025b1e7977382ca77aaaa7b50afd78a +SHA512 (thunderbird-langpacks-60.7.1-20190618.tar.xz) = dba8a7c760e9411578c08ac253750a4e77879f69e5fe86f33092b8963bc8a1658aeb03d75cbcb83ddac98dbec9fe356a49e394aa63005fb28a3344f6744a492b +SHA512 (lightning-langpacks-60.7.1.tar.xz) = bd3112e8d9c806a673cb8155b651bfa40069308386a78c13ba59807ce849d289659661bd3d75dc6a72c768151e119ca02382bdf557e1b68a6908a5d8e33b73e9 diff --git a/thunderbird.spec b/thunderbird.spec index e281d42..2fce018 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -88,13 +88,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.7.0 +Version: 60.7.1 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190520.tar.xz +Source1: thunderbird-langpacks-%{version}-20190618.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -698,6 +698,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Jun 18 2019 Jan Horak - 60.7.1-1 +- Update to 60.7.1 + * Mon May 20 2019 Martin Stransky - 60.7.0-1 - Update to 60.7.0 From 81a226f738a471d1d2b1c89fbc7aec3737d91260 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 20 Jun 2019 14:33:26 +0200 Subject: [PATCH 060/402] Update to 60.7.2 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 4383944..05d71ba 100644 --- a/.gitignore +++ b/.gitignore @@ -247,3 +247,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.7.1.source.tar.xz /thunderbird-langpacks-60.7.1-20190618.tar.xz /lightning-langpacks-60.7.1.tar.xz +/thunderbird-60.7.2.source.tar.xz +/thunderbird-langpacks-60.7.2-20190620.tar.xz +/lightning-langpacks-60.7.2.tar.xz diff --git a/sources b/sources index b178d30..356c6c9 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.7.1.source.tar.xz) = 181d4aec12bb7bb910e24b0cfbc6e909df7bc8b14833ae76add54f9f0aca9cb88b0f9d53d5c3cfd81f8a4f297b0ac8ba8025b1e7977382ca77aaaa7b50afd78a -SHA512 (thunderbird-langpacks-60.7.1-20190618.tar.xz) = dba8a7c760e9411578c08ac253750a4e77879f69e5fe86f33092b8963bc8a1658aeb03d75cbcb83ddac98dbec9fe356a49e394aa63005fb28a3344f6744a492b -SHA512 (lightning-langpacks-60.7.1.tar.xz) = bd3112e8d9c806a673cb8155b651bfa40069308386a78c13ba59807ce849d289659661bd3d75dc6a72c768151e119ca02382bdf557e1b68a6908a5d8e33b73e9 +SHA512 (thunderbird-60.7.2.source.tar.xz) = 20744857c1008c052a6c1ac8de4d83147f7ae247951b4dc91f9b9efaa628d9da7328618987e625b9d4aa9b55400d13ffb0f0766eb35f73de054cc019b93c6454 +SHA512 (thunderbird-langpacks-60.7.2-20190620.tar.xz) = 63ed2cda2e72430195776416dcb623722f2cdb63daef14cde1018a9d2303bdb34aae479784c53f75c4ae14adb8675f4aad52fbddbb8226639abe94d1f8a989f4 +SHA512 (lightning-langpacks-60.7.2.tar.xz) = 7f7d738d2b1bf9ca6af5ab34f6c8cf6cdd7258126e295667c60213e174e4b6f16a8c35ca7236fdaafa37c1ed2d340c5341aa744ec0379e6cc263a3dfc8a20b44 diff --git a/thunderbird.spec b/thunderbird.spec index 2fce018..a3ffe42 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -88,13 +88,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.7.1 +Version: 60.7.2 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190618.tar.xz +Source1: thunderbird-langpacks-%{version}-20190620.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -698,6 +698,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Jun 20 2019 Jan Horak - 60.7.2-1 +- Update to 60.7.2 + * Tue Jun 18 2019 Jan Horak - 60.7.1-1 - Update to 60.7.1 From 563569fe79287d0e3c440f62bd67d077842ace89 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 21 Jun 2019 17:22:22 +0200 Subject: [PATCH 061/402] Update to build 2 --- .gitignore | 1 + sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 05d71ba..89c8d12 100644 --- a/.gitignore +++ b/.gitignore @@ -250,3 +250,4 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.7.2.source.tar.xz /thunderbird-langpacks-60.7.2-20190620.tar.xz /lightning-langpacks-60.7.2.tar.xz +/thunderbird-langpacks-60.7.2-20190621.tar.xz diff --git a/sources b/sources index 356c6c9..857eea9 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.7.2.source.tar.xz) = 20744857c1008c052a6c1ac8de4d83147f7ae247951b4dc91f9b9efaa628d9da7328618987e625b9d4aa9b55400d13ffb0f0766eb35f73de054cc019b93c6454 -SHA512 (thunderbird-langpacks-60.7.2-20190620.tar.xz) = 63ed2cda2e72430195776416dcb623722f2cdb63daef14cde1018a9d2303bdb34aae479784c53f75c4ae14adb8675f4aad52fbddbb8226639abe94d1f8a989f4 -SHA512 (lightning-langpacks-60.7.2.tar.xz) = 7f7d738d2b1bf9ca6af5ab34f6c8cf6cdd7258126e295667c60213e174e4b6f16a8c35ca7236fdaafa37c1ed2d340c5341aa744ec0379e6cc263a3dfc8a20b44 +SHA512 (thunderbird-60.7.2.source.tar.xz) = e889bbc75a72a7063122f4e49b702d921a1795d59e63597b8f42da1665863cf925498acda44bfcb4328b183be3413dab5f1f51d96bf4b867156ac15b3fa3e712 +SHA512 (thunderbird-langpacks-60.7.2-20190621.tar.xz) = b8089252cf741d542fc3e4d215ddc15aebadbf0d63dd08798b3a18759c778d388e40fd349aaf4a9500f87e1d392328afe56b5415066bc4de6e5e3ab3a312302f +SHA512 (lightning-langpacks-60.7.2.tar.xz) = 287afc75b86db02c5fb8fb96b024d93821d4fa1b0c498588f1f541623f055b4e13021a43fe2a72292e136bf1a01da17a7569ea3ff22f727699c01f1144ee46cb diff --git a/thunderbird.spec b/thunderbird.spec index a3ffe42..9996fb2 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -89,12 +89,12 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.7.2 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190620.tar.xz +Source1: thunderbird-langpacks-%{version}-20190621.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -698,6 +698,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Fri Jun 21 2019 Jan Horak - 60.7.2-2 +- Update to 60.7.2 build 2 + * Thu Jun 20 2019 Jan Horak - 60.7.2-1 - Update to 60.7.2 From b5cb18a6062231dd3012103ad358104861b244f3 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 10 Jul 2019 20:27:15 +0200 Subject: [PATCH 062/402] update to 60.8.0 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 13 ++++++++----- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 89c8d12..90801e6 100644 --- a/.gitignore +++ b/.gitignore @@ -251,3 +251,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-langpacks-60.7.2-20190620.tar.xz /lightning-langpacks-60.7.2.tar.xz /thunderbird-langpacks-60.7.2-20190621.tar.xz +/thunderbird-60.8.0.source.tar.xz +/thunderbird-langpacks-60.8.0-20190704.tar.xz +/lightning-langpacks-60.8.0.tar.xz diff --git a/sources b/sources index 857eea9..bb7ac03 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.7.2.source.tar.xz) = e889bbc75a72a7063122f4e49b702d921a1795d59e63597b8f42da1665863cf925498acda44bfcb4328b183be3413dab5f1f51d96bf4b867156ac15b3fa3e712 -SHA512 (thunderbird-langpacks-60.7.2-20190621.tar.xz) = b8089252cf741d542fc3e4d215ddc15aebadbf0d63dd08798b3a18759c778d388e40fd349aaf4a9500f87e1d392328afe56b5415066bc4de6e5e3ab3a312302f -SHA512 (lightning-langpacks-60.7.2.tar.xz) = 287afc75b86db02c5fb8fb96b024d93821d4fa1b0c498588f1f541623f055b4e13021a43fe2a72292e136bf1a01da17a7569ea3ff22f727699c01f1144ee46cb +SHA512 (thunderbird-60.8.0.source.tar.xz) = b465544a8cbedf0aff0f737cf98e2d030331f1ea016b2e541dfe30a5cf3172f9075e5a9c8d6b7e0f97ffc2e0d3eebbaf9a39e76a499b9fc976bbc0c944dfd058 +SHA512 (thunderbird-langpacks-60.8.0-20190704.tar.xz) = 9613f678dde57ef2c99bf389a180a7c222472df74d935b80b49ab68e61cd36ad4950d7bad79fe11fdbbb728954b50297d80c4c4e422e4edfc0268fff012bf259 +SHA512 (lightning-langpacks-60.8.0.tar.xz) = 9ee5321810cc316e5d9725e6e43c95f24ab907a75962c1e78c9f24fe0eda421a4608f242018f1d52aa8fbc1d9be4a4e1e01cc707e0b8a9ae466505d0e3468fe2 diff --git a/thunderbird.spec b/thunderbird.spec index 9996fb2..73cf836 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -88,13 +88,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.7.2 -Release: 2%{?dist} +Version: 60.8.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190621.tar.xz +Source1: thunderbird-langpacks-%{version}-20190704.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -109,7 +109,7 @@ Source28: thunderbird-wayland.sh.in Source29: thunderbird-wayland.desktop # Build patches -Patch1: rust-1.33-build.patch +#Patch1: rust-1.33-build.patch Patch9: mozilla-build-arm.patch Patch26: build-icu-big-endian.patch Patch37: build-jit-atomic-always-lucky.patch @@ -238,7 +238,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %setup -q # Build patches -%patch1 -p1 -b .rust-1.33-build +#%patch1 -p1 -b .rust-1.33-build %patch9 -p2 -b .arm %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build @@ -698,6 +698,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Jul 10 2019 Martin Stransky - 60.8.0-1 +- Update to 60.8.0 + * Fri Jun 21 2019 Jan Horak - 60.7.2-2 - Update to 60.7.2 build 2 From 149d30b308a8e46ce895a4791d496dc33518cd70 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Thu, 11 Jul 2019 14:26:24 +0200 Subject: [PATCH 063/402] Add rust 1.35 fixes --- rust-1.33-build.patch | 36 ++++++++++++++++++++++-------------- thunderbird.spec | 4 ++-- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/rust-1.33-build.patch b/rust-1.33-build.patch index 7fc4131..746145f 100644 --- a/rust-1.33-build.patch +++ b/rust-1.33-build.patch @@ -1,22 +1,30 @@ -diff -up thunderbird-60.7.0/servo/components/style/gecko/regen_atoms.py.rust-1.33-build thunderbird-60.7.0/servo/components/style/gecko/regen_atoms.py ---- thunderbird-60.7.0/servo/components/style/gecko/regen_atoms.py.rust-1.33-build 2019-05-17 14:05:38.000000000 +0200 -+++ thunderbird-60.7.0/servo/components/style/gecko/regen_atoms.py 2019-05-20 15:01:06.284881858 +0200 -@@ -202,6 +202,7 @@ RULE_TEMPLATE = ('("{atom}") =>\n ' - ' }}}};') +diff -up thunderbird-60.8.0/servo/components/style_traits/values.rs.rust-1.33-build thunderbird-60.8.0/servo/components/style_traits/values.rs +--- thunderbird-60.8.0/servo/components/style_traits/values.rs.rust-1.33-build 2019-07-03 17:25:28.000000000 +0200 ++++ thunderbird-60.8.0/servo/components/style_traits/values.rs 2019-07-11 13:38:53.687318154 +0200 +@@ -135,6 +135,7 @@ where + } + } - MACRO = ''' -+/// Returns a static atom by passing the literal string it represents. ++/// Some comment #[macro_export] - macro_rules! atom {{ - {} -diff -up thunderbird-60.7.0/servo/components/style/properties/properties.mako.rs.rust-1.33-build thunderbird-60.7.0/servo/components/style/properties/properties.mako.rs ---- thunderbird-60.7.0/servo/components/style/properties/properties.mako.rs.rust-1.33-build 2019-05-17 14:05:38.000000000 +0200 -+++ thunderbird-60.7.0/servo/components/style/properties/properties.mako.rs 2019-05-20 15:01:06.286881852 +0200 + macro_rules! serialize_function { + ($dest: expr, $name: ident($( $arg: expr, )+)) => { +@@ -404,6 +405,7 @@ impl_to_css_for_predefined_type!(::csspa + impl_to_css_for_predefined_type!(::cssparser::Color); + impl_to_css_for_predefined_type!(::cssparser::UnicodeRange); + ++/// Some comment + #[macro_export] + macro_rules! define_css_keyword_enum { + (pub enum $name:ident { $($variant:ident = $css:expr,)+ }) => { +diff -up thunderbird-60.8.0/servo/components/style/properties/properties.mako.rs.old thunderbird-60.8.0/servo/components/style/properties/properties.mako.rs +--- thunderbird-60.8.0/servo/components/style/properties/properties.mako.rs.old 2019-07-11 14:22:51.393784701 +0200 ++++ thunderbird-60.8.0/servo/components/style/properties/properties.mako.rs 2019-07-11 14:24:03.182578100 +0200 @@ -55,6 +55,7 @@ use style_adjuster::StyleAdjuster; pub use self::declaration_block::*; -+/// Generated ++/// Neco #[cfg(feature = "gecko")] #[macro_export] macro_rules! property_name { @@ -25,7 +33,7 @@ diff -up thunderbird-60.7.0/servo/components/style/properties/properties.mako.rs } -// NOTE(emilio): Callers are responsible to deal with prefs. -+/// Callers are responsible to deal with prefs. ++/// NOTE(emilio): Callers are responsible to deal with prefs. #[macro_export] macro_rules! css_properties_accessors { ($macro_name: ident) => { diff --git a/thunderbird.spec b/thunderbird.spec index 73cf836..8a84488 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -109,7 +109,7 @@ Source28: thunderbird-wayland.sh.in Source29: thunderbird-wayland.desktop # Build patches -#Patch1: rust-1.33-build.patch +Patch1: rust-1.33-build.patch Patch9: mozilla-build-arm.patch Patch26: build-icu-big-endian.patch Patch37: build-jit-atomic-always-lucky.patch @@ -238,7 +238,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %setup -q # Build patches -#%patch1 -p1 -b .rust-1.33-build +%patch1 -p1 -b .rust-1.33-build %patch9 -p2 -b .arm %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build From 3f8a092a699e3128d137b4e327b9a705ec081f63 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 27 Jul 2019 01:24:41 +0000 Subject: [PATCH 064/402] - Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 8a84488..94fc335 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -89,7 +89,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 60.8.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -698,6 +698,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Sat Jul 27 2019 Fedora Release Engineering - 60.8.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + * Wed Jul 10 2019 Martin Stransky - 60.8.0-1 - Update to 60.8.0 From c65ef0279a3f5a54e71d774457de2495937208d1 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 3 Sep 2019 13:59:05 +0200 Subject: [PATCH 065/402] Update to 68.0 --- .gitignore | 3 + build-aarch64-skia.patch | 21 - build-disable-elfhack.patch | 16 +- build-jit-atomic-always-lucky.patch | 12 - firefox-SIOCGSTAMP.patch | 16 + firefox-wayland.patch | 4441 --------------------------- mozilla-1353817.patch | 27 +- mozilla-1460871-ldap-query.patch | 164 - mozilla-1508378.patch | 55 - mozilla-1522780.patch | 42 - mozilla-1526243.patch | 340 -- mozilla-1533969.patch | 18 - mozilla-1540145.patch | 168 - rust-1.33-build.patch | 47 - sources | 6 +- thunderbird-mozconfig | 2 - thunderbird.spec | 60 +- 17 files changed, 69 insertions(+), 5369 deletions(-) delete mode 100644 build-aarch64-skia.patch delete mode 100644 build-jit-atomic-always-lucky.patch create mode 100644 firefox-SIOCGSTAMP.patch delete mode 100644 firefox-wayland.patch delete mode 100644 mozilla-1460871-ldap-query.patch delete mode 100644 mozilla-1508378.patch delete mode 100644 mozilla-1522780.patch delete mode 100644 mozilla-1526243.patch delete mode 100644 mozilla-1533969.patch delete mode 100644 mozilla-1540145.patch delete mode 100644 rust-1.33-build.patch diff --git a/.gitignore b/.gitignore index 90801e6..f2a8d9c 100644 --- a/.gitignore +++ b/.gitignore @@ -254,3 +254,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-60.8.0.source.tar.xz /thunderbird-langpacks-60.8.0-20190704.tar.xz /lightning-langpacks-60.8.0.tar.xz +/thunderbird-68.0.source.tar.xz +/thunderbird-langpacks-68.0-20190829.tar.xz +/lightning-langpacks-68.0.tar.xz diff --git a/build-aarch64-skia.patch b/build-aarch64-skia.patch deleted file mode 100644 index b23296e..0000000 --- a/build-aarch64-skia.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up thunderbird-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia thunderbird-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp ---- thunderbird-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia 2018-08-28 14:36:13.555012053 +0200 -+++ thunderbird-60.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp 2018-08-28 14:38:17.160274150 +0200 -@@ -666,7 +666,7 @@ SI F approx_powf(F x, F y) { - } - - SI F from_half(U16 h) { --#if defined(JUMPER_IS_NEON) && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. -+#if 0 && defined(JUMPER_IS_NEON) && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. - return vcvt_f32_f16(h); - - #elif defined(JUMPER_IS_HSW) || defined(JUMPER_IS_AVX512) -@@ -686,7 +686,7 @@ SI F from_half(U16 h) { - } - - SI U16 to_half(F f) { --#if defined(JUMPER_IS_NEON) && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. -+#if 0 && defined(JUMPER_IS_NEON) && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. - return vcvt_f16_f32(f); - - #elif defined(JUMPER_IS_HSW) || defined(JUMPER_IS_AVX512) diff --git a/build-disable-elfhack.patch b/build-disable-elfhack.patch index 11e6a54..0856e5c 100644 --- a/build-disable-elfhack.patch +++ b/build-disable-elfhack.patch @@ -1,12 +1,12 @@ -diff -up firefox-62.0.2/toolkit/moz.configure.elfhack firefox-62.0.2/toolkit/moz.configure ---- firefox-62.0.2/toolkit/moz.configure.elfhack 2018-09-27 14:32:56.549507561 +0200 -+++ firefox-62.0.2/toolkit/moz.configure 2018-09-27 14:33:08.219532121 +0200 -@@ -1195,7 +1195,7 @@ with only_when(has_elfhack): - option('--disable-elf-hack', help='Disable elf hacks') +diff -up thunderbird-68.0/toolkit/moz.configure.elfhack thunderbird-68.0/toolkit/moz.configure +--- thunderbird-68.0/toolkit/moz.configure.elfhack 2019-08-29 16:33:28.491708653 +0200 ++++ thunderbird-68.0/toolkit/moz.configure 2019-08-29 16:33:58.019805525 +0200 +@@ -1130,7 +1130,7 @@ with only_when('--enable-compile-environ + help='{Enable|Disable} elf hacks') - set_config('USE_ELF_HACK', -- depends_if('--enable-elf-hack')(lambda _: True)) -+ depends_if('--enable-elf-hack')(lambda _: False)) + set_config('USE_ELF_HACK', +- depends_if('--enable-elf-hack')(lambda _: True)) ++ depends_if('--enable-elf-hack')(lambda _: False)) @depends(check_build_environment) diff --git a/build-jit-atomic-always-lucky.patch b/build-jit-atomic-always-lucky.patch deleted file mode 100644 index ab99524..0000000 --- a/build-jit-atomic-always-lucky.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up firefox-60.5.0/js/src/jit/AtomicOperations.h.jit-atomic-lucky firefox-60.5.0/js/src/jit/AtomicOperations.h ---- firefox-60.5.0/js/src/jit/AtomicOperations.h.jit-atomic-lucky 2019-01-22 10:20:27.993697161 +0100 -+++ firefox-60.5.0/js/src/jit/AtomicOperations.h 2019-01-22 10:23:15.337873762 +0100 -@@ -394,7 +394,7 @@ inline bool AtomicOperations::isLockfree - #elif defined(__s390__) || defined(__s390x__) - #include "jit/none/AtomicOperations-feeling-lucky.h" - #else --#error "No AtomicOperations support provided for this platform" -+#include "jit/none/AtomicOperations-feeling-lucky.h" - #endif - - #endif // jit_AtomicOperations_h diff --git a/firefox-SIOCGSTAMP.patch b/firefox-SIOCGSTAMP.patch new file mode 100644 index 0000000..673cb07 --- /dev/null +++ b/firefox-SIOCGSTAMP.patch @@ -0,0 +1,16 @@ +diff -up firefox-68.0/media/libyuv/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.old firefox-68.0/media/libyuv/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium +diff -up firefox-68.0/media/webrtc/trunk/Makefile.old firefox-68.0/media/webrtc/trunk/Makefile +diff -up firefox-68.0/media/webrtc/trunk/webrtc/rtc_base/physicalsocketserver.cc.old firefox-68.0/media/webrtc/trunk/webrtc/rtc_base/physicalsocketserver.cc +--- firefox-68.0/media/webrtc/trunk/webrtc/rtc_base/physicalsocketserver.cc.old 2019-07-10 20:10:04.420328534 +0200 ++++ firefox-68.0/media/webrtc/trunk/webrtc/rtc_base/physicalsocketserver.cc 2019-07-10 20:13:48.766658793 +0200 +@@ -62,6 +62,10 @@ typedef void* SockOptArg; + + #if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC) && !defined(WEBRTC_BSD) && !defined(__native_client__) + ++#ifndef SIOCGSTAMP ++#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ ++#endif ++ + int64_t GetSocketRecvTimestamp(int socket) { + struct timeval tv_ioctl; + int ret = ioctl(socket, SIOCGSTAMP, &tv_ioctl); diff --git a/firefox-wayland.patch b/firefox-wayland.patch deleted file mode 100644 index ec42d9f..0000000 --- a/firefox-wayland.patch +++ /dev/null @@ -1,4441 +0,0 @@ -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; -- XGetWindowAttributes(mXDisplay, mXWindow, &windowAttrs); -+ if (!XGetWindowAttributes(mXDisplay, mXWindow, &windowAttrs)) { -+ NS_WARNING("GtkCompositorWidget(): XGetWindowAttributes() failed!"); -+ } - - 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 += [ -+ '/layout/base', - '/layout/generic', - '/layout/xul', - '/other-licenses/atk-1.0', -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 -+#ifdef MOZ_WAYLAND -+#include "nsWaylandDisplay.h" -+#include - #endif - #include - #include -@@ -19,12 +20,20 @@ - #include "maiRedundantObjectFactory.h" - #endif - -+#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); - - /* 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); -+ -+ 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)); -+ return (*sGdkWindowGetScaleFactorPtr)(window); -+ } -+ -+ return 1; -+} - #endif - - 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 - }; - -@@ -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); -+ -+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.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) -+STUB(gdk_x11_screen_get_screen_number) -+STUB(gdk_x11_screen_lookup_visual) - STUB(gdk_x11_screen_supports_net_wm_hint) - STUB(gdk_x11_visual_get_xvisual) - STUB(gdk_x11_window_foreign_new_for_display) -@@ -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) -+STUB(gtk_im_multicontext_get_context_id) - STUB(gtk_im_multicontext_get_type) - STUB(gtk_im_multicontext_new) - STUB(gtk_info_bar_get_type) -@@ -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; - } - -+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_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; -+} -+ -+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); -+} -+ -+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() { - } - } - --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" - -@@ -31,15 +33,43 @@ - #include - #include - #include --#include --#include - #include - --#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); -+ if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) -+ actions = GdkDragAction(actions | GDK_ACTION_MOVE); -+ -+ return actions; -+} -+ -+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)) -+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; -+ if (action & GDK_ACTION_MOVE) -+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; -+ -+ 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)); -+ -+ gpointer user_data = nullptr; -+ gdk_window_get_user_data(gdkParentWindow, &user_data); -+ -+ return GTK_WIDGET(user_data); -+} -+ - 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; - - 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); -+} -+ -+/* We follow logic of gdk_wayland_drag_context_commit_status()/gdkdnd-wayland.c -+ * here. -+ */ -+void WaylandDataOffer::SetDragStatus(GdkDragAction aAction, uint32_t aTime) { -+ uint32_t dnd_actions = gdk_to_wl_actions(aAction); -+ uint32_t all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | -+ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; -+ -+ wl_data_offer_set_actions(mWaylandDataOffer, all_actions, dnd_actions); -+ -+ /* Workaround Wayland D&D architecture here. To get the data_device_drop() -+ signal (which routes to nsDragService::GetData() call) we need to -+ accept at least one mime type before data_device_leave(). -+ -+ Real wl_data_offer_accept() for actualy requested data mime type is -+ called from nsDragService::GetData(). -+ */ -+ if (mTargetMIMETypes[0]) { -+ wl_data_offer_accept(mWaylandDataOffer, aTime, -+ gdk_atom_name(mTargetMIMETypes[0])); -+ } -+} -+ -+void WaylandDataOffer::SetSelectedDragAction(uint32_t aWaylandAction) { -+ mSelectedDragAction = aWaylandAction; -+} -+ -+GdkDragAction WaylandDataOffer::GetSelectedDragAction() { -+ return wl_to_gdk_actions(mSelectedDragAction); -+} -+ -+void WaylandDataOffer::SetAvailableDragActions(uint32_t aWaylandActions) { -+ mAvailableDragAction = aWaylandActions; -+} -+ -+GdkDragAction WaylandDataOffer::GetAvailableDragActions() { -+ return wl_to_gdk_actions(mAvailableDragAction); -+} -+ - static void data_offer_offer(void *data, struct wl_data_offer *wl_data_offer, - 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) {} -+ 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) {} -+ uint32_t dnd_action) { -+ auto *offer = static_cast(data); -+ offer->SetSelectedDragAction(dnd_action); -+} - - /* wl_data_offer callback description: - * - * data_offer_offer - Is called for each MIME type available at wl_data_offer. -- * data_offer_source_actions - Exposes all available D&D actions. -- * data_offer_action - Expose one actually selected D&D action. -+ * data_offer_source_actions - This event indicates the actions offered by -+ * the data source. -+ * data_offer_action - This event indicates the action selected by -+ * the compositor after matching the source/destination -+ * side actions. - */ --static const struct wl_data_offer_listener data_offer_listener = { -+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, -+ wl_display *aDisplay) -+ : mDataOffer(aDataOffer), -+ mDisplay(aDisplay), -+ mTime(0), -+ mGtkWidget(nullptr), -+ mX(0), -+ mY(0) {} -+ -+void nsWaylandDragContext::DropDataEnter(GtkWidget *aGtkWidget, uint32_t aTime, -+ nscoord aX, nscoord aY) { -+ mTime = aTime; -+ mGtkWidget = aGtkWidget; -+ mX = aX; -+ mY = aY; -+} -+ -+void nsWaylandDragContext::DropMotion(uint32_t aTime, nscoord aX, nscoord aY) { -+ mTime = aTime; -+ mX = aX; -+ mY = aY; -+} -+ -+void nsWaylandDragContext::GetLastDropInfo(uint32_t *aTime, nscoord *aX, -+ nscoord *aY) { -+ *aTime = mTime; -+ *aX = mX; -+ *aY = mY; -+} -+ -+void nsWaylandDragContext::SetDragStatus(GdkDragAction aAction) { -+ mDataOffer->SetDragStatus(aAction, mTime); -+} -+ -+GdkDragAction nsWaylandDragContext::GetSelectedDragAction() { -+ GdkDragAction gdkAction = mDataOffer->GetSelectedDragAction(); -+ -+ // We emulate gdk_drag_context_get_actions() here. -+ if (!gdkAction) { -+ gdkAction = mDataOffer->GetAvailableDragActions(); -+ } -+ -+ return gdkAction; -+} -+ -+GList *nsWaylandDragContext::GetTargets() { -+ int targetNums; -+ GdkAtom *atoms = mDataOffer->GetTargets(&targetNums); -+ -+ GList *targetList = nullptr; -+ for (int i = 0; i < targetNums; i++) { -+ targetList = g_list_append(targetList, GDK_ATOM_TO_POINTER(atoms[i])); -+ } -+ -+ return targetList; -+} -+ -+char *nsWaylandDragContext::GetData(const char *aMimeType, -+ uint32_t *aContentLength) { -+ mDataOffer->DragOfferAccept(aMimeType, mTime); -+ return mDataOffer->GetData(mDisplay, aMimeType, aContentLength); -+} -+ -+void nsRetrievalContextWayland::RegisterNewDataOffer( - wl_data_offer *aWaylandDataOffer) { - DataOffer *dataOffer = static_cast( - g_hash_table_lookup(mActiveOffers, aWaylandDataOffer)); -+ MOZ_ASSERT( -+ dataOffer == nullptr, -+ "Registered WaylandDataOffer already exists. Wayland protocol error?"); -+ - if (!dataOffer) { - dataOffer = new WaylandDataOffer(aWaylandDataOffer); - g_hash_table_insert(mActiveOffers, aWaylandDataOffer, dataOffer); - } - } - --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); -@@ -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; -+ -+ // 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::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)); - 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; -+} -+ -+void nsRetrievalContextWayland::ClearDragAndDropDataOffer(void) { -+ mDragContext = nullptr; - } - - // We have a new fresh data content. -@@ -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. -@@ -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(); -+ -+ 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)); -+ -+ 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) {} -+ nsWaylandDragContext *dropContext = context->GetDragContext(); -+ WindowDragLeaveHandler(dropContext->GetWidget()); -+ -+ context->ClearDragAndDropDataOffer(); -+} - - 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(); - --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); -+ -+ WindowDragMotionHandler(dropContext->GetWidget(), nullptr, dropContext, x, y, -+ time); -+} -+ -+static void data_device_drop(void *data, struct wl_data_device *data_device) { -+ nsRetrievalContextWayland *context = -+ static_cast(data); -+ -+ 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: - * -@@ -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 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. -+ * -+ * 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, -@@ -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_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, --}; -- --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); -- } else if (mKeyboard && !(caps & WL_SEAT_CAPABILITY_KEYBOARD)) { -- 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 const struct wl_seat_listener seat_listener = { -- seat_handle_capabilities, --}; -- --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 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()); -+#endif -+ delete static_cast(aDataOffer); -+ return true; -+} -+ - nsRetrievalContextWayland::~nsRetrievalContextWayland(void) { -+ g_hash_table_foreach_remove(mActiveOffers, offer_hash_remove, nullptr); - g_hash_table_destroy(mActiveOffers); -+ WaylandDisplayRelease(mDisplay); - } - - 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 { -- mClipboardData = -- dataOffer->GetData(mDisplay, aMimeType, &mClipboardDataLength); -+ mClipboardData = dataOffer->GetData(mDisplay->GetDisplay(), aMimeType, -+ &mClipboardDataLength); - } - } - -@@ -588,7 +736,7 @@ const char *nsRetrievalContextWayland::G - (selection == GDK_SELECTION_PRIMARY) ? mPrimaryOffer : mClipboardOffer; - if (!dataOffer) return nullptr; - -- 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; - }; - - 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: - virtual ~WaylandDataOffer(); -+ -+ private: - bool RequestDataTransfer(const char* aMimeType, int fd) override; - - wl_data_offer* mWaylandDataOffer; -+ uint32_t mSelectedDragAction; -+ uint32_t mAvailableDragAction; - }; - - 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; - - gtk_primary_selection_offer* mPrimaryDataOffer; - }; - -+class nsWaylandDragContext : public nsISupports { -+ NS_DECL_ISUPPORTS -+ -+ 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 SetDragStatus(GdkDragAction action); -+ GdkDragAction GetSelectedDragAction(); -+ -+ GtkWidget* GetWidget() { return mGtkWidget; } -+ GList* GetTargets(); -+ char* GetData(const char* aMimeType, uint32_t* aContentLength); -+ -+ private: -+ virtual ~nsWaylandDragContext(){}; -+ -+ nsAutoPtr mDataOffer; -+ wl_display* mDisplay; -+ uint32_t mTime; -+ GtkWidget* mGtkWidget; -+ nscoord mX, mY; -+}; -+ - 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 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 ConfigureKeyboard(wl_seat_capability caps); - void TransferFastTrackClipboard(int aClipboardRequestNumber, - GtkSelectionData* aSelectionData); - -- 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; - - 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" --#include "nsISelection.h" - #include "nsViewManager.h" - #include "nsIFrame.h" - #include "nsGtkUtils.h" -@@ -43,10 +43,15 @@ - #include "gfxPlatform.h" - #include "ScreenHelperGTK.h" - #include "nsArrayUtils.h" -+#ifdef MOZ_WAYLAND -+#include "nsClipboardWayland.h" -+#endif - - using namespace mozilla; - using namespace mozilla::gfx; - -+#define NS_SYSTEMINFO_CONTRACTID "@mozilla.org/system-info;1" -+ - // This sets how opaque the drag image is - #define DRAG_IMAGE_ALPHA_LEVEL 0.5 - -@@ -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 -+ , -+ mPendingWaylandDragContext(nullptr), -+ mTargetWaylandDragContext(nullptr) -+#endif -+{ - // 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 -+ - 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); -+} -+#endif -+ - 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; -+#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 -@@ -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(); -+ } - } -+#ifdef MOZ_WAYLAND -+ else { -+ mTargetDragData = mTargetWaylandDragContext->GetData(gdk_atom_name(aFlavor), -+ &mTargetDragDataLen); -+ mTargetDragDataReceived = true; -+ } -+#endif - MOZ_LOG(sDragLm, LogLevel::Debug, ("finished inner iteration\n")); - } - -@@ -1218,6 +1304,10 @@ void nsDragService::SourceEndDragSession - // this just releases the list of data items that we provide - mSourceDataItems = nullptr; - -+ // 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 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. - --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); - } - - 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"); - } - } - --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 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; -+#endif - mPendingWindowPoint = aWindowPoint; - mPendingTime = aTime; - -@@ -1717,6 +1814,9 @@ gboolean nsDragService::RunScheduledTask - // succeeed. - mTargetWidget = mTargetWindow->GetMozContainerWidget(); - mTargetDragContext.steal(mPendingDragContext); -+#ifdef MOZ_WAYLAND -+ mTargetWaylandDragContext = mPendingWaylandDragContext.forget(); -+#endif - mTargetTime = mPendingTime; - - // 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; -+#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 - } - } - } -@@ -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) { -+ 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 -+ mTargetWaylandDragContext = nullptr; -+#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 -@@ -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; - } -+#ifdef MOZ_WAYLAND -+ else if (mTargetWaylandDragContextForRemote) { -+ ReplyToDragMotion(mTargetWaylandDragContextForRemote); -+ mTargetWaylandDragContextForRemote = nullptr; -+ } -+#endif - return NS_OK; - } - -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 - - class nsWindow; -+class nsWaylandDragContext; - - namespace mozilla { - namespace gfx { -@@ -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, - mozilla::LayoutDeviceIntPoint aWindowPoint, - guint aTime); - -@@ -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; -+#endif - guint mPendingTime; - - // 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; -+#endif - // mTargetDragContextForRemote is set while waiting for a reply from - // a child process. - nsCountedRef mTargetDragContextForRemote; -+#ifdef MOZ_WAYLAND -+ RefPtr mTargetWaylandDragContextForRemote; -+#endif - guint mTargetTime; - - // 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); - - // 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); -+#endif - gboolean DispatchDropEvent(); - static uint32_t GetCurrentModifiers(); - }; -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" - -+#ifdef MOZ_WAYLAND -+#include -+#endif -+ - namespace mozilla { - namespace widget { - -@@ -200,7 +204,11 @@ void KeymapWrapper::Init() { - mModifierKeys.Clear(); - memset(mModifierMasks, 0, sizeof(mModifierMasks)); - -- 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(); -+#endif - - gdk_window_add_filter(nullptr, FilterEvents, this); - -@@ -276,9 +284,9 @@ void KeymapWrapper::InitXKBExtension() { - ("%p InitXKBExtension, Succeeded", this)); - } - --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 = 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"); -+ -+ 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(); -+ -+ // 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"); -+ -+ 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); -+ 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 const struct wl_keyboard_listener keyboard_listener = { -+ 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; -+ -+ 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, -+}; -+ -+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 const struct wl_registry_listener keyboard_registry_listener = { -+ 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); -+} -+#endif -+ - 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.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 - #include -+#ifdef MOZ_WAYLAND -+#include -+#include -+#endif - - namespace mozilla { - namespace widget { -@@ -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); -+#endif -+ - /** - * 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(); -+#endif - - /** - * 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); -+#endif - }; - - } // 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" -+#include "nsCSSColorUtils.h" - -+using namespace mozilla; - using mozilla::LookAndFeel; - - #define GDK_COLOR_TO_NS_RGB(c) \ -@@ -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); -+ return NS_OK; -+} -+ - 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; -@@ -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; -+ case eColorID__moz_cellhighlight: -+ aColor = mMozCellHighlightBackground; -+ break; -+ case eColorID__moz_cellhighlighttext: -+ aColor = mMozCellHighlightText; -+ break; - case eColorID_Widget3DHighlight: - 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(); -+ - // 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 - -+#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(); - }; - - #endif -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/. */ -+ -+#include "nsWaylandDisplay.h" -+ -+#include "base/message_loop.h" // for MessageLoop -+#include "base/task.h" // for NewRunnableMethod, etc -+#include "mozilla/StaticMutex.h" -+ -+namespace mozilla { -+namespace widget { -+ -+#define MAX_DISPLAY_CONNECTIONS 2 -+ -+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; -+} -+ -+nsWaylandDisplay *WaylandDisplayGet(GdkDisplay *aGdkDisplay) { -+ if (!aGdkDisplay) { -+ aGdkDisplay = 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(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; -+ } -+ } -+ MOZ_ASSERT(false, "Missing nsWaylandDisplay for this thread!"); -+ return false; -+} -+ -+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: -+ */ -+/* 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; -+}; -+ -+nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay = nullptr); -+void WaylandDisplayRelease(nsWaylandDisplay* aDisplay); -+ -+} // namespace widget -+} // namespace mozilla -+ -+#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" - #include "mozilla/WidgetUtils.h" -+#include "mozilla/dom/WheelEventBinding.h" - #include - - #include "GeckoProfiler.h" -@@ -25,13 +26,15 @@ - #include "prlink.h" - #include "nsGTKToolkit.h" - #include "nsIRollupListener.h" --#include "nsIDOMNode.h" -+#include "nsINode.h" - - #include "nsWidgetsCID.h" - #include "nsDragService.h" - #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 -+#include "nsView.h" - #endif - - #include "nsGkAtoms.h" -@@ -116,6 +120,7 @@ using namespace mozilla::widget; - #include "mozilla/layers/CompositorThread.h" - - #ifdef MOZ_X11 -+#include "GLContextGLX.h" // for GLContextGLX::FindVisual() - #include "GtkCompositorWidget.h" - #include "gfxXlibSurface.h" - #include "WindowSurfaceX11Image.h" -@@ -129,8 +134,6 @@ using namespace mozilla::widget; - #include "nsShmImage.h" - #include "gtkdrawing.h" - --#include "nsIDOMWheelEvent.h" -- - #include "NativeKeyBindings.h" - - #include -@@ -140,6 +143,7 @@ using namespace mozilla::gfx; - using namespace mozilla::widget; - using namespace mozilla::layers; - using mozilla::gl::GLContext; -+using mozilla::gl::GLContextGLX; - - // Don't put more than this many rects in the dirty region, just fluff - // out to the bounding-box if there are more -@@ -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_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK | -+ GDK_FOCUS_CHANGE_MASK; - - /* utility functions */ -+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 - } - - 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. -@@ -639,9 +644,6 @@ void nsWindow::Destroy() { - - ClearCachedResources(); - -- 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; - } - -@@ -774,7 +782,7 @@ void nsWindow::SetParent(nsIWidget *aNew - bool nsWindow::WidgetTypeSupportsAcceleration() { return !IsSmallPopup(); } - - void nsWindow::ReparentNativeWidget(nsIWidget *aNewParent) { -- NS_PRECONDITION(aNewParent, ""); -+ MOZ_ASSERT(aNewParent, "null widget"); - NS_ASSERTION(!mIsDestroyed, ""); - NS_ASSERTION(!static_cast(aNewParent)->mIsDestroyed, ""); - -@@ -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 -+ if (mContainer && !mContainer->ready_to_draw) return FALSE; -+#endif - - 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 & -@@ -3075,6 +3111,7 @@ void nsWindow::OnDPIChanged() { - // Update menu's font size etc - presShell->ThemeChanged(); - } -+ mWidgetListener->UIResolutionChanged(); - } - } - -@@ -3443,13 +3480,15 @@ nsresult nsWindow::Create(nsIWidget *aPa - gtk_style_context_has_class(style, "csd"); - eventWidget = (drawToContainer) ? container : mShell; - -- 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); - -+ 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); - - 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::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); -+ } -+#endif /* MOZ_X11 */ -+} -+ - 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; - -@@ -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); -- gdk_window_set_role(gdkWindow, role); -- --#ifdef MOZ_X11 -- if (mIsX11Display) { -- 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); -+ -+ RefreshWindowClass(); - } - - void nsWindow::NativeResize() { -@@ -3820,6 +3875,8 @@ void nsWindow::NativeMoveResize() { - NativeShow(false); - } - NativeMove(); -+ -+ return; - } - - 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 -+ - 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. -@@ -6351,34 +6450,19 @@ int32_t nsWindow::RoundsWidgetCoordinate - - 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) { -+ XFlush(mXDisplay); -+ } -+ - *aInitData = mozilla::widget::GtkCompositorWidgetInitData( - (mXWindow != X11None) ? mXWindow : (uintptr_t) nullptr, - mXDisplay ? nsCString(XDisplayString(mXDisplay)) : nsCString(), - GetClientSize()); - } - --bool nsWindow::IsComposited() const { -- if (!mGdkWindow) { -- NS_WARNING("nsWindow::HasARGBVisual called before realization!"); -- return false; -- } -- -- GdkScreen *gdkScreen = gdk_screen_get_default(); -- return gdk_screen_is_composited(gdkScreen) && -- (gdk_window_get_visual(mGdkWindow) == -- gdk_screen_get_rgba_visual(gdkScreen)); --} -- - #ifdef MOZ_WAYLAND --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 -+/* XApp progress support currently works by setting a property -+ * on a window with this Atom name. A supporting window manager -+ * will notice this and pass it along to whatever handling has -+ * been implemented on that end (e.g. passing it on to a taskbar -+ * widget.) There is no issue if WM support is lacking, this is -+ * simply ignored in that case. -+ * -+ * See https://github.com/linuxmint/xapps/blob/master/libxapp/xapp-gtk-window.c -+ * for further details. -+ */ -+ -+#define PROGRESS_HINT "_NET_WM_XAPP_PROGRESS" -+ -+static void set_window_hint_cardinal(Window xid, const gchar *atom_name, -+ gulong cardinal) { -+ GdkDisplay *display; -+ -+ 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)); -+ } -+} -+#endif // MOZ_X11 -+ -+void nsWindow::SetProgress(unsigned long progressPercent) { -+#ifdef MOZ_X11 -+ -+ if (!mIsX11Display) { -+ return; -+ } -+ -+ if (!mShell) { -+ return; -+ } -+ -+ progressPercent = MIN(progressPercent, 100); -+ -+ set_window_hint_cardinal(GDK_WINDOW_XID(gtk_widget_get_window(mShell)), -+ PROGRESS_HINT, progressPercent); -+#endif // MOZ_X11 -+} -+ -+#ifdef MOZ_X11 -+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.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); -+#endif -+ - class gfxPattern; - - namespace mozilla { -@@ -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; - -@@ -216,6 +228,8 @@ class nsWindow final : public nsBaseWidg - mozilla::gfx::DrawTarget* aDrawTarget, - LayoutDeviceIntRegion& aInvalidRegion) override; - -+ void SetProgress(unsigned long progressPercent); -+ - 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; - - void UpdateClientOffsetForCSDWindow(); - - 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; -+ -+ void SetCompositorHint(WindowComposeRequest aState); -+#endif -+ nsCString mGtkWindowTypeName; -+ nsCString mGtkWindowRoleName; -+ void RefreshWindowClass(); -+ - 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 "X11UndefineNone.h" - - class nsWindow; - -@@ -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) -- --// 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; - - 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; - } - --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)) { - Resize(aSourceBuffer->mWidth, aSourceBuffer->mHeight); - } -@@ -478,204 +311,381 @@ bool WindowBackBuffer::SetImageDataFromB - return true; - } - --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, mWaylandDisplay->GetSurfaceFormat()); -+ static_cast(mShmPool.GetImageData()), lockSize, -+ BUFFER_BPP * mWidth, mFormat); - } - --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) { -+ NS_WARNING("Deleted WindowSurfaceWayland with a pending commit!"); -+ } -+ -+ if (mDelayedCommitHandle) { -+ // Delete reference to this to prevent WaylandBufferDelayCommitHandler() -+ // operate on released this. mDelayedCommitHandle itself will -+ // be released at WaylandBufferDelayCommitHandler(). -+ *mDelayedCommitHandle = nullptr; -+ } - - if (mFrameCallback) { - wl_callback_destroy(mFrameCallback); - } - -+ delete mWaylandBuffer; -+ -+ 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 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()); -- } --} -- --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); -+ return mWaylandBuffer; - } - -- if (!mFrontBuffer->IsAttached()) { -- if (!mFrontBuffer->IsMatchingSize(aWidth, aHeight)) { -- mFrontBuffer->Resize(aWidth, aHeight); -+ if (!mWaylandBuffer->IsAttached()) { -+ if (!mWaylandBuffer->IsMatchingSize(aWidth, aHeight)) { -+ mWaylandBuffer->Resize(aWidth, aHeight); - // There's a chance that scale factor has been changed - // 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; - } - -- // Front buffer is used by compositor, draw to back buffer -- if (mBackBuffer->IsAttached()) { -+ if (MOZ_UNLIKELY(availableBuffer == BACK_BUFFER_NUM)) { - NS_WARNING("No drawing buffer available"); - return nullptr; - } - -- MOZ_ASSERT(!mDelayedCommit, -- "Uncommitted buffer switch, screen artifacts ahead."); -- -- WindowBackBuffer *tmp = mFrontBuffer; -- mFrontBuffer = mBackBuffer; -- mBackBuffer = tmp; -+ WindowBackBuffer* lastWaylandBuffer = mWaylandBuffer; -+ mWaylandBuffer = mBackupBuffer[availableBuffer]; -+ mBackupBuffer[availableBuffer] = lastWaylandBuffer; - -- if (mBackBuffer->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(lastWaylandBuffer); - // When buffer switches we need to damage whole screen - // (https://bugzilla.redhat.com/show_bug.cgi?id=1418260) -- mFullScreenDamage = true; -+ mWaylandBufferFullScreenDamage = true; - } else { - // Former buffer has different size from the new request. Only resize - // the new buffer and leave gecko to render new whole content. -- mFrontBuffer->Resize(aWidth, aHeight); -+ mWaylandBuffer->Resize(aWidth, aHeight); - } - -- return mFrontBuffer; -+ return mWaylandBuffer; - } - --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(WindowBackBuffer::GetSurfaceFormat())); -+ if (mImageSurface->CairoStatus()) { -+ return nullptr; -+ } -+ } -+ -+ 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: -+ -+ A) Lock() is called to whole surface. In that case we don't need -+ to clip/buffer the drawing and we can return wl_buffer directly -+ for drawing. -+ - mWaylandBuffer is available - that's an ideal situation. -+ - mWaylandBuffer is locked by compositor - flip buffers and draw. -+ - if we can't flip buffers - go B) -+ -+ 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) { - MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); - -- 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); -+ -+ if (mDrawToWaylandBufferDirectly) { -+ RefPtr dt = -+ LockWaylandBuffer(screenRect.width, screenRect.height, -+ mWindow->WaylandSurfaceNeedsClear()); -+ if (dt) { -+ return dt.forget(); -+ } -+ -+ // We don't have any front buffer available. Try indirect drawing -+ // to mImageSurface which is mirrored to front buffer at commit. -+ mDrawToWaylandBufferDirectly = false; -+ } -+ -+ return LockImageSurface(lockSize); -+} -+ -+bool WindowSurfaceWayland::CommitImageSurfaceToWaylandBuffer( -+ const LayoutDeviceIntRegion& aRegion) { -+ MOZ_ASSERT(!mDrawToWaylandBufferDirectly); -+ -+ LayoutDeviceIntRect screenRect = mWindow->GetBounds(); -+ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); -+ -+ gfx::Rect rect(bounds); -+ if (rect.IsEmpty()) { -+ return false; -+ } -+ -+ RefPtr dt = LockWaylandBuffer( -+ screenRect.width, screenRect.height, mWindow->WaylandSurfaceNeedsClear()); -+ RefPtr surf = -+ gfx::Factory::CreateSourceSurfaceForCairoSurface( -+ mImageSurface->CairoSurface(), mImageSurface->GetSize(), -+ mImageSurface->Format()); -+ if (!dt || !surf) { -+ return false; -+ } -+ -+ uint32_t numRects = aRegion.GetNumRects(); -+ if (numRects != 1) { -+ AutoTArray rects; -+ rects.SetCapacity(numRects); -+ for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { -+ rects.AppendElement(iter.Get().ToUnknownRect()); -+ } -+ dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); -+ } -+ -+ dt->DrawSurface(surf, rect, rect); -+ -+ if (numRects != 1) { -+ dt->PopClip(); -+ } -+ -+ return true; -+} -+ -+static void WaylandBufferDelayCommitHandler(WindowSurfaceWayland** aSurface) { -+ if (*aSurface) { -+ (*aSurface)->DelayedCommitHandler(); -+ } else { -+ // Referenced WindowSurfaceWayland is already deleted. -+ // Do nothing but just release the mDelayedCommitHandle allocated at -+ // WindowSurfaceWayland::CommitWaylandBuffer(). -+ free(aSurface); -+ } -+} -+ -+void WindowSurfaceWayland::CommitWaylandBuffer() { -+ MOZ_ASSERT(mPendingCommit, "Committing empty surface!"); -+ -+ 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!"); -+ -+ // Do nothing if there's already mDelayedCommitHandle pending. -+ if (!mDelayedCommitHandle) { -+ mDelayedCommitHandle = static_cast( -+ moz_xmalloc(sizeof(*mDelayedCommitHandle))); -+ *mDelayedCommitHandle = this; -+ -+ MessageLoop::current()->PostDelayedTask( -+ NewRunnableFunction("WaylandBackBufferCommit", -+ &WaylandBufferDelayCommitHandler, -+ mDelayedCommitHandle), -+ EVENT_LOOP_DELAY); -+ } - return; - } -- wl_proxy_set_queue((struct wl_proxy *)waylandSurface, -+ wl_proxy_set_queue((struct wl_proxy*)waylandSurface, - mWaylandDisplay->GetEventQueue()); - -- if (mFullScreenDamage) { -+ // We have an active frame callback request so handle it. -+ if (mFrameCallback) { -+ if (waylandSurface == mLastCommittedSurface) { -+ // We have an active frame callback pending from our recent surface. -+ // It means we should defer the commit to FrameCallbackHandler(). -+ return; -+ } -+ // If our stored wl_surface does not match the actual one it means the frame -+ // callback is no longer active and we should release it. -+ wl_callback_destroy(mFrameCallback); -+ mFrameCallback = nullptr; -+ mLastCommittedSurface = nullptr; -+ } -+ -+ if (mWaylandBufferFullScreenDamage) { - LayoutDeviceIntRect rect = mWindow->GetBounds(); - wl_surface_damage(waylandSurface, 0, 0, rect.width, rect.height); -- mFullScreenDamage = false; -+ mWaylandBufferFullScreenDamage = false; - } else { -- for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) { -- 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); - } - } - -- // Frame callback is always connected to actual wl_surface. When the surface -- // is unmapped/deleted the frame callback is never called. Unfortunatelly -- // we don't know if the frame callback is not going to be called. -- // But our mozcontainer code deletes wl_surface when the GdkWindow is hidden -- // creates a new one when is visible. -- if (mFrameCallback && mFrameCallbackSurface == waylandSurface) { -- // Do nothing here - we have a valid wl_surface and the buffer will be -- // commited to compositor in next frame callback event. -- mDelayedCommit = true; -- return; -- } else { -- if (mFrameCallback) { -- // Delete frame callback connected to obsoleted wl_surface. -- wl_callback_destroy(mFrameCallback); -- } -+ // Clear all back buffer damage as we're committing -+ // all requested regions. -+ mWaylandBufferDamage.SetEmpty(); - -- mFrameCallback = wl_surface_frame(waylandSurface); -- wl_callback_add_listener(mFrameCallback, &frame_listener, this); -- mFrameCallbackSurface = waylandSurface; -- -- // There's no pending frame callback so we can draw immediately -- // and create frame callback for possible subsequent drawing. -- mFrontBuffer->Attach(waylandSurface); -- mDelayedCommit = false; -+ mFrameCallback = wl_surface_frame(waylandSurface); -+ wl_callback_add_listener(mFrameCallback, &frame_listener, this); -+ -+ if (mNeedScaleFactorUpdate || mLastCommittedSurface != waylandSurface) { -+ wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor()); -+ mNeedScaleFactorUpdate = false; - } -+ -+ mWaylandBuffer->Attach(waylandSurface); -+ mLastCommittedSurface = waylandSurface; -+ -+ // There's no pending commit, all changes are sent to compositor. -+ mPendingCommit = false; -+} -+ -+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) { -+ mWaylandBufferDamage.OrWith(aInvalidRegion); -+ } -+ -+ // We're ready to commit. -+ mPendingCommit = true; -+ CommitWaylandBuffer(); - } - - void WindowSurfaceWayland::FrameCallbackHandler() { - MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); -+ MOZ_ASSERT(mFrameCallback != nullptr, -+ "FrameCallbackHandler() called without valid frame callback!"); -+ MOZ_ASSERT(mLastCommittedSurface != nullptr, -+ "FrameCallbackHandler() called without valid wl_surface!"); - -- if (mFrameCallback) { -- wl_callback_destroy(mFrameCallback); -- mFrameCallback = nullptr; -- mFrameCallbackSurface = nullptr; -+ wl_callback_destroy(mFrameCallback); -+ mFrameCallback = nullptr; -+ -+ if (mPendingCommit) { -+ CommitWaylandBuffer(); - } -+} - -- if (mDelayedCommit) { -- wl_surface *waylandSurface = mWindow->GetWaylandSurface(); -- if (!waylandSurface) { -- // Target window is already destroyed - don't bother to render there. -- NS_WARNING("No drawing buffer available"); -- return; -- } -- wl_proxy_set_queue((struct wl_proxy *)waylandSurface, -- mWaylandDisplay->GetEventQueue()); -+void WindowSurfaceWayland::DelayedCommitHandler() { -+ MOZ_ASSERT(mDelayedCommitHandle != nullptr, "Missing mDelayedCommitHandle!"); - -- // Send pending surface to compositor and register frame callback -- // for possible subsequent drawing. -- mFrameCallback = wl_surface_frame(waylandSurface); -- wl_callback_add_listener(mFrameCallback, &frame_listener, this); -- mFrameCallbackSurface = waylandSurface; -+ *mDelayedCommitHandle = nullptr; -+ free(mDelayedCommitHandle); -+ mDelayedCommitHandle = nullptr; - -- mFrontBuffer->Attach(waylandSurface); -- mDelayedCommit = false; -+ if (mPendingCommit) { -+ CommitWaylandBuffer(); - } - } - -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 { - --// 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(); - -- already_AddRefed Lock(const LayoutDeviceIntRegion& aRegion); -+ already_AddRefed Lock(); - - void Attach(wl_surface* aSurface); - 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) { - return aWidth == mWidth && aHeight == mHeight; -@@ -82,6 +60,8 @@ class WindowBackBuffer { - return aBuffer->mWidth == mWidth && aBuffer->mHeight == mHeight; - } - -+ static gfx::SurfaceFormat GetSurfaceFormat() { return mFormat; } -+ - 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[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 -up thunderbird-60.6.1/widget/gtk/WindowSurfaceProvider.cpp.old thunderbird-60.6.1/widget/gtk/WindowSurfaceProvider.cpp ---- thunderbird-60.6.1/widget/gtk/WindowSurfaceProvider.cpp.old 2019-05-14 21:11:50.219841534 +0200 -+++ thunderbird-60.6.1/widget/gtk/WindowSurfaceProvider.cpp 2019-05-14 21:11:58.228755117 +0200 -@@ -52,9 +52,6 @@ void WindowSurfaceProvider::Initialize(D - - #ifdef MOZ_WAYLAND - void WindowSurfaceProvider::Initialize(nsWindow* aWidget) { -- MOZ_ASSERT(aWidget->GetWaylandDisplay(), -- "We are supposed to have a Wayland display!"); -- - mWidget = aWidget; - mIsX11Display = false; - } diff --git a/mozilla-1353817.patch b/mozilla-1353817.patch index dc8d8f8..8bdac06 100644 --- a/mozilla-1353817.patch +++ b/mozilla-1353817.patch @@ -1,27 +1,12 @@ -From 1cc652f5525f458b0b4ceb12af24bf5a4367db32 Mon Sep 17 00:00:00 2001 -From: Nicolas Dufresne -Date: Tue, 23 May 2017 13:09:48 -0400 -Subject: [PATCH] Bug 1353817: Include SkNx_neon.h for ARM64 too - -This fixes build errors as arm_neon.h was missing along with some -missing converters. ---- - gfx/skia/skia/src/core/SkNx.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/gfx/skia/skia/src/core/SkNx.h b/gfx/skia/skia/src/core/SkNx.h -index 6bca856..b0427aa 100644 ---- a/gfx/skia/skia/src/core/SkNx.h -+++ b/gfx/skia/skia/src/core/SkNx.h -@@ -299,7 +299,7 @@ typedef SkNx<4, uint32_t> Sk4u; +diff -up thunderbird-68.0/gfx/skia/skia/include/private/SkNx.h.1353817 thunderbird-68.0/gfx/skia/skia/include/private/SkNx.h +--- thunderbird-68.0/gfx/skia/skia/include/private/SkNx.h.1353817 2019-08-29 16:31:20.892290062 +0200 ++++ thunderbird-68.0/gfx/skia/skia/include/private/SkNx.h 2019-08-29 16:32:05.430436157 +0200 +@@ -416,7 +416,7 @@ typedef SkNx<8, uint32_t> Sk8u; // Include platform specific specializations if available. #if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 - #include "../opts/SkNx_sse.h" + #include "SkNx_sse.h" -#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON) +#elif !defined(SKNX_NO_SIMD) && (defined(SK_ARM_HAS_NEON) || defined(SK_CPU_ARM64)) - #include "../opts/SkNx_neon.h" + #include "SkNx_neon.h" #else --- -2.9.4 - diff --git a/mozilla-1460871-ldap-query.patch b/mozilla-1460871-ldap-query.patch deleted file mode 100644 index 2f9c23d..0000000 --- a/mozilla-1460871-ldap-query.patch +++ /dev/null @@ -1,164 +0,0 @@ -diff -up thunderbird-60.2.1/comm/ldap/xpcom/public/nsILDAPOperation.idl.1460871-ldap-query thunderbird-60.2.1/comm/ldap/xpcom/public/nsILDAPOperation.idl ---- thunderbird-60.2.1/comm/ldap/xpcom/public/nsILDAPOperation.idl.1460871-ldap-query 2018-10-01 16:52:39.000000000 +0200 -+++ thunderbird-60.2.1/comm/ldap/xpcom/public/nsILDAPOperation.idl 2018-10-04 09:40:04.491575949 +0200 -@@ -52,6 +52,10 @@ interface nsILDAPOperation : nsISupports - * private parameter (anything caller desires) - */ - attribute nsISupports closure; -+ /** -+ * number of the request for compare that the request is still valid. -+ */ -+ attribute unsigned long requestNum; - - /** - * No time and/or size limit specified -diff -up thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.cpp.1460871-ldap-query thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.cpp ---- thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.cpp.1460871-ldap-query 2018-10-01 16:52:39.000000000 +0200 -+++ thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.cpp 2018-10-04 09:40:04.491575949 +0200 -@@ -400,6 +400,19 @@ convertControlArray(nsIArray *aXpcomArra - return NS_OK; - } - -+ /* attribute unsigned long requestNum; */ -+NS_IMETHODIMP nsLDAPOperation::GetRequestNum(uint32_t *aRequestNum) -+{ -+ *aRequestNum = mRequestNum; -+ return NS_OK; -+} -+ -+NS_IMETHODIMP nsLDAPOperation::SetRequestNum(uint32_t aRequestNum) -+{ -+ mRequestNum = aRequestNum; -+ return NS_OK; -+} -+ - NS_IMETHODIMP - nsLDAPOperation::SearchExt(const nsACString& aBaseDn, int32_t aScope, - const nsACString& aFilter, -diff -up thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.h.1460871-ldap-query thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.h ---- thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.h.1460871-ldap-query 2018-10-01 16:52:39.000000000 +0200 -+++ thunderbird-60.2.1/comm/ldap/xpcom/src/nsLDAPOperation.h 2018-10-04 09:40:04.491575949 +0200 -@@ -36,6 +36,8 @@ class nsLDAPOperation : public nsILDAPOp - * used to break cycles - */ - void Clear(); -+ // Stores the request number for later check of the operation is still valid -+ int32_t mRequestNum; - - private: - virtual ~nsLDAPOperation(); -diff -up thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp.1460871-ldap-query thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp ---- thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp.1460871-ldap-query 2018-10-01 16:52:43.000000000 +0200 -+++ thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp 2018-10-04 09:40:55.334670404 +0200 -@@ -22,6 +22,8 @@ - - using namespace mozilla; - -+extern mozilla::LazyLogModule gLDAPLogModule; // defined in nsLDAPService.cpp -+ - // nsAbLDAPListenerBase inherits nsILDAPMessageListener - class nsAbQueryLDAPMessageListener : public nsAbLDAPListenerBase - { -@@ -66,7 +68,6 @@ protected: - - bool mFinished; - bool mCanceled; -- bool mWaitingForPrevQueryToFinish; - - nsCOMPtr mServerSearchControls; - nsCOMPtr mClientSearchControls; -@@ -94,7 +95,6 @@ nsAbQueryLDAPMessageListener::nsAbQueryL - mResultLimit(resultLimit), - mFinished(false), - mCanceled(false), -- mWaitingForPrevQueryToFinish(false), - mServerSearchControls(serverSearchControls), - mClientSearchControls(clientSearchControls) - { -@@ -116,9 +116,6 @@ nsresult nsAbQueryLDAPMessageListener::C - return NS_OK; - - mCanceled = true; -- if (!mFinished) -- mWaitingForPrevQueryToFinish = true; -- - return NS_OK; - } - -@@ -129,6 +126,8 @@ NS_IMETHODIMP nsAbQueryLDAPMessageListen - - int32_t messageType; - rv = aMessage->GetType(&messageType); -+ uint32_t requestNum; -+ mOperation->GetRequestNum(&requestNum); - NS_ENSURE_SUCCESS(rv, rv); - - bool cancelOperation = false; -@@ -137,6 +136,14 @@ NS_IMETHODIMP nsAbQueryLDAPMessageListen - { - MutexAutoLock lock (mLock); - -+ if (requestNum != sCurrentRequestNum) { -+ MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug, -+ ("nsAbQueryLDAPMessageListener::OnLDAPMessage: Ignoring message with " -+ "request num %d, current request num is %d.", -+ requestNum, sCurrentRequestNum)); -+ return NS_OK; -+ } -+ - if (mFinished) - return NS_OK; - -@@ -166,11 +173,10 @@ NS_IMETHODIMP nsAbQueryLDAPMessageListen - rv = OnLDAPMessageSearchResult(aMessage); - break; - case nsILDAPMessage::RES_SEARCH_ENTRY: -- if (!mFinished && !mWaitingForPrevQueryToFinish) -+ if (!mFinished) - rv = OnLDAPMessageSearchEntry(aMessage); - break; - case nsILDAPMessage::RES_SEARCH_RESULT: -- mWaitingForPrevQueryToFinish = false; - rv = OnLDAPMessageSearchResult(aMessage); - NS_ENSURE_SUCCESS(rv, rv); - break; -@@ -207,6 +213,8 @@ nsresult nsAbQueryLDAPMessageListener::D - rv = mOperation->Init(mConnection, this, nullptr); - NS_ENSURE_SUCCESS(rv, rv); - -+ mOperation->SetRequestNum(++sCurrentRequestNum); -+ - nsAutoCString dn; - rv = mSearchUrl->GetDn(dn); - NS_ENSURE_SUCCESS(rv, rv); -diff -up thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp.1460871-ldap-query thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp ---- thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp.1460871-ldap-query 2018-10-01 16:52:43.000000000 +0200 -+++ thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp 2018-10-04 09:40:04.492575951 +0200 -@@ -20,6 +20,8 @@ - - using namespace mozilla; - -+uint32_t nsAbLDAPListenerBase::sCurrentRequestNum = 0; -+ - nsAbLDAPListenerBase::nsAbLDAPListenerBase(nsILDAPURL* url, - nsILDAPConnection* connection, - const nsACString &login, -@@ -249,6 +251,7 @@ NS_IMETHODIMP nsAbLDAPListenerBase::OnLD - InitFailed(); - return rv; - } -+ mOperation->SetRequestNum(++sCurrentRequestNum); - - // Try non-password mechanisms first - if (mSaslMechanism.EqualsLiteral("GSSAPI")) -diff -up thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.h.1460871-ldap-query thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.h ---- thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.h.1460871-ldap-query 2018-10-01 16:52:43.000000000 +0200 -+++ thunderbird-60.2.1/comm/mailnews/addrbook/src/nsAbLDAPListenerBase.h 2018-10-04 09:40:04.492575951 +0200 -@@ -47,6 +47,7 @@ protected: - int32_t mTimeOut; - bool mBound; - bool mInitialized; -+ static uint32_t sCurrentRequestNum; - - mozilla::Mutex mLock; - }; diff --git a/mozilla-1508378.patch b/mozilla-1508378.patch deleted file mode 100644 index 127256e..0000000 --- a/mozilla-1508378.patch +++ /dev/null @@ -1,55 +0,0 @@ -diff -up thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.cpp.1508378 thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.cpp ---- thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.cpp.1508378 2019-04-12 09:23:26.846503741 +0200 -+++ thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.cpp 2019-04-12 09:25:45.661937077 +0200 -@@ -567,6 +567,23 @@ static void WaylandBufferDelayCommitHand - } - } - -+void WindowSurfaceWayland::CalcRectScale(LayoutDeviceIntRect& aRect, int aScale) { -+ if (aRect.x & 0x1) { -+ aRect.width += 1; -+ } -+ aRect.x = aRect.x / aScale; -+ -+ if (aRect.y & 0x1) { -+ aRect.height += 1; -+ } -+ aRect.y = aRect.y / aScale; -+ -+ aRect.width = (aRect.width & 0x1) ? aRect.width / aScale + 1 : -+ aRect.width / aScale; -+ aRect.height = (aRect.height & 0x1) ? aRect.height / aScale + 1 : -+ aRect.height / aScale; -+} -+ - void WindowSurfaceWayland::CommitWaylandBuffer() { - MOZ_ASSERT(mPendingCommit, "Committing empty surface!"); - -@@ -617,11 +634,13 @@ void WindowSurfaceWayland::CommitWayland - gint scaleFactor = mWindow->GdkScaleFactor(); - for (auto iter = mWaylandBufferDamage.RectIter(); !iter.Done(); - iter.Next()) { -- const mozilla::LayoutDeviceIntRect& r = iter.Get(); -+ 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); -+ if (scaleFactor > 1) { -+ CalcRectScale(r, scaleFactor); -+ } -+ wl_surface_damage(waylandSurface, r.x, r.y, r.width, r.height); - } - } - -diff -up thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.h.1508378 thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.h ---- thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.h.1508378 2019-04-12 09:23:26.817503860 +0200 -+++ thunderbird-60.6.1/widget/gtk/WindowSurfaceWayland.h 2019-04-12 09:23:26.846503741 +0200 -@@ -101,6 +101,7 @@ class WindowSurfaceWayland : public Wind - const gfx::IntSize& aLockSize); - bool CommitImageSurfaceToWaylandBuffer(const LayoutDeviceIntRegion& aRegion); - void CommitWaylandBuffer(); -+ void CalcRectScale(LayoutDeviceIntRect& aRect, int scale); - - // TODO: Do we need to hold a reference to nsWindow object? - nsWindow* mWindow; diff --git a/mozilla-1522780.patch b/mozilla-1522780.patch deleted file mode 100644 index 701f43b..0000000 --- a/mozilla-1522780.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff -up thunderbird-60.5.0/toolkit/xre/nsAppRunner.cpp.1522780 thunderbird-60.5.0/toolkit/xre/nsAppRunner.cpp ---- thunderbird-60.5.0/toolkit/xre/nsAppRunner.cpp.1522780 2019-02-05 20:57:28.384820067 +0100 -+++ thunderbird-60.5.0/toolkit/xre/nsAppRunner.cpp 2019-02-05 21:05:27.623511428 +0100 -@@ -3872,10 +3872,26 @@ int XREMain::XRE_mainStartup(bool* aExit - saveDisplayArg = true; - } - -- // On Wayland disabled builds read X11 DISPLAY env exclusively -- // and don't care about different displays. --#if !defined(MOZ_WAYLAND) -- if (!display_name) { -+ bool disableWayland = true; -+#if defined(MOZ_WAYLAND) -+ // Make X11 backend the default one. -+ // Enable Wayland backend only when GDK_BACKEND is set and -+ // Gtk+ >= 3.22 where we can expect recent enough -+ // compositor & libwayland interface. -+ disableWayland = (PR_GetEnv("GDK_BACKEND") == nullptr) || -+ (gtk_check_version(3, 22, 0) != nullptr); -+ // Enable Wayland on Gtk+ >= 3.22 where we can expect recent enough -+ disableWayland = (gtk_check_version(3, 22, 0) != nullptr); -+ if (!disableWayland) { -+ // Make X11 backend the default one unless MOZ_ENABLE_WAYLAND or -+ // GDK_BACKEND are specified. -+ disableWayland = (PR_GetEnv("GDK_BACKEND") == nullptr) && -+ (PR_GetEnv("MOZ_ENABLE_WAYLAND") == nullptr); -+ } -+#endif -+ // On Wayland disabled builds read X11 DISPLAY env exclusively -+ // and don't care about different displays. -+ if (disableWayland && !display_name) { - display_name = PR_GetEnv("DISPLAY"); - if (!display_name) { - PR_fprintf(PR_STDERR, -@@ -3883,7 +3899,6 @@ int XREMain::XRE_mainStartup(bool* aExit - return 1; - } - } --#endif - - if (display_name) { - mGdkDisplay = gdk_display_open(display_name); diff --git a/mozilla-1526243.patch b/mozilla-1526243.patch deleted file mode 100644 index 2d12378..0000000 --- a/mozilla-1526243.patch +++ /dev/null @@ -1,340 +0,0 @@ -changeset: 465480:a86f3560fb17 -parent: 465477:26d9b7ffbd6b -user: Martin Stransky -date: Fri Mar 29 15:30:15 2019 +0100 -summary: Bug 1526243 - [Linux] Don't use nsGConfService in nsGNOMEShellService.cpp, r=glandium - -diff --git a/browser/components/shell/nsGNOMEShellService.cpp b/browser/components/shell/nsGNOMEShellService.cpp ---- a/browser/components/shell/nsGNOMEShellService.cpp -+++ b/browser/components/shell/nsGNOMEShellService.cpp -@@ -10,17 +10,16 @@ - #include "nsShellService.h" - #include "nsIServiceManager.h" - #include "nsIFile.h" - #include "nsIProperties.h" - #include "nsDirectoryServiceDefs.h" - #include "nsIPrefService.h" - #include "prenv.h" - #include "nsString.h" --#include "nsIGConfService.h" - #include "nsIGIOService.h" - #include "nsIGSettingsService.h" - #include "nsIStringBundle.h" - #include "nsIOutputStream.h" - #include "nsIProcess.h" - #include "nsServiceManagerUtils.h" - #include "nsComponentManagerUtils.h" - #include "nsIImageLoadingContent.h" -@@ -65,48 +64,39 @@ static const ProtocolAssociation appProt - - static const MimeTypeAssociation appTypes[] = { - // clang-format off - { "text/html", "htm html shtml" }, - { "application/xhtml+xml", "xhtml xht" } - // clang-format on - }; - --// GConf registry key constants --#define DG_BACKGROUND "/desktop/gnome/background" -- --#define kDesktopImageKey DG_BACKGROUND "/picture_filename" --#define kDesktopOptionsKey DG_BACKGROUND "/picture_options" --#define kDesktopDrawBGKey DG_BACKGROUND "/draw_background" --#define kDesktopColorKey DG_BACKGROUND "/primary_color" -- - #define kDesktopBGSchema "org.gnome.desktop.background" - #define kDesktopImageGSKey "picture-uri" - #define kDesktopOptionGSKey "picture-options" - #define kDesktopDrawBGGSKey "draw-background" - #define kDesktopColorGSKey "primary-color" - - static bool IsRunningAsASnap() { return (PR_GetEnv("SNAP") != nullptr); } - - nsresult nsGNOMEShellService::Init() { - nsresult rv; - - if (gfxPlatform::IsHeadless()) { - return NS_ERROR_NOT_AVAILABLE; - } - -- // GConf, GSettings or GIO _must_ be available, or we do not allow -+ // GSettings or GIO _must_ be available, or we do not allow - // CreateInstance to succeed. - -- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); - nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); - nsCOMPtr gsettings = - do_GetService(NS_GSETTINGSSERVICE_CONTRACTID); - -- if (!gconf && !giovfs && !gsettings) return NS_ERROR_NOT_AVAILABLE; -+ if (!giovfs && !gsettings) return NS_ERROR_NOT_AVAILABLE; - - // Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use - // the locale encoding. If it's not set, they use UTF-8. - mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nullptr; - - if (GetAppPathFromLauncher()) return NS_OK; - - nsCOMPtr dirSvc( -@@ -212,35 +202,23 @@ nsGNOMEShellService::IsDefaultBrowser(bo - } - if (strcmp(output, "yes\n") == 0) { - *aIsDefaultBrowser = true; - } - g_free(output); - return NS_OK; - } - -- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); - nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); -- -- bool enabled; - nsAutoCString handler; - nsCOMPtr gioApp; - - for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) { - if (!appProtocols[i].essential) continue; - -- if (gconf) { -- handler.Truncate(); -- gconf->GetAppForProtocol(nsDependentCString(appProtocols[i].name), -- &enabled, handler); -- -- if (!CheckHandlerMatchesAppName(handler) || !enabled) -- return NS_OK; // the handler is disabled or set to another app -- } -- - if (giovfs) { - handler.Truncate(); - nsCOMPtr handlerApp; - giovfs->GetAppForURIScheme(nsDependentCString(appProtocols[i].name), - getter_AddRefs(handlerApp)); - gioApp = do_QueryInterface(handlerApp); - if (!gioApp) return NS_OK; - -@@ -270,39 +248,17 @@ nsGNOMEShellService::SetDefaultBrowser(b - GSpawnFlags flags = static_cast(G_SPAWN_SEARCH_PATH | - G_SPAWN_STDOUT_TO_DEV_NULL | - G_SPAWN_STDERR_TO_DEV_NULL); - g_spawn_sync(nullptr, (gchar **)argv, nullptr, flags, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr); - return NS_OK; - } - -- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); - nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); -- if (gconf) { -- nsAutoCString appKeyValue; -- if (mAppIsInPath) { -- // mAppPath is in the users path, so use only the basename as the launcher -- gchar *tmp = g_path_get_basename(mAppPath.get()); -- appKeyValue = tmp; -- g_free(tmp); -- } else { -- appKeyValue = mAppPath; -- } -- -- appKeyValue.AppendLiteral(" %s"); -- -- for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) { -- if (appProtocols[i].essential || aClaimAllTypes) { -- gconf->SetAppForProtocol(nsDependentCString(appProtocols[i].name), -- appKeyValue); -- } -- } -- } -- - if (giovfs) { - nsresult rv; - nsCOMPtr bundleService = - do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr brandBundle; - rv = bundleService->CreateBundle(BRAND_PROPERTIES, -@@ -353,19 +309,21 @@ nsGNOMEShellService::SetDefaultBrowser(b - } - - return NS_OK; - } - - NS_IMETHODIMP - nsGNOMEShellService::GetCanSetDesktopBackground(bool *aResult) { - // setting desktop background is currently only supported -- // for Gnome or desktops using the same GSettings and GConf keys -- const char *gnomeSession = getenv("GNOME_DESKTOP_SESSION_ID"); -- if (gnomeSession) { -+ // for Gnome or desktops using the same GSettings keys -+ const char *currentDesktop = getenv("XDG_CURRENT_DESKTOP"); -+ if (currentDesktop && -+ (strstr(currentDesktop, "GNOME-Flashback:GNOME") != nullptr || -+ strstr(currentDesktop, "GNOME") != nullptr)) { - *aResult = true; - } else { - *aResult = false; - } - - return NS_OK; - } - -@@ -439,20 +397,16 @@ nsGNOMEShellService::SetDesktopBackgroun - filePath.Append('/'); - filePath.Append(NS_ConvertUTF16toUTF8(brandName)); - filePath.AppendLiteral("_wallpaper.png"); - - // write the image to a file in the home dir - rv = WriteImage(filePath, container); - NS_ENSURE_SUCCESS(rv, rv); - -- // Try GSettings first. If we don't have GSettings or the right schema, fall -- // back to using GConf instead. Note that if GSettings works ok, the changes -- // get mirrored to GConf by the gsettings->gconf bridge in -- // gnome-settings-daemon - nsCOMPtr gsettings = - do_GetService(NS_GSETTINGSSERVICE_CONTRACTID); - if (gsettings) { - nsCOMPtr background_settings; - gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(kDesktopBGSchema), - getter_AddRefs(background_settings)); - if (background_settings) { - gchar *file_uri = g_filename_to_uri(filePath.get(), nullptr, nullptr); -@@ -465,32 +419,17 @@ nsGNOMEShellService::SetDesktopBackgroun - nsDependentCString(file_uri)); - g_free(file_uri); - background_settings->SetBoolean(NS_LITERAL_CSTRING(kDesktopDrawBGGSKey), - true); - return rv; - } - } - -- // if the file was written successfully, set it as the system wallpaper -- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); -- -- if (gconf) { -- gconf->SetString(NS_LITERAL_CSTRING(kDesktopOptionsKey), options); -- -- // Set the image to an empty string first to force a refresh -- // (since we could be writing a new image on top of an existing -- // Firefox_wallpaper.png and nautilus doesn't monitor the file for changes) -- gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), EmptyCString()); -- -- gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), filePath); -- gconf->SetBool(NS_LITERAL_CSTRING(kDesktopDrawBGKey), true); -- } -- -- return rv; -+ return NS_ERROR_FAILURE; - } - - #define COLOR_16_TO_8_BIT(_c) ((_c) >> 8) - #define COLOR_8_TO_16_BIT(_c) ((_c) << 8 | (_c)) - - NS_IMETHODIMP - nsGNOMEShellService::GetDesktopBackgroundColor(uint32_t *aColor) { - nsCOMPtr gsettings = -@@ -502,22 +441,16 @@ nsGNOMEShellService::GetDesktopBackgroun - gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(kDesktopBGSchema), - getter_AddRefs(background_settings)); - if (background_settings) { - background_settings->GetString(NS_LITERAL_CSTRING(kDesktopColorGSKey), - background); - } - } - -- if (!background_settings) { -- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); -- if (gconf) -- gconf->GetString(NS_LITERAL_CSTRING(kDesktopColorKey), background); -- } -- - if (background.IsEmpty()) { - *aColor = 0; - return NS_OK; - } - - GdkColor color; - gboolean success = gdk_color_parse(background.get(), &color); - -@@ -555,23 +488,17 @@ nsGNOMEShellService::SetDesktopBackgroun - getter_AddRefs(background_settings)); - if (background_settings) { - background_settings->SetString(NS_LITERAL_CSTRING(kDesktopColorGSKey), - colorString); - return NS_OK; - } - } - -- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); -- -- if (gconf) { -- gconf->SetString(NS_LITERAL_CSTRING(kDesktopColorKey), colorString); -- } -- -- return NS_OK; -+ return NS_ERROR_FAILURE; - } - - NS_IMETHODIMP - nsGNOMEShellService::OpenApplication(int32_t aApplication) { - nsAutoCString scheme; - if (aApplication == APPLICATION_MAIL) - scheme.AssignLiteral("mailto"); - else if (aApplication == APPLICATION_NEWS) -@@ -581,55 +508,17 @@ nsGNOMEShellService::OpenApplication(int - - nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); - if (giovfs) { - nsCOMPtr handlerApp; - giovfs->GetAppForURIScheme(scheme, getter_AddRefs(handlerApp)); - if (handlerApp) return handlerApp->LaunchWithURI(nullptr, nullptr); - } - -- nsCOMPtr gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); -- if (!gconf) return NS_ERROR_FAILURE; -- -- bool enabled; -- nsAutoCString appCommand; -- gconf->GetAppForProtocol(scheme, &enabled, appCommand); -- -- if (!enabled) return NS_ERROR_FAILURE; -- -- // XXX we don't currently handle launching a terminal window. -- // If the handler requires a terminal, bail. -- bool requiresTerminal; -- gconf->HandlerRequiresTerminal(scheme, &requiresTerminal); -- if (requiresTerminal) return NS_ERROR_FAILURE; -- -- // Perform shell argument expansion -- int argc; -- char **argv; -- if (!g_shell_parse_argv(appCommand.get(), &argc, &argv, nullptr)) -- return NS_ERROR_FAILURE; -- -- char **newArgv = new char *[argc + 1]; -- int newArgc = 0; -- -- // Run through the list of arguments. Copy all of them to the new -- // argv except for %s, which we skip. -- for (int i = 0; i < argc; ++i) { -- if (strcmp(argv[i], "%s") != 0) newArgv[newArgc++] = argv[i]; -- } -- -- newArgv[newArgc] = nullptr; -- -- gboolean err = g_spawn_async(nullptr, newArgv, nullptr, G_SPAWN_SEARCH_PATH, -- nullptr, nullptr, nullptr, nullptr); -- -- g_strfreev(argv); -- delete[] newArgv; -- -- return err ? NS_OK : NS_ERROR_FAILURE; -+ return NS_ERROR_FAILURE; - } - - NS_IMETHODIMP - nsGNOMEShellService::OpenApplicationWithURI(nsIFile *aApplication, - const nsACString &aURI) { - nsresult rv; - nsCOMPtr process = - do_CreateInstance("@mozilla.org/process/util;1", &rv); - diff --git a/mozilla-1533969.patch b/mozilla-1533969.patch deleted file mode 100644 index f84d77a..0000000 --- a/mozilla-1533969.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff -up thunderbird-60.6.1/js/src/util/NativeStack.cpp.1533969 thunderbird-60.6.1/js/src/util/NativeStack.cpp -diff -up thunderbird-60.6.1/tools/profiler/core/platform.h.1533969 thunderbird-60.6.1/tools/profiler/core/platform.h ---- thunderbird-60.6.1/tools/profiler/core/platform.h.1533969 2019-03-26 12:51:50.138988424 +0100 -+++ thunderbird-60.6.1/tools/profiler/core/platform.h 2019-03-26 12:54:57.576579732 +0100 -@@ -47,11 +47,11 @@ - #if defined(__GLIBC__) - #include - #include --static inline pid_t gettid() { return (pid_t)syscall(SYS_gettid); } -+# define gettid() static_cast(syscall(SYS_gettid)) - #elif defined(GP_OS_darwin) - #include - #include --static inline pid_t gettid() { return (pid_t)syscall(SYS_thread_selfid); } -+# define gettid() static_cast(syscall(SYS_thread_selfid)) - #elif defined(GP_OS_android) - #include - #elif defined(GP_OS_windows) diff --git a/mozilla-1540145.patch b/mozilla-1540145.patch deleted file mode 100644 index efdf89d..0000000 --- a/mozilla-1540145.patch +++ /dev/null @@ -1,168 +0,0 @@ -diff -up firefox-66.0.1/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.mozilla-1540145 firefox-66.0.1/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp ---- firefox-66.0.1/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.mozilla-1540145 2019-03-22 06:06:07.000000000 +0100 -+++ firefox-66.0.1/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp 2019-04-01 09:33:18.621166482 +0200 -@@ -6,7 +6,6 @@ - #include "nsISystemProxySettings.h" - #include "mozilla/ModuleUtils.h" - #include "nsIServiceManager.h" --#include "nsIGConfService.h" - #include "nsIURI.h" - #include "nsReadableUtils.h" - #include "nsArrayUtils.h" -@@ -32,16 +31,10 @@ class nsUnixSystemProxySettings final : - private: - ~nsUnixSystemProxySettings() = default; - -- nsCOMPtr mGConf; -- nsCOMPtr mGSettings; -+ nsCOMPtr mGSettings; - nsCOMPtr mProxySettings; - nsInterfaceHashtable - mSchemeProxySettings; -- bool IsProxyMode(const char* aMode); -- nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, -- nsACString& aResult); -- nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, -- int32_t aPort, nsACString& aResult); - nsresult GetProxyFromGSettings(const nsACString& aScheme, - const nsACString& aHost, int32_t aPort, - nsACString& aResult); -@@ -66,20 +59,10 @@ nsresult nsUnixSystemProxySettings::Init - NS_LITERAL_CSTRING("org.gnome.system.proxy"), - getter_AddRefs(mProxySettings)); - } -- if (!mProxySettings) { -- mGConf = do_GetService(NS_GCONFSERVICE_CONTRACTID); -- } - - return NS_OK; - } - --bool nsUnixSystemProxySettings::IsProxyMode(const char* aMode) { -- nsAutoCString mode; -- return NS_SUCCEEDED(mGConf->GetString( -- NS_LITERAL_CSTRING("/system/proxy/mode"), mode)) && -- mode.EqualsASCII(aMode); --} -- - nsresult nsUnixSystemProxySettings::GetPACURI(nsACString& aResult) { - if (mProxySettings) { - nsCString proxyMode; -@@ -92,14 +75,8 @@ nsresult nsUnixSystemProxySettings::GetP - } - /* The org.gnome.system.proxy schema has been found, but auto mode is not - * set. Don't try the GConf and return empty string. */ -- aResult.Truncate(); -- return NS_OK; - } - -- if (mGConf && IsProxyMode("auto")) { -- return mGConf->GetString(NS_LITERAL_CSTRING("/system/proxy/autoconfig_url"), -- aResult); -- } - // Return an empty string when auto mode is not set. - aResult.Truncate(); - return NS_OK; -@@ -217,30 +194,6 @@ static nsresult GetProxyFromEnvironment( - return NS_OK; - } - --nsresult nsUnixSystemProxySettings::SetProxyResultFromGConf( -- const char* aKeyBase, const char* aType, nsACString& aResult) { -- nsAutoCString hostKey; -- hostKey.AppendASCII(aKeyBase); -- hostKey.AppendLiteral("host"); -- nsAutoCString host; -- nsresult rv = mGConf->GetString(hostKey, host); -- NS_ENSURE_SUCCESS(rv, rv); -- if (host.IsEmpty()) return NS_ERROR_FAILURE; -- -- nsAutoCString portKey; -- portKey.AppendASCII(aKeyBase); -- portKey.AppendLiteral("port"); -- int32_t port; -- rv = mGConf->GetInt(portKey, &port); -- NS_ENSURE_SUCCESS(rv, rv); -- -- /* When port is 0, proxy is not considered as enabled even if host is set. */ -- if (port == 0) return NS_ERROR_FAILURE; -- -- SetProxyResult(aType, host, port, aResult); -- return NS_OK; --} -- - nsresult nsUnixSystemProxySettings::SetProxyResultFromGSettings( - const char* aKeyBase, const char* aType, nsACString& aResult) { - nsDependentCString key(aKeyBase); -@@ -366,63 +319,6 @@ static bool HostIgnoredByProxy(const nsA - return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0; - } - --nsresult nsUnixSystemProxySettings::GetProxyFromGConf(const nsACString& aScheme, -- const nsACString& aHost, -- int32_t aPort, -- nsACString& aResult) { -- bool masterProxySwitch = false; -- mGConf->GetBool(NS_LITERAL_CSTRING("/system/http_proxy/use_http_proxy"), -- &masterProxySwitch); -- // if no proxy is set in GConf return NS_ERROR_FAILURE -- if (!(IsProxyMode("manual") || masterProxySwitch)) { -- return NS_ERROR_FAILURE; -- } -- -- nsCOMPtr ignoreList; -- if (NS_SUCCEEDED(mGConf->GetStringList( -- NS_LITERAL_CSTRING("/system/http_proxy/ignore_hosts"), -- getter_AddRefs(ignoreList))) && -- ignoreList) { -- uint32_t len = 0; -- ignoreList->GetLength(&len); -- for (uint32_t i = 0; i < len; ++i) { -- nsCOMPtr str = do_QueryElementAt(ignoreList, i); -- if (str) { -- nsAutoString s; -- if (NS_SUCCEEDED(str->GetData(s)) && !s.IsEmpty()) { -- if (HostIgnoredByProxy(NS_ConvertUTF16toUTF8(s), aHost)) { -- aResult.AppendLiteral("DIRECT"); -- return NS_OK; -- } -- } -- } -- } -- } -- -- bool useHttpProxyForAll = false; -- // This setting sometimes doesn't exist, don't bail on failure -- mGConf->GetBool(NS_LITERAL_CSTRING("/system/http_proxy/use_same_proxy"), -- &useHttpProxyForAll); -- -- nsresult rv; -- if (!useHttpProxyForAll) { -- rv = SetProxyResultFromGConf("/system/proxy/socks_", "SOCKS", aResult); -- if (NS_SUCCEEDED(rv)) return rv; -- } -- -- if (aScheme.LowerCaseEqualsLiteral("http") || useHttpProxyForAll) { -- rv = SetProxyResultFromGConf("/system/http_proxy/", "PROXY", aResult); -- } else if (aScheme.LowerCaseEqualsLiteral("https")) { -- rv = SetProxyResultFromGConf("/system/proxy/secure_", "PROXY", aResult); -- } else if (aScheme.LowerCaseEqualsLiteral("ftp")) { -- rv = SetProxyResultFromGConf("/system/proxy/ftp_", "PROXY", aResult); -- } else { -- rv = NS_ERROR_FAILURE; -- } -- -- return rv; --} -- - nsresult nsUnixSystemProxySettings::GetProxyFromGSettings( - const nsACString& aScheme, const nsACString& aHost, int32_t aPort, - nsACString& aResult) { -@@ -494,7 +390,6 @@ nsresult nsUnixSystemProxySettings::GetP - nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult); - if (NS_SUCCEEDED(rv)) return rv; - } -- if (mGConf) return GetProxyFromGConf(aScheme, aHost, aPort, aResult); - - return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult); - } diff --git a/rust-1.33-build.patch b/rust-1.33-build.patch deleted file mode 100644 index 746145f..0000000 --- a/rust-1.33-build.patch +++ /dev/null @@ -1,47 +0,0 @@ -diff -up thunderbird-60.8.0/servo/components/style_traits/values.rs.rust-1.33-build thunderbird-60.8.0/servo/components/style_traits/values.rs ---- thunderbird-60.8.0/servo/components/style_traits/values.rs.rust-1.33-build 2019-07-03 17:25:28.000000000 +0200 -+++ thunderbird-60.8.0/servo/components/style_traits/values.rs 2019-07-11 13:38:53.687318154 +0200 -@@ -135,6 +135,7 @@ where - } - } - -+/// Some comment - #[macro_export] - macro_rules! serialize_function { - ($dest: expr, $name: ident($( $arg: expr, )+)) => { -@@ -404,6 +405,7 @@ impl_to_css_for_predefined_type!(::csspa - impl_to_css_for_predefined_type!(::cssparser::Color); - impl_to_css_for_predefined_type!(::cssparser::UnicodeRange); - -+/// Some comment - #[macro_export] - macro_rules! define_css_keyword_enum { - (pub enum $name:ident { $($variant:ident = $css:expr,)+ }) => { -diff -up thunderbird-60.8.0/servo/components/style/properties/properties.mako.rs.old thunderbird-60.8.0/servo/components/style/properties/properties.mako.rs ---- thunderbird-60.8.0/servo/components/style/properties/properties.mako.rs.old 2019-07-11 14:22:51.393784701 +0200 -+++ thunderbird-60.8.0/servo/components/style/properties/properties.mako.rs 2019-07-11 14:24:03.182578100 +0200 -@@ -55,6 +55,7 @@ use style_adjuster::StyleAdjuster; - - pub use self::declaration_block::*; - -+/// Neco - #[cfg(feature = "gecko")] - #[macro_export] - macro_rules! property_name { -@@ -3852,7 +3853,7 @@ impl fmt::Debug for AliasId { - } - } - --// NOTE(emilio): Callers are responsible to deal with prefs. -+/// NOTE(emilio): Callers are responsible to deal with prefs. - #[macro_export] - macro_rules! css_properties_accessors { - ($macro_name: ident) => { -@@ -3875,6 +3876,7 @@ macro_rules! css_properties_accessors { - } - } - -+/// Neco - #[macro_export] - macro_rules! longhand_properties_idents { - ($macro_name: ident) => { diff --git a/sources b/sources index bb7ac03..6f69d8d 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (thunderbird-60.8.0.source.tar.xz) = b465544a8cbedf0aff0f737cf98e2d030331f1ea016b2e541dfe30a5cf3172f9075e5a9c8d6b7e0f97ffc2e0d3eebbaf9a39e76a499b9fc976bbc0c944dfd058 -SHA512 (thunderbird-langpacks-60.8.0-20190704.tar.xz) = 9613f678dde57ef2c99bf389a180a7c222472df74d935b80b49ab68e61cd36ad4950d7bad79fe11fdbbb728954b50297d80c4c4e422e4edfc0268fff012bf259 -SHA512 (lightning-langpacks-60.8.0.tar.xz) = 9ee5321810cc316e5d9725e6e43c95f24ab907a75962c1e78c9f24fe0eda421a4608f242018f1d52aa8fbc1d9be4a4e1e01cc707e0b8a9ae466505d0e3468fe2 +SHA512 (thunderbird-68.0.source.tar.xz) = 91f82016b71d65b58c1383248ac6f7a8cd8217409323eb14e8aabf2e509391bba4d18e0aa6d0cdac191d10e9794977f22f509078b7c5e3ac7c22afe379a0f299 +SHA512 (thunderbird-langpacks-68.0-20190829.tar.xz) = c11ca1f39c146cfbad8b2e4d5e1e8698caa6d97c9bb650b788a7df487dc3e2ee551aec9b814baae064b06543f0ae832583005e02c9d5cab1f3e66dbe1b28b08f +SHA512 (lightning-langpacks-68.0.tar.xz) = d51c99a5d3dd95b66552fab6fdf9d55d00f56dcc73389790354846078a0f973bbd6273ada0d342f09a4045f3453c7e2bdd166821b4100efc0bc511f77a099148 diff --git a/thunderbird-mozconfig b/thunderbird-mozconfig index c6e3cc4..805c81c 100644 --- a/thunderbird-mozconfig +++ b/thunderbird-mozconfig @@ -9,14 +9,12 @@ ac_add_options --libdir="$LIBDIR" ac_add_options --with-system-jpeg ac_add_options --with-system-zlib ac_add_options --with-system-libvpx -ac_add_options --with-pthreads ac_add_options --disable-tests ac_add_options --disable-strip # temporary disable system cairo, because compilation fails ac_add_options --disable-necko-wifi ac_add_options --disable-updater ac_add_options --enable-startup-notification -ac_add_options --enable-pie ac_add_options --with-system-icu # lightning related diff --git a/thunderbird.spec b/thunderbird.spec index 94fc335..65a47cc 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -14,6 +14,7 @@ ExcludeArch: s390x %define system_ffi 1 %define build_langpacks 1 +%global build_with_clang 0 %global disable_elfhack 0 %if 0%{?fedora} > 28 @@ -88,13 +89,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 60.8.0 -Release: 2%{?dist} +Version: 68.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190704.tar.xz +Source1: thunderbird-langpacks-%{version}-20190829.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -109,15 +110,12 @@ Source28: thunderbird-wayland.sh.in Source29: thunderbird-wayland.desktop # Build patches -Patch1: rust-1.33-build.patch Patch9: mozilla-build-arm.patch Patch26: build-icu-big-endian.patch -Patch37: build-jit-atomic-always-lucky.patch -Patch40: build-aarch64-skia.patch Patch226: rhbz-1354671.patch Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch +Patch416: firefox-SIOCGSTAMP.patch Patch103: rhbz-1219542-s390-build.patch -Patch104: mozilla-1533969.patch Patch105: thunderbird-debug.patch # PPC fix @@ -125,17 +123,11 @@ Patch304: mozilla-1245783.patch Patch305: build-big-endian.patch Patch306: mozilla-1353817.patch Patch307: build-disable-elfhack.patch -Patch309: mozilla-1460871-ldap-query.patch # Fedora specific patches -Patch311: firefox-wayland.patch -Patch312: mozilla-1522780.patch # Upstream patches -Patch400: mozilla-1526243.patch -Patch401: mozilla-1540145.patch Patch402: mozilla-526293.patch -Patch403: mozilla-1508378.patch %if %{official_branding} # Required by Mozilla Corporation @@ -170,8 +162,9 @@ BuildRequires: libXrender-devel BuildRequires: hunspell-devel BuildRequires: llvm BuildRequires: llvm-devel -BuildRequires: clang -BuildRequires: clang-libs +%if 0%{?build_with_clang} +BuildRequires: lld +%endif %if %{?system_sqlite} BuildRequires: sqlite-devel >= %{sqlite_version} Requires: sqlite >= %{sqlite_build_version} @@ -238,24 +231,19 @@ debug %{name}, you want to install %{name}-debuginfo instead. %setup -q # Build patches -%patch1 -p1 -b .rust-1.33-build %patch9 -p2 -b .arm %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build %endif -%patch104 -p1 -b .1533969 %patch105 -p1 -b .debug %patch304 -p1 -b .1245783 -%patch309 -p1 -b .1460871-ldap-query # Patch for big endian platforms only %if 0%{?big_endian} %patch26 -p1 -b .icu %patch305 -p1 -b .big-endian %endif -%patch37 -p1 -b .jit-atomic-lucky -%patch40 -p1 -b .aarch64-skia #ARM run-time patch %ifarch aarch64 %patch226 -p1 -b .1354671 @@ -263,6 +251,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %ifarch %{arm} %patch415 -p1 -b .mozilla-1238661 %endif +%patch416 -p1 -b .SIOCGSTAMP %patch306 -p1 -b .1353817 %if 0%{?disable_elfhack} @@ -270,13 +259,8 @@ debug %{name}, you want to install %{name}-debuginfo instead. %endif #cd .. -%patch311 -p1 -b .wayland -%patch312 -p1 -b .1522780 -%patch400 -p1 -b .1526243 -%patch401 -p1 -b .1540145 %patch402 -p1 -b .526293 -%patch403 -p1 -b .1508378 %if %{official_branding} # Required by Mozilla Corporation @@ -445,9 +429,11 @@ MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g1/') # (OOM when linking, rhbz#1238225) export MOZ_DEBUG_FLAGS=" " %endif +%if !0%{?build_with_clang} %ifarch s390 %{arm} ppc aarch64 i686 MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads" %endif +%endif export CFLAGS=`echo $MOZ_OPT_FLAGS |sed -e 's/-fpermissive//g'` export CXXFLAGS=$MOZ_OPT_FLAGS @@ -456,6 +442,25 @@ export LDFLAGS=$MOZ_LINK_FLAGS export PREFIX='%{_prefix}' export LIBDIR='%{_libdir}' +%if 0%{?build_with_clang} +export LLVM_PROFDATA="llvm-profdata" +export AR="llvm-ar" +export NM="llvm-nm" +export RANLIB="llvm-ranlib" +echo "ac_add_options --enable-linker=lld" >> .mozconfig +%else +export CC=gcc +export CXX=g++ +export AR="gcc-ar" +export NM="gcc-nm" +export RANLIB="gcc-ranlib" +%endif + +%if 0%{?build_with_pgo} +echo "ac_add_options MOZ_PGO=1" >> .mozconfig +echo "ac_add_options --enable-lto" >> .mozconfig +%endif + MOZ_SMP_FLAGS=-j1 # On x86 architectures, Mozilla can build up to 4 jobs at once in parallel, # however builds tend to fail on other arches when building in parallel. @@ -657,8 +662,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{mozappdir}/plugin-container %{mozappdir}/defaults %{mozappdir}/dictionaries -%dir %{mozappdir}/extensions -%{mozappdir}/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}.xpi %if %{build_langpacks} %dir %{langpackdir} %endif @@ -698,6 +701,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Aug 29 2019 Jan Horak - 68.0-1 +- Update to 68.0 + * Sat Jul 27 2019 Fedora Release Engineering - 60.8.0-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild From 0ca10b45fa08c7265de6e27f1136dc57bd724cea Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 3 Sep 2019 14:44:53 +0200 Subject: [PATCH 066/402] Added cbindgen --- .gitignore | 1 + gen_cbindgen-vendor.sh | 32 ++++++++++++++++++++++++++++++++ sources | 1 + thunderbird.spec | 27 +++++++++++++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100755 gen_cbindgen-vendor.sh diff --git a/.gitignore b/.gitignore index f2a8d9c..634766a 100644 --- a/.gitignore +++ b/.gitignore @@ -257,3 +257,4 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.0.source.tar.xz /thunderbird-langpacks-68.0-20190829.tar.xz /lightning-langpacks-68.0.tar.xz +/cbindgen-vendor.tar.xz diff --git a/gen_cbindgen-vendor.sh b/gen_cbindgen-vendor.sh new file mode 100755 index 0000000..01ecc5d --- /dev/null +++ b/gen_cbindgen-vendor.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -x + +# Dummy Cargo.toml file with cbindgen dependency +cat > Cargo.toml < 28 @@ -192,8 +193,15 @@ Provides: thunderbird-lightning Obsoletes: thunderbird-lightning-gdata <= 1:3.3.0.14 BuildRequires: rust BuildRequires: cargo +%if 0%{?build_with_clang} BuildRequires: clang-devel +%endif BuildRequires: python2-devel +%if !0%{?use_bundled_cbindgen} +BuildRequires: cbindgen +%endif + + Suggests: u2f-hidraw-policy %description @@ -377,6 +385,25 @@ echo "ac_add_options --disable-crashreporter" >> .mozconfig #=============================================================================== %build +%if 0%{?use_bundled_cbindgen} + +mkdir -p my_rust_vendor +cd my_rust_vendor +%{__tar} xf %{SOURCE2} +cd - +mkdir -p .cargo +cat > .cargo/config < Date: Tue, 3 Sep 2019 15:22:03 +0200 Subject: [PATCH 067/402] Fixing codegen installation --- thunderbird.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index b077a08..985685f 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -101,6 +101,7 @@ Source1: thunderbird-langpacks-%{version}-20190829.tar.xz Source2: lightning-langpacks-%{version}.tar.xz %endif Source3: get-calendar-langpacks.sh +Source4: cbindgen-vendor.tar.xz Source10: thunderbird-mozconfig Source11: thunderbird-mozconfig-branded @@ -389,7 +390,7 @@ echo "ac_add_options --disable-crashreporter" >> .mozconfig mkdir -p my_rust_vendor cd my_rust_vendor -%{__tar} xf %{SOURCE2} +%{__tar} xf %{SOURCE4} cd - mkdir -p .cargo cat > .cargo/config < Date: Tue, 3 Sep 2019 15:58:04 +0200 Subject: [PATCH 068/402] Added clang buildrequire --- thunderbird.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/thunderbird.spec b/thunderbird.spec index 985685f..be7428e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -164,6 +164,8 @@ BuildRequires: libXrender-devel BuildRequires: hunspell-devel BuildRequires: llvm BuildRequires: llvm-devel +BuildRequires: clang +BuildRequires: clang-libs %if 0%{?build_with_clang} BuildRequires: lld %endif From 72ae43e747981f76cce58e0067affb7eb2ca44da Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 4 Sep 2019 10:08:02 +0200 Subject: [PATCH 069/402] add clang-devel build require --- thunderbird.spec | 2 -- 1 file changed, 2 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index be7428e..4b9df9e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -196,9 +196,7 @@ Provides: thunderbird-lightning Obsoletes: thunderbird-lightning-gdata <= 1:3.3.0.14 BuildRequires: rust BuildRequires: cargo -%if 0%{?build_with_clang} BuildRequires: clang-devel -%endif BuildRequires: python2-devel %if !0%{?use_bundled_cbindgen} BuildRequires: cbindgen From c5201d52dc53dd5be241a2f62b631e640d60d529 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 4 Sep 2019 10:58:40 +0200 Subject: [PATCH 070/402] Added nodejs as buildrequire --- node-stdout-nonblocking-wrapper | 2 ++ thunderbird.spec | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100755 node-stdout-nonblocking-wrapper diff --git a/node-stdout-nonblocking-wrapper b/node-stdout-nonblocking-wrapper new file mode 100755 index 0000000..b2814b8 --- /dev/null +++ b/node-stdout-nonblocking-wrapper @@ -0,0 +1,2 @@ +#!/bin/sh +exec /usr/bin/node "$@" 2>&1 | cat - diff --git a/thunderbird.spec b/thunderbird.spec index 4b9df9e..5308cb8 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -110,6 +110,7 @@ Source20: thunderbird.desktop Source21: thunderbird.sh.in Source28: thunderbird-wayland.sh.in Source29: thunderbird-wayland.desktop +Source32: node-stdout-nonblocking-wrapper # Build patches Patch9: mozilla-build-arm.patch @@ -201,6 +202,8 @@ BuildRequires: python2-devel %if !0%{?use_bundled_cbindgen} BuildRequires: cbindgen %endif +BuildRequires: nodejs +BuildRequires: nasm >= 1.13 Suggests: u2f-hidraw-policy @@ -383,6 +386,8 @@ echo "ac_add_options --enable-crashreporter" >> .mozconfig echo "ac_add_options --disable-crashreporter" >> .mozconfig %endif +echo 'export NODEJS="%{_buildrootdir}/bin/node-stdout-nonblocking-wrapper"' >> .mozconfig + #=============================================================================== %build @@ -423,6 +428,9 @@ esac rm -f config/external/icu/data/icudt*l.dat %endif +mkdir %{_buildrootdir}/bin || : +cp %{SOURCE32} %{_buildrootdir}/bin || : + # Update the various config.guess to upstream release for aarch64 support find ./ -name config.guess -exec cp /usr/lib/rpm/config.guess {} ';' From f0e9d7ba8f69f8b112717821e33ee06733f3e64b Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 4 Sep 2019 11:10:00 +0200 Subject: [PATCH 071/402] Disable aarch64 patch --- thunderbird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 5308cb8..14aa02b 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -258,7 +258,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. #ARM run-time patch %ifarch aarch64 -%patch226 -p1 -b .1354671 +#%patch226 -p1 -b .1354671 %endif %ifarch %{arm} %patch415 -p1 -b .mozilla-1238661 From 9016b951adbe07a913da4095cc1fc9f362dd6057 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 4 Sep 2019 15:26:02 +0200 Subject: [PATCH 072/402] Add workaround for OOM on arm and i686 in rust --- thunderbird.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/thunderbird.spec b/thunderbird.spec index 14aa02b..0045c64 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -478,6 +478,10 @@ export LDFLAGS=$MOZ_LINK_FLAGS export PREFIX='%{_prefix}' export LIBDIR='%{_libdir}' +%ifarch %{arm} %{ix86} +export RUSTFLAGS="-Cdebuginfo=0" +%endif + %if 0%{?build_with_clang} export LLVM_PROFDATA="llvm-profdata" export AR="llvm-ar" From f5d06a23238ef85541dcdf5c326475a1b1435ce3 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 5 Sep 2019 09:00:31 +0200 Subject: [PATCH 073/402] Deal with user_vfp struct missing in aarch64 --- build-aarch64-user_vfp.patch | 12 ++++++++++++ thunderbird.spec | 2 ++ 2 files changed, 14 insertions(+) create mode 100644 build-aarch64-user_vfp.patch diff --git a/build-aarch64-user_vfp.patch b/build-aarch64-user_vfp.patch new file mode 100644 index 0000000..85e72c7 --- /dev/null +++ b/build-aarch64-user_vfp.patch @@ -0,0 +1,12 @@ +diff -up thunderbird-68.0/js/src/wasm/WasmSignalHandlers.cpp.aarch64-user_vfp thunderbird-68.0/js/src/wasm/WasmSignalHandlers.cpp +--- thunderbird-68.0/js/src/wasm/WasmSignalHandlers.cpp.aarch64-user_vfp 2019-09-05 08:57:46.443137916 +0200 ++++ thunderbird-68.0/js/src/wasm/WasmSignalHandlers.cpp 2019-09-05 08:58:07.776196823 +0200 +@@ -244,7 +244,7 @@ using mozilla::DebugOnly; + // emulation here. + + #if defined(__linux__) && defined(__arm__) +-# define WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS ++//# define WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS + #endif + + #ifdef WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS diff --git a/thunderbird.spec b/thunderbird.spec index 0045c64..773830a 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -118,6 +118,7 @@ Patch26: build-icu-big-endian.patch Patch226: rhbz-1354671.patch Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch Patch416: firefox-SIOCGSTAMP.patch +Patch417: build-aarch64-user_vfp.patch Patch103: rhbz-1219542-s390-build.patch Patch105: thunderbird-debug.patch @@ -264,6 +265,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch415 -p1 -b .mozilla-1238661 %endif %patch416 -p1 -b .SIOCGSTAMP +%patch417 -p1 -b .aarch64-user_vfp %patch306 -p1 -b .1353817 %if 0%{?disable_elfhack} From 8eb86f590c77d38aa8dc7de10a46835ad8c0c854 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 6 Sep 2019 12:17:50 +0200 Subject: [PATCH 074/402] Disabled arm due to rhbz#1658940 --- thunderbird.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/thunderbird.spec b/thunderbird.spec index 773830a..592d9da 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -1,3 +1,6 @@ +# Disabled arm due to rhbz#1658940 +ExcludeArch: armv7hl + # Disabled due to https://pagure.io/fedora-infrastructure/issue/7581 ExcludeArch: s390x From 0456464d53a7cc7eb266a80d8643ac901970885b Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 10 Sep 2019 10:16:17 +0200 Subject: [PATCH 075/402] Added build workarounds for oom on i686 --- thunderbird.spec | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 592d9da..4dd1075 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -470,10 +470,20 @@ MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g1/') # (OOM when linking, rhbz#1238225) export MOZ_DEBUG_FLAGS=" " %endif + +%ifarch %{arm} %{ix86} +MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g0/') +export MOZ_DEBUG_FLAGS=" " +%endif + %if !0%{?build_with_clang} -%ifarch s390 %{arm} ppc aarch64 i686 +%ifarch s390 ppc aarch64 %{ix86} MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads" %endif +%ifarch %{arm} +MOZ_LINK_FLAGS="-Wl,--no-keep-memory" +echo "ac_add_options --enable-linker=gold" >> .mozconfig +%endif %endif export CFLAGS=`echo $MOZ_OPT_FLAGS |sed -e 's/-fpermissive//g'` From b4b11fc4528a3cda96ea24974750b4e59dd82367 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 10 Sep 2019 12:45:12 +0200 Subject: [PATCH 076/402] Changed optimize flags according to firefox --- thunderbird.spec | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index 4dd1075..32bac27 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -320,19 +320,8 @@ echo "ac_add_options --enable-system-ffi" >> .mozconfig echo "ac_add_options --enable-debug" >> .mozconfig echo "ac_add_options --disable-optimize" >> .mozconfig %else - %define optimize_flags "none" - # Fedora 26 (gcc7) needs to disable default build flags (mozbz#1342344) - %if 0%{?fedora} > 25 || 0%{?rhel} > 7 - %ifnarch s390 s390x - %define optimize_flags "-g -O2" - %endif - %endif - %ifarch armv7hl - # ARMv7 need that (rhbz#1426850) - %define optimize_flags "-g -O2 -fno-schedule-insns" - %endif %ifarch ppc64le aarch64 - %define optimize_flags "-g -O2" + %global optimize_flags "-g -O2" %endif %if %{optimize_flags} != "none" echo 'ac_add_options --enable-optimize=%{?optimize_flags}' >> .mozconfig From 2f8aa70b27b392681589bfaa4cf9101624f9d6fd Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 11 Sep 2019 16:15:02 +0200 Subject: [PATCH 077/402] Fixing build issues on i686 --- thunderbird.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 32bac27..6effc4d 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -320,10 +320,11 @@ echo "ac_add_options --enable-system-ffi" >> .mozconfig echo "ac_add_options --enable-debug" >> .mozconfig echo "ac_add_options --disable-optimize" >> .mozconfig %else + %global optimize_flags "none" %ifarch ppc64le aarch64 %global optimize_flags "-g -O2" %endif - %if %{optimize_flags} != "none" + %if %{?optimize_flags} != "none" echo 'ac_add_options --enable-optimize=%{?optimize_flags}' >> .mozconfig %else echo 'ac_add_options --enable-optimize' >> .mozconfig From b7825be8a1f92f196702c0dec7f6ace2cddb3d01 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 12 Sep 2019 10:52:05 +0200 Subject: [PATCH 078/402] Update to 68.1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 634766a..384b94c 100644 --- a/.gitignore +++ b/.gitignore @@ -258,3 +258,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-langpacks-68.0-20190829.tar.xz /lightning-langpacks-68.0.tar.xz /cbindgen-vendor.tar.xz +/thunderbird-68.1.0.source.tar.xz +/thunderbird-langpacks-68.1.0-20190912.tar.xz +/lightning-langpacks-68.1.0.tar.xz diff --git a/sources b/sources index e3b8635..945e452 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.0.source.tar.xz) = 91f82016b71d65b58c1383248ac6f7a8cd8217409323eb14e8aabf2e509391bba4d18e0aa6d0cdac191d10e9794977f22f509078b7c5e3ac7c22afe379a0f299 -SHA512 (thunderbird-langpacks-68.0-20190829.tar.xz) = c11ca1f39c146cfbad8b2e4d5e1e8698caa6d97c9bb650b788a7df487dc3e2ee551aec9b814baae064b06543f0ae832583005e02c9d5cab1f3e66dbe1b28b08f -SHA512 (lightning-langpacks-68.0.tar.xz) = d51c99a5d3dd95b66552fab6fdf9d55d00f56dcc73389790354846078a0f973bbd6273ada0d342f09a4045f3453c7e2bdd166821b4100efc0bc511f77a099148 +SHA512 (thunderbird-68.1.0.source.tar.xz) = eb2a71bbf4b87ee1156f32b3829cf6970855187f9e60f5003bd3f3680b53b80f34220ed2575c26834bc2960b2c85b2b53c2ee5437b4c19031f94eae5ca9a010c +SHA512 (thunderbird-langpacks-68.1.0-20190912.tar.xz) = 8d96e56d224e1788225b3ad59ae3579409d451ad14395d37b5cbe41216bd6c91059ababe5298db742306e63aec2176f2564e6ab578b168e44945561a75e6054a +SHA512 (lightning-langpacks-68.1.0.tar.xz) = c371106520f128c33687e37d82b212dfdbecc083626f7ceb00fb260935e7c3b158e358ad4d30243b0c540f4a6b98b77290e57358efa4f0832d14d9c329a44d11 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d diff --git a/thunderbird.spec b/thunderbird.spec index 6effc4d..2fd6ea0 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.0 +Version: 68.1.0 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190829.tar.xz +Source1: thunderbird-langpacks-%{version}-20190912.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -746,6 +746,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Sep 12 2019 Jan Horak - 68.1.0-1 +- Update to 68.1.0 + * Thu Aug 29 2019 Jan Horak - 68.0-1 - Update to 68.0 From a7c9530625bbc7f77627f36549d11c37db38cc34 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 12 Sep 2019 16:20:53 +0200 Subject: [PATCH 079/402] Added workaround for failing inline function on ppc64le --- mozilla-1512162.patch | 21 +++++++++++++++++++++ thunderbird.spec | 2 ++ 2 files changed, 23 insertions(+) create mode 100644 mozilla-1512162.patch diff --git a/mozilla-1512162.patch b/mozilla-1512162.patch new file mode 100644 index 0000000..0ee0ed5 --- /dev/null +++ b/mozilla-1512162.patch @@ -0,0 +1,21 @@ +diff -up thunderbird-68.1.0/js/xpconnect/src/XPCWrappedNative.cpp.mozbz-1512162 thunderbird-68.1.0/js/xpconnect/src/XPCWrappedNative.cpp +--- thunderbird-68.1.0/js/xpconnect/src/XPCWrappedNative.cpp.mozbz-1512162 2019-09-10 01:43:33.000000000 +0200 ++++ thunderbird-68.1.0/js/xpconnect/src/XPCWrappedNative.cpp 2019-09-12 16:16:52.644123766 +0200 +@@ -1092,7 +1092,7 @@ class MOZ_STACK_CLASS CallMethodHelper f + MOZ_ALWAYS_INLINE bool GetOutParamSource(uint8_t paramIndex, + MutableHandleValue srcp) const; + +- MOZ_ALWAYS_INLINE bool GatherAndConvertResults(); ++ bool GatherAndConvertResults(); + + MOZ_ALWAYS_INLINE bool QueryInterfaceFastPath(); + +@@ -1139,7 +1139,7 @@ class MOZ_STACK_CLASS CallMethodHelper f + + ~CallMethodHelper(); + +- MOZ_ALWAYS_INLINE bool Call(); ++ bool Call(); + + // Trace implementation so we can put our CallMethodHelper in a Rooted. + void trace(JSTracer* aTrc); diff --git a/thunderbird.spec b/thunderbird.spec index 2fd6ea0..099b941 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -122,6 +122,7 @@ Patch226: rhbz-1354671.patch Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch Patch416: firefox-SIOCGSTAMP.patch Patch417: build-aarch64-user_vfp.patch +Patch418: mozilla-1512162.patch Patch103: rhbz-1219542-s390-build.patch Patch105: thunderbird-debug.patch @@ -269,6 +270,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %endif %patch416 -p1 -b .SIOCGSTAMP %patch417 -p1 -b .aarch64-user_vfp +%patch418 -p1 -b .mozbz-1512162 %patch306 -p1 -b .1353817 %if 0%{?disable_elfhack} From 200befb61d0a9bffea6510b34969a542130b463b Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Thu, 26 Sep 2019 10:21:55 +0200 Subject: [PATCH 080/402] Allow profile downgrade --- thunderbird.sh.in | 3 +++ thunderbird.spec | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/thunderbird.sh.in b/thunderbird.sh.in index f25f264..8f283d8 100644 --- a/thunderbird.sh.in +++ b/thunderbird.sh.in @@ -153,4 +153,7 @@ do esac done +# Don't throw "old profile" dialog box. +export MOZ_ALLOW_DOWNGRADE=1 + exec $MOZ_PROGRAM "$@" diff --git a/thunderbird.spec b/thunderbird.spec index 099b941..9fb5f58 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.1.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -748,6 +748,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Sep 26 2019 Martin Stransky - 68.1.0-2 +- Allow profile downgrade + * Thu Sep 12 2019 Jan Horak - 68.1.0-1 - Update to 68.1.0 From 38abd39b8978b9b5857f7f296e46168437f3f306 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 27 Sep 2019 14:30:34 +0200 Subject: [PATCH 081/402] Update to 68.1.1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 384b94c..76745b0 100644 --- a/.gitignore +++ b/.gitignore @@ -261,3 +261,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.1.0.source.tar.xz /thunderbird-langpacks-68.1.0-20190912.tar.xz /lightning-langpacks-68.1.0.tar.xz +/thunderbird-68.1.1.source.tar.xz +/thunderbird-langpacks-68.1.1-20190927.tar.xz +/lightning-langpacks-68.1.1.tar.xz diff --git a/sources b/sources index 945e452..c405f6c 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.1.0.source.tar.xz) = eb2a71bbf4b87ee1156f32b3829cf6970855187f9e60f5003bd3f3680b53b80f34220ed2575c26834bc2960b2c85b2b53c2ee5437b4c19031f94eae5ca9a010c -SHA512 (thunderbird-langpacks-68.1.0-20190912.tar.xz) = 8d96e56d224e1788225b3ad59ae3579409d451ad14395d37b5cbe41216bd6c91059ababe5298db742306e63aec2176f2564e6ab578b168e44945561a75e6054a -SHA512 (lightning-langpacks-68.1.0.tar.xz) = c371106520f128c33687e37d82b212dfdbecc083626f7ceb00fb260935e7c3b158e358ad4d30243b0c540f4a6b98b77290e57358efa4f0832d14d9c329a44d11 +SHA512 (thunderbird-68.1.1.source.tar.xz) = 946b9694c93bcd416fb2fe1f2448c7304d97a9b8dada9921ea5790cac019b0a53da2666eb974eb416bffd9f7874a51650563daa4dee97fef1091ac3b8df3f2ac +SHA512 (thunderbird-langpacks-68.1.1-20190927.tar.xz) = 4935ff7a4cb939cf184d2d1c337b5b380a716c27ec7fdbf35c61755bc11d77afac83005dd30df7eb8b26dd65ec3cdb33b98229be7803dfe32fbfcae9544a7bd5 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d +SHA512 (lightning-langpacks-68.1.1.tar.xz) = 178b23a38f3a8f9b89c015cf37d945a6ee1a9a65afc32ee0345895afa30154e1564040f4133389122bafdd1da108fe49582e82ca66537fd13956d2034f0a8187 diff --git a/thunderbird.spec b/thunderbird.spec index 9fb5f58..728b8df 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.1.0 -Release: 2%{?dist} +Version: 68.1.1 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190912.tar.xz +Source1: thunderbird-langpacks-%{version}-20190927.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -748,6 +748,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Fri Sep 27 2019 Jan Horak - 68.1.1-1 +- Update to 68.1.1 + * Thu Sep 26 2019 Martin Stransky - 68.1.0-2 - Allow profile downgrade From b27bc1043764e75f4e55e4439df7ac966de12584 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 2 Oct 2019 17:24:01 +0200 Subject: [PATCH 082/402] Don't compare buildID in upgradepath because builds in newer distro can be build sooner than in previous one. --- rh-old-version-check.patch | 20 ++++++++++++++++++++ thunderbird.spec | 9 ++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 rh-old-version-check.patch diff --git a/rh-old-version-check.patch b/rh-old-version-check.patch new file mode 100644 index 0000000..b83f34b --- /dev/null +++ b/rh-old-version-check.patch @@ -0,0 +1,20 @@ +diff -up firefox-69.0/toolkit/xre/nsAppRunner.cpp.old-version-check firefox-69.0/toolkit/xre/nsAppRunner.cpp +--- firefox-69.0/toolkit/xre/nsAppRunner.cpp.old-version-check 2019-10-02 16:58:38.018077162 +0200 ++++ firefox-69.0/toolkit/xre/nsAppRunner.cpp 2019-10-02 16:59:57.955339034 +0200 +@@ -2453,13 +2453,9 @@ int32_t CompareCompatVersions(const nsAC + return result; + } + +- // Fall back to build ID comparison. +- result = CompareBuildIDs(oldAppBuildID, newAppBuildID); +- if (result != 0) { +- return result; +- } +- +- return CompareBuildIDs(oldPlatformBuildID, newPlatformBuildID); ++ // Don't compare build ids because the build time can be older on the ++ // newer distribution package. ++ return 0; + } + + /** diff --git a/thunderbird.spec b/thunderbird.spec index 728b8df..8da222b 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.1.1 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -133,10 +133,12 @@ Patch306: mozilla-1353817.patch Patch307: build-disable-elfhack.patch # Fedora specific patches +Patch200: rh-old-version-check.patch # Upstream patches Patch402: mozilla-526293.patch + %if %{official_branding} # Required by Mozilla Corporation @@ -280,6 +282,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch402 -p1 -b .526293 +%patch200 -p1 -b .old-version-check %if %{official_branding} # Required by Mozilla Corporation @@ -748,6 +751,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Oct 2 2019 Jan Horak - 68.1.1-2 +- Do not compare buildID to check for older version because + it could cause problems after distro upgrade + * Fri Sep 27 2019 Jan Horak - 68.1.1-1 - Update to 68.1.1 From f8d78db48fbe1af1df5edf57458fdee3955e7c2a Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 3 Oct 2019 10:24:50 +0200 Subject: [PATCH 083/402] Revert "Don't compare buildID in upgradepath because builds in newer distro can be build sooner than in previous one." This reverts commit b27bc1043764e75f4e55e4439df7ac966de12584. --- rh-old-version-check.patch | 20 -------------------- thunderbird.spec | 9 +-------- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 rh-old-version-check.patch diff --git a/rh-old-version-check.patch b/rh-old-version-check.patch deleted file mode 100644 index b83f34b..0000000 --- a/rh-old-version-check.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff -up firefox-69.0/toolkit/xre/nsAppRunner.cpp.old-version-check firefox-69.0/toolkit/xre/nsAppRunner.cpp ---- firefox-69.0/toolkit/xre/nsAppRunner.cpp.old-version-check 2019-10-02 16:58:38.018077162 +0200 -+++ firefox-69.0/toolkit/xre/nsAppRunner.cpp 2019-10-02 16:59:57.955339034 +0200 -@@ -2453,13 +2453,9 @@ int32_t CompareCompatVersions(const nsAC - return result; - } - -- // Fall back to build ID comparison. -- result = CompareBuildIDs(oldAppBuildID, newAppBuildID); -- if (result != 0) { -- return result; -- } -- -- return CompareBuildIDs(oldPlatformBuildID, newPlatformBuildID); -+ // Don't compare build ids because the build time can be older on the -+ // newer distribution package. -+ return 0; - } - - /** diff --git a/thunderbird.spec b/thunderbird.spec index 8da222b..728b8df 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.1.1 -Release: 2%{?dist} +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -133,12 +133,10 @@ Patch306: mozilla-1353817.patch Patch307: build-disable-elfhack.patch # Fedora specific patches -Patch200: rh-old-version-check.patch # Upstream patches Patch402: mozilla-526293.patch - %if %{official_branding} # Required by Mozilla Corporation @@ -282,7 +280,6 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch402 -p1 -b .526293 -%patch200 -p1 -b .old-version-check %if %{official_branding} # Required by Mozilla Corporation @@ -751,10 +748,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog -* Wed Oct 2 2019 Jan Horak - 68.1.1-2 -- Do not compare buildID to check for older version because - it could cause problems after distro upgrade - * Fri Sep 27 2019 Jan Horak - 68.1.1-1 - Update to 68.1.1 From eb8931b4ab33c0185301a32b39d3e78ecb81ccff Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 3 Oct 2019 10:27:09 +0200 Subject: [PATCH 084/402] Allow downgrade because during distro upgrade the build time can be older in newer version than the previous one. --- thunderbird.sh.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/thunderbird.sh.in b/thunderbird.sh.in index 8f283d8..110ead1 100644 --- a/thunderbird.sh.in +++ b/thunderbird.sh.in @@ -59,6 +59,12 @@ export GNOME_DISABLE_CRASH_DIALOG ## export G_SLICE=always-malloc +## +## Allow downgrade because during distro upgrade the build time can be +## older in newer version than the previous one. +## +export MOZ_ALLOW_DOWNGRADE=1 + ## ## To disable the use of Firefox localization, set MOZ_DISABLE_LANGPACKS=1 ## in your environment before launching Firefox. From 9b0e86bea54b755d15a7d56824e1943d4e8d14f5 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 3 Oct 2019 10:44:01 +0200 Subject: [PATCH 085/402] Bump release for the rebuild --- thunderbird.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 728b8df..421d087 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.1.1 -Release: 1%{?dist} +Release: 3%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -748,6 +748,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Oct 3 2019 Jan Horak - 68.1.1-3 +- Allow downgrades of the profile because after distro upgrade there is a chance + that the the downgrade refusal dialog is shown. + * Fri Sep 27 2019 Jan Horak - 68.1.1-1 - Update to 68.1.1 From 292635b40d0d53762b099aa07fba3562ff3fef9d Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 23 Oct 2019 16:30:27 +0200 Subject: [PATCH 086/402] added symbolic icon --- thunderbird-symbolic.svg | 76 ++++++++++++++++++++++++++++++++++++++++ thunderbird.spec | 7 ++++ 2 files changed, 83 insertions(+) create mode 100644 thunderbird-symbolic.svg diff --git a/thunderbird-symbolic.svg b/thunderbird-symbolic.svg new file mode 100644 index 0000000..9387527 --- /dev/null +++ b/thunderbird-symbolic.svg @@ -0,0 +1,76 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/thunderbird.spec b/thunderbird.spec index 421d087..7378ff8 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -111,6 +111,7 @@ Source11: thunderbird-mozconfig-branded Source12: thunderbird-redhat-default-prefs.js Source20: thunderbird.desktop Source21: thunderbird.sh.in +Source25: thunderbird-symbolic.svg Source28: thunderbird-wayland.sh.in Source29: thunderbird-wayland.desktop Source32: node-stdout-nonblocking-wrapper @@ -545,6 +546,11 @@ for s in 16 22 24 32 48 64 128 256; do $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${s}x${s}/apps/thunderbird.png done +# Install hight contrast icon +%{__mkdir_p} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +%{__cp} -p %{SOURCE25} \ + %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps + desktop-file-install --vendor mozilla \ --dir $RPM_BUILD_ROOT%{_datadir}/applications \ @@ -730,6 +736,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{_datadir}/icons/hicolor/48x48/apps/thunderbird.png %{_datadir}/icons/hicolor/64x64/apps/thunderbird.png %{_datadir}/icons/hicolor/128x128/apps/thunderbird.png +%{_datadir}/icons/hicolor/symbolic/apps/thunderbird-symbolic.svg %if %{enable_mozilla_crashreporter} %{mozappdir}/crashreporter %{mozappdir}/crashreporter.ini From 08c8f2c7db0eaa92b2630ee33de11dd82c04e6e5 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 23 Oct 2019 22:46:58 +0200 Subject: [PATCH 087/402] Added symbolic icon --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 7378ff8..3d8a3b8 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.1.1 -Release: 3%{?dist} +Release: 4%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -755,6 +755,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Oct 23 2019 Jan Horak - 68.1.1-4 +- Added symbolic icon + * Thu Oct 3 2019 Jan Horak - 68.1.1-3 - Allow downgrades of the profile because after distro upgrade there is a chance that the the downgrade refusal dialog is shown. From 3197fda1e5300a736ff4fe57c1882ed06540ef96 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 29 Oct 2019 12:58:15 +0100 Subject: [PATCH 088/402] Update to 68.2 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 76745b0..a6b02b1 100644 --- a/.gitignore +++ b/.gitignore @@ -264,3 +264,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.1.1.source.tar.xz /thunderbird-langpacks-68.1.1-20190927.tar.xz /lightning-langpacks-68.1.1.tar.xz +/thunderbird-68.2.0.source.tar.xz +/thunderbird-langpacks-68.2.0-20191029.tar.xz +/lightning-langpacks-68.2.0.tar.xz diff --git a/sources b/sources index c405f6c..c927d93 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.1.1.source.tar.xz) = 946b9694c93bcd416fb2fe1f2448c7304d97a9b8dada9921ea5790cac019b0a53da2666eb974eb416bffd9f7874a51650563daa4dee97fef1091ac3b8df3f2ac -SHA512 (thunderbird-langpacks-68.1.1-20190927.tar.xz) = 4935ff7a4cb939cf184d2d1c337b5b380a716c27ec7fdbf35c61755bc11d77afac83005dd30df7eb8b26dd65ec3cdb33b98229be7803dfe32fbfcae9544a7bd5 +SHA512 (thunderbird-68.2.0.source.tar.xz) = ca9afc870245dfaaabe3c75d4db266596c9dd714ea20b775b80e5d9df4671a5c71d2af84c734e27e07efcdb6f0fac0c34b48fda45a5a64e3e092bdafea474efc +SHA512 (thunderbird-langpacks-68.2.0-20191029.tar.xz) = 6fbcb25f52d196d9a0f78e1bac0b5d048ad7262d160d5756ad035b722581adf8a938d3e7a33f17f288d144d1afef3738e8849c73407f592557e68329ce41960e SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.1.1.tar.xz) = 178b23a38f3a8f9b89c015cf37d945a6ee1a9a65afc32ee0345895afa30154e1564040f4133389122bafdd1da108fe49582e82ca66537fd13956d2034f0a8187 +SHA512 (lightning-langpacks-68.2.0.tar.xz) = d91e8729224382f67bf5eb8c539f56ddcfb88a80d91a78a0a2fb7908e5eef3a7b69467e2d971e0a6a7187e102661146e3fb88e5ffcccf912db1dde66483b6405 diff --git a/thunderbird.spec b/thunderbird.spec index 3d8a3b8..4ee0918 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.1.1 -Release: 4%{?dist} +Version: 68.2.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20190927.tar.xz +Source1: thunderbird-langpacks-%{version}-20191029.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -755,6 +755,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Oct 29 2019 Jan Horak - 68.2.0-1 +- Update to 68.2.0 + * Wed Oct 23 2019 Jan Horak - 68.1.1-4 - Added symbolic icon From 80acbfc5224677a5cbdc9816c1c6b2469496a8b5 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 1 Nov 2019 12:58:19 +0100 Subject: [PATCH 089/402] Update to 68.2.1 build 1 --- .gitignore | 3 +++ sources | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index a6b02b1..b1f99fe 100644 --- a/.gitignore +++ b/.gitignore @@ -267,3 +267,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.2.0.source.tar.xz /thunderbird-langpacks-68.2.0-20191029.tar.xz /lightning-langpacks-68.2.0.tar.xz +/thunderbird-68.2.1.source.tar.xz +/thunderbird-langpacks-68.2.1-20191101.tar.xz +/lightning-langpacks-68.2.1.tar.xz diff --git a/sources b/sources index c927d93..24d52cd 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.2.0.source.tar.xz) = ca9afc870245dfaaabe3c75d4db266596c9dd714ea20b775b80e5d9df4671a5c71d2af84c734e27e07efcdb6f0fac0c34b48fda45a5a64e3e092bdafea474efc -SHA512 (thunderbird-langpacks-68.2.0-20191029.tar.xz) = 6fbcb25f52d196d9a0f78e1bac0b5d048ad7262d160d5756ad035b722581adf8a938d3e7a33f17f288d144d1afef3738e8849c73407f592557e68329ce41960e +SHA512 (thunderbird-68.2.1.source.tar.xz) = 2d921cac84f6f09b63c122e54fff7848ff0d0997c8c5fedd87503e487750aa2cde8d117e1a0cdbfbf042cc364554bfd4c81b639635a03d656c62e934b973da7c +SHA512 (thunderbird-langpacks-68.2.1-20191101.tar.xz) = 23e2b57247dd20d82a9098a741522914614c39a8a21e6e91f1db56fcbb1f123b0f1b7496e71ced08254eb4d38fae9a9c664a3a474ad498e9d450e6eb9d83f79f SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.2.0.tar.xz) = d91e8729224382f67bf5eb8c539f56ddcfb88a80d91a78a0a2fb7908e5eef3a7b69467e2d971e0a6a7187e102661146e3fb88e5ffcccf912db1dde66483b6405 +SHA512 (lightning-langpacks-68.2.1.tar.xz) = c03b33ec484144d5bbfe27d2bae5874a06f9e070cfae7f3c4c467105ed0696a454c1c8669829c5d7103fb9059899b095ecc7fde5acc3d9586306f6a930f8c885 From dbc5b536c6daccb88dfe8cd272b36518cdc40ece Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 1 Nov 2019 12:59:57 +0100 Subject: [PATCH 090/402] Added spec file changes --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 4ee0918..d3bed30 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,7 +93,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.2.0 +Version: 68.2.1 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ @@ -755,6 +755,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Fri Nov 01 2019 Jan Horak - 68.2.1-1 +- Update to 68.2.1 build1 + * Tue Oct 29 2019 Jan Horak - 68.2.0-1 - Update to 68.2.0 From dbd644ff772c4f1a7c0c788de695f440f6b3706c Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 1 Nov 2019 13:35:37 +0100 Subject: [PATCH 091/402] fixing langpacks filename --- thunderbird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index d3bed30..b19e700 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -99,7 +99,7 @@ URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20191029.tar.xz +Source1: thunderbird-langpacks-%{version}-20191101.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif From 1818d680c532fef9c29169661b4a15d8cf7f95e9 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 5 Nov 2019 19:25:18 +0100 Subject: [PATCH 092/402] Update to 68.2.2 build 1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index b1f99fe..0873fd2 100644 --- a/.gitignore +++ b/.gitignore @@ -270,3 +270,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.2.1.source.tar.xz /thunderbird-langpacks-68.2.1-20191101.tar.xz /lightning-langpacks-68.2.1.tar.xz +/thunderbird-68.2.2.source.tar.xz +/thunderbird-langpacks-68.2.2-20191105.tar.xz +/lightning-langpacks-68.2.2.tar.xz diff --git a/sources b/sources index 24d52cd..92924cb 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.2.1.source.tar.xz) = 2d921cac84f6f09b63c122e54fff7848ff0d0997c8c5fedd87503e487750aa2cde8d117e1a0cdbfbf042cc364554bfd4c81b639635a03d656c62e934b973da7c -SHA512 (thunderbird-langpacks-68.2.1-20191101.tar.xz) = 23e2b57247dd20d82a9098a741522914614c39a8a21e6e91f1db56fcbb1f123b0f1b7496e71ced08254eb4d38fae9a9c664a3a474ad498e9d450e6eb9d83f79f +SHA512 (thunderbird-68.2.2.source.tar.xz) = 96c9d7b7820091896b174e2c7924e426fa0fd2e6edfa8268ab502c1292a7456d3d864f97976cced0a5e9587bfa2dd92023df1a52f989729a92e0ca604e5ab5eb +SHA512 (thunderbird-langpacks-68.2.2-20191105.tar.xz) = 75c3f5a117d60e8ea0ca8c744374c2f7dd67e544bb80699082f714cd4c0640292959138db4ce45b91279d1df93199071d0b9d5a6cb341a87b95c4d2748d545f4 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.2.1.tar.xz) = c03b33ec484144d5bbfe27d2bae5874a06f9e070cfae7f3c4c467105ed0696a454c1c8669829c5d7103fb9059899b095ecc7fde5acc3d9586306f6a930f8c885 +SHA512 (lightning-langpacks-68.2.2.tar.xz) = 5dcddeab50835b8010f1e19fe4b1248b4c7df62e0167e100adb897241469411be8351ea18038b39ba1ce1401dd9a1b840f3c644ab1cb63261f3ee5359ca9825a diff --git a/thunderbird.spec b/thunderbird.spec index b19e700..7cb4dc3 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.2.1 +Version: 68.2.2 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20191101.tar.xz +Source1: thunderbird-langpacks-%{version}-20191105.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -755,6 +755,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Nov 05 2019 Jan Horak - 68.2.2-1 +- Update to 68.2.2 build1 + * Fri Nov 01 2019 Jan Horak - 68.2.1-1 - Update to 68.2.1 build1 From d71cf7432cc509e51b3d7f0f13f5bf93499a40f4 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 3 Dec 2019 12:49:00 +0100 Subject: [PATCH 093/402] Update to 68.3.0 build2 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 0873fd2..bc56042 100644 --- a/.gitignore +++ b/.gitignore @@ -273,3 +273,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.2.2.source.tar.xz /thunderbird-langpacks-68.2.2-20191105.tar.xz /lightning-langpacks-68.2.2.tar.xz +/thunderbird-68.3.0.source.tar.xz +/thunderbird-langpacks-68.3.0-20191203.tar.xz +/lightning-langpacks-68.3.0.tar.xz diff --git a/sources b/sources index 92924cb..7ea25c4 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.2.2.source.tar.xz) = 96c9d7b7820091896b174e2c7924e426fa0fd2e6edfa8268ab502c1292a7456d3d864f97976cced0a5e9587bfa2dd92023df1a52f989729a92e0ca604e5ab5eb -SHA512 (thunderbird-langpacks-68.2.2-20191105.tar.xz) = 75c3f5a117d60e8ea0ca8c744374c2f7dd67e544bb80699082f714cd4c0640292959138db4ce45b91279d1df93199071d0b9d5a6cb341a87b95c4d2748d545f4 +SHA512 (thunderbird-68.3.0.source.tar.xz) = 94474f91a4e7b927b94698340c31015fda6f25533ec2a4aad0712bd6d2f9a528184345ed7ddb0ff25e207375391a5c6252506538e4a4992614cd152db28d8cd5 +SHA512 (thunderbird-langpacks-68.3.0-20191203.tar.xz) = a1f3931ddd7290e7e063b273515c5bb9307ce28045150b445af46f37d0f9ed96c8e86547271c384f6de8020fb07a9d5bb3744e824c2ceb1cb2d6ff3b8ccdc009 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.2.2.tar.xz) = 5dcddeab50835b8010f1e19fe4b1248b4c7df62e0167e100adb897241469411be8351ea18038b39ba1ce1401dd9a1b840f3c644ab1cb63261f3ee5359ca9825a +SHA512 (lightning-langpacks-68.3.0.tar.xz) = 88df26a4ea8214946ba738be79eb3aef09fd57fb5febbd56e92511dab2caa549d1d60dea313eec834225321d36752bd32d9f95fa29291663818a4314b4252a1c diff --git a/thunderbird.spec b/thunderbird.spec index 7cb4dc3..0dae2fc 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.2.2 +Version: 68.3.0 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20191105.tar.xz +Source1: thunderbird-langpacks-%{version}-20191203.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -755,6 +755,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Dec 03 2019 Jan Horak - 68.3.0-1 +- Update to 68.3.0 build2 + * Tue Nov 05 2019 Jan Horak - 68.2.2-1 - Update to 68.2.2 build1 From d6ceee7d72d72fb2d2b5c4ab87ed4caddcb804df Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 4 Dec 2019 14:03:32 +0100 Subject: [PATCH 094/402] Added fix for bindgen --- ...c52706f23db9dc9d74642eeebd89d73cb8d0.patch | 171 ++++++++++++++++++ thunderbird.spec | 2 + 2 files changed, 173 insertions(+) create mode 100644 bindgen-d0dfc52706f23db9dc9d74642eeebd89d73cb8d0.patch diff --git a/bindgen-d0dfc52706f23db9dc9d74642eeebd89d73cb8d0.patch b/bindgen-d0dfc52706f23db9dc9d74642eeebd89d73cb8d0.patch new file mode 100644 index 0000000..0968827 --- /dev/null +++ b/bindgen-d0dfc52706f23db9dc9d74642eeebd89d73cb8d0.patch @@ -0,0 +1,171 @@ +diff -up thunderbird-68.3.0/third_party/rust/bindgen/.cargo-checksum.json.bindgen thunderbird-68.3.0/third_party/rust/bindgen/.cargo-checksum.json +--- thunderbird-68.3.0/third_party/rust/bindgen/.cargo-checksum.json.bindgen 2019-12-01 15:29:26.000000000 +0100 ++++ thunderbird-68.3.0/third_party/rust/bindgen/.cargo-checksum.json 2019-12-04 11:38:42.878975886 +0100 +@@ -1 +1 @@ +-{"files":{"Cargo.toml":"9af635e7bad9021a49742a312faf6178b757dbd48aabc998931d6f491f14c179","LICENSE":"c23953d9deb0a3312dbeaf6c128a657f3591acee45067612fa68405eaa4525db","README.md":"5a1f556c6a57c0a6ccc65e19c27718e0f4b32381a8efcc80f6601b33c58c5d59","build.rs":"a9f6915c54d75f357ce32f96327bf4df53dc81a505b70831978f9dac6f43841d","src/callbacks.rs":"b24d7982332c6a35928f134184ddf4072fe4545a45546b97b9b0e0c1fbb77c08","src/clang.rs":"e9203eb5a1b432efebafcd011896e35e8c9145037bf99e7bb3709dc1b8e8e783","src/codegen/bitfield_unit.rs":"88b0604322dc449fc9284850eadc1f5d14b42fa747d4258bae0b6b9535f52dfd","src/codegen/bitfield_unit_tests.rs":"2073ac6a36e0bc9afaef5b1207966817c8fb7a1a9f6368c3b1b8f79822efbfba","src/codegen/error.rs":"2613af1d833377fd4a70719f4a09951d9d45dc9227827b9a2a938a1bcaaea2dd","src/codegen/helpers.rs":"fbd23e68dd51ccaddeb9761394d5df2db49baded0e2dccf6bbc52a2d6de502eb","src/codegen/impl_debug.rs":"f82969461d522fb758eca552ceaf189122a404cbb47fcc16008bfe52fc62aefa","src/codegen/impl_partialeq.rs":"d40d9ee2849c4d3d557b033c4d3af5e6de4a44347f67c0f016198086338811af","src/codegen/mod.rs":"238d989e13b7556e5d120a2bfe85b43332fba56cbe8df886d4c32e650fff1247","src/codegen/struct_layout.rs":"3fa5524aff82365ce292b0cc85080514c85a6dbd31bce90f001773b995dda28e","src/extra_assertions.rs":"494534bd4f18b80d89b180c8a93733e6617edcf7deac413e9a73fd6e7bc9ced7","src/features.rs":"c5fd7149f4a3b41fd4f89ade08505170942f4bc791bcb6a34fdddd3ae61856f8","src/ir/analysis/derive.rs":"325d4c1c1e6194e743f42a2316f1501b0ef852fe309f2e9cac3434825ad235f0","src/ir/analysis/has_destructor.rs":"63644f479738df35e531d3324ff892614083c3656e0747aa34d9f20dada878ec","src/ir/analysis/has_float.rs":"76162a309e4285a806755a08c687a3e7bc894a100a63da4e88584035e215b11d","src/ir/analysis/has_type_param_in_array.rs":"fdbc0af28a144c88ea2de83e6e6da5e1ffb40e3dd63fd7a708095d085bb06f94","src/ir/analysis/has_vtable.rs":"5788372d27bdbaaf0454bc17be31a5480918bc41a8a1c4832e8c61185c07f9cd","src/ir/analysis/mod.rs":"1f218e15c19f6666512908abc853fa7ff9ca5d0fafd94f026d9e4b0ce287ec3c","src/ir/analysis/sizedness.rs":"8dc10043d872e68e660ef96edca4d9733f95be45cdad4893462fa929b335014f","src/ir/analysis/template_params.rs":"6312c008bbc80f50e72a766756c8daddea0b6eeb31ec924b83a231df931e170e","src/ir/annotations.rs":"39a5ab19f4d5dfa617577e4a0d0d2b67b5369d480c7cca4b14d172458c9843f0","src/ir/comment.rs":"c48abe01c5af0f09f583a89f1394bc6c161b40f6c8f0f600bbfe3c907b47969b","src/ir/comp.rs":"ca439407faefbe3a198246f0a1dbdf4e40307e45eaaad317e85d1aab37bb31fc","src/ir/context.rs":"599226eb04d337a1b1b13af91af91bdb02dbd5f26f274cbc0ebc4489eb144fc0","src/ir/derive.rs":"34f9aa76b6c9c05136bb69dcd6455397faef571a567254d2c541d50a962994db","src/ir/dot.rs":"95ed2968fc3239d87892e9f1edf1ed6dd18630d949564961765967ea1d16960c","src/ir/enum_ty.rs":"9cc242d6b3c1866665594e8b306860ee39c0ea42d22198d46b7fded473fe3e84","src/ir/function.rs":"2d41d9df19f42b0c383f338be4c026c005853a8d1caf5f3e5a2f3a8dad202232","src/ir/int.rs":"07e0c7dbd2dd977177fae3acd2a14adf271c6cf9ff4b57cddc11d50734fd4801","src/ir/item.rs":"3bcdb69b793350e5744aec3577cdbb1e5068ece5220c38763cecd82dfb5e8f03","src/ir/item_kind.rs":"dbeae8c4fd0e5c9485d325aea040e056a1f2cd6d43fc927dee8fe1c0c59a7197","src/ir/layout.rs":"d49582081f5f86f7595afbe4845f38fb3b969a840b568f4a49b265e7d790bb5b","src/ir/mod.rs":"2eae90f207fad2e45957ec9287064992a419e3fc916aba84faff2ea25cbeb5ee","src/ir/module.rs":"c4d90bf38fe3672e01923734ccbdb7951ea929949d5f413a9c2aee12395a5094","src/ir/objc.rs":"758aa955a0c5d6ad82606c88a1f4cd1d93e666b71e82d43b18b1aaae96cf888a","src/ir/template.rs":"c0f8570b927dfd6a421fc4ce3094ec837a3ed936445225dbfac961e8e0842ae5","src/ir/traversal.rs":"ea751379a5aec02f93f8d2c61e18232776b1f000dbeae64b9a7195ba21a19dd6","src/ir/ty.rs":"952fb04cd6a71a2bca5c509aecacb42a1de0cae75824941541a38dc589f0993a","src/ir/var.rs":"8bdafb6d02f2c55ae11c28d88b19fb7a65ba8466da12ff039ae4c16c790b291e","src/lib.rs":"d5c8b404c515d30fc2d78b28eb84cff6b256f1f1e2dbd6aca280529bb2af6879","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"e519053bcdde6bc88f60f955246a02d53b3db1cc5ccd1612e6675b790b7460b0","src/options.rs":"041d635c8f6712ca32676a68f06d0245faed5577d9513786e058540ea2a69a7f","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"5cb72fc3714c0d79e9e942d003349c0775fafd7cd0c9603c65f5261883bbf9cf","src/time.rs":"3b763e6fee51d0eb01228dfe28bc28a9f692aff73b2a7b90a030902e0238fca6"},"package":"6bd7710ac8399ae1ebe1e3aac7c9047c4f39f2c94b33c997f482f49e96991f7c"} +\ No newline at end of file ++{"files":{"Cargo.toml":"9af635e7bad9021a49742a312faf6178b757dbd48aabc998931d6f491f14c179","LICENSE":"c23953d9deb0a3312dbeaf6c128a657f3591acee45067612fa68405eaa4525db","README.md":"5a1f556c6a57c0a6ccc65e19c27718e0f4b32381a8efcc80f6601b33c58c5d59","build.rs":"a9f6915c54d75f357ce32f96327bf4df53dc81a505b70831978f9dac6f43841d","src/callbacks.rs":"b24d7982332c6a35928f134184ddf4072fe4545a45546b97b9b0e0c1fbb77c08","src/clang.rs":"e9203eb5a1b432efebafcd011896e35e8c9145037bf99e7bb3709dc1b8e8e783","src/codegen/bitfield_unit.rs":"88b0604322dc449fc9284850eadc1f5d14b42fa747d4258bae0b6b9535f52dfd","src/codegen/bitfield_unit_tests.rs":"2073ac6a36e0bc9afaef5b1207966817c8fb7a1a9f6368c3b1b8f79822efbfba","src/codegen/error.rs":"2613af1d833377fd4a70719f4a09951d9d45dc9227827b9a2a938a1bcaaea2dd","src/codegen/helpers.rs":"fbd23e68dd51ccaddeb9761394d5df2db49baded0e2dccf6bbc52a2d6de502eb","src/codegen/impl_debug.rs":"f82969461d522fb758eca552ceaf189122a404cbb47fcc16008bfe52fc62aefa","src/codegen/impl_partialeq.rs":"d40d9ee2849c4d3d557b033c4d3af5e6de4a44347f67c0f016198086338811af","src/codegen/mod.rs":"238d989e13b7556e5d120a2bfe85b43332fba56cbe8df886d4c32e650fff1247","src/codegen/struct_layout.rs":"3fa5524aff82365ce292b0cc85080514c85a6dbd31bce90f001773b995dda28e","src/extra_assertions.rs":"494534bd4f18b80d89b180c8a93733e6617edcf7deac413e9a73fd6e7bc9ced7","src/features.rs":"c5fd7149f4a3b41fd4f89ade08505170942f4bc791bcb6a34fdddd3ae61856f8","src/ir/analysis/derive.rs":"325d4c1c1e6194e743f42a2316f1501b0ef852fe309f2e9cac3434825ad235f0","src/ir/analysis/has_destructor.rs":"63644f479738df35e531d3324ff892614083c3656e0747aa34d9f20dada878ec","src/ir/analysis/has_float.rs":"76162a309e4285a806755a08c687a3e7bc894a100a63da4e88584035e215b11d","src/ir/analysis/has_type_param_in_array.rs":"fdbc0af28a144c88ea2de83e6e6da5e1ffb40e3dd63fd7a708095d085bb06f94","src/ir/analysis/has_vtable.rs":"8c92a52c0f859c7bec7bfbc36b9d18f904baab0c8c9dc1b3e7af34de1a0b0da4","src/ir/analysis/mod.rs":"1f218e15c19f6666512908abc853fa7ff9ca5d0fafd94f026d9e4b0ce287ec3c","src/ir/analysis/sizedness.rs":"71f1a37f75b971ea5b0d8457473cc410947dbf706cb6d2c0338916910b78a675","src/ir/analysis/template_params.rs":"6312c008bbc80f50e72a766756c8daddea0b6eeb31ec924b83a231df931e170e","src/ir/annotations.rs":"39a5ab19f4d5dfa617577e4a0d0d2b67b5369d480c7cca4b14d172458c9843f0","src/ir/comment.rs":"c48abe01c5af0f09f583a89f1394bc6c161b40f6c8f0f600bbfe3c907b47969b","src/ir/comp.rs":"ca439407faefbe3a198246f0a1dbdf4e40307e45eaaad317e85d1aab37bb31fc","src/ir/context.rs":"599226eb04d337a1b1b13af91af91bdb02dbd5f26f274cbc0ebc4489eb144fc0","src/ir/derive.rs":"e5581852eec87918901a129284b4965aefc8a19394187a8095779a084f28fabe","src/ir/dot.rs":"95ed2968fc3239d87892e9f1edf1ed6dd18630d949564961765967ea1d16960c","src/ir/enum_ty.rs":"9cc242d6b3c1866665594e8b306860ee39c0ea42d22198d46b7fded473fe3e84","src/ir/function.rs":"2d41d9df19f42b0c383f338be4c026c005853a8d1caf5f3e5a2f3a8dad202232","src/ir/int.rs":"07e0c7dbd2dd977177fae3acd2a14adf271c6cf9ff4b57cddc11d50734fd4801","src/ir/item.rs":"3bcdb69b793350e5744aec3577cdbb1e5068ece5220c38763cecd82dfb5e8f03","src/ir/item_kind.rs":"dbeae8c4fd0e5c9485d325aea040e056a1f2cd6d43fc927dee8fe1c0c59a7197","src/ir/layout.rs":"d49582081f5f86f7595afbe4845f38fb3b969a840b568f4a49b265e7d790bb5b","src/ir/mod.rs":"2eae90f207fad2e45957ec9287064992a419e3fc916aba84faff2ea25cbeb5ee","src/ir/module.rs":"c4d90bf38fe3672e01923734ccbdb7951ea929949d5f413a9c2aee12395a5094","src/ir/objc.rs":"758aa955a0c5d6ad82606c88a1f4cd1d93e666b71e82d43b18b1aaae96cf888a","src/ir/template.rs":"c0f8570b927dfd6a421fc4ce3094ec837a3ed936445225dbfac961e8e0842ae5","src/ir/traversal.rs":"ea751379a5aec02f93f8d2c61e18232776b1f000dbeae64b9a7195ba21a19dd6","src/ir/ty.rs":"952fb04cd6a71a2bca5c509aecacb42a1de0cae75824941541a38dc589f0993a","src/ir/var.rs":"8bdafb6d02f2c55ae11c28d88b19fb7a65ba8466da12ff039ae4c16c790b291e","src/lib.rs":"d5c8b404c515d30fc2d78b28eb84cff6b256f1f1e2dbd6aca280529bb2af6879","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"e519053bcdde6bc88f60f955246a02d53b3db1cc5ccd1612e6675b790b7460b0","src/options.rs":"041d635c8f6712ca32676a68f06d0245faed5577d9513786e058540ea2a69a7f","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"5cb72fc3714c0d79e9e942d003349c0775fafd7cd0c9603c65f5261883bbf9cf","src/time.rs":"3b763e6fee51d0eb01228dfe28bc28a9f692aff73b2a7b90a030902e0238fca6"},"package":"6bd7710ac8399ae1ebe1e3aac7c9047c4f39f2c94b33c997f482f49e96991f7c"} +diff -up thunderbird-68.3.0/third_party/rust/bindgen/src/ir/analysis/has_vtable.rs.bindgen thunderbird-68.3.0/third_party/rust/bindgen/src/ir/analysis/has_vtable.rs +--- thunderbird-68.3.0/third_party/rust/bindgen/src/ir/analysis/has_vtable.rs.bindgen 2019-12-01 15:29:26.000000000 +0100 ++++ thunderbird-68.3.0/third_party/rust/bindgen/src/ir/analysis/has_vtable.rs 2019-12-04 11:33:09.631921359 +0100 +@@ -9,17 +9,17 @@ use std::ops; + use {HashMap, Entry}; + + /// The result of the `HasVtableAnalysis` for an individual item. +-#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord)] ++#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] + pub enum HasVtableResult { +- /// The item has a vtable, but the actual vtable pointer is in a base +- /// member. +- BaseHasVtable, ++ /// The item does not have a vtable pointer. ++ No, + + /// The item has a vtable and the actual vtable pointer is within this item. + SelfHasVtable, + +- /// The item does not have a vtable pointer. +- No ++ /// The item has a vtable, but the actual vtable pointer is in a base ++ /// member. ++ BaseHasVtable, + } + + impl Default for HasVtableResult { +@@ -28,21 +28,6 @@ impl Default for HasVtableResult { + } + } + +-impl cmp::PartialOrd for HasVtableResult { +- fn partial_cmp(&self, rhs: &Self) -> Option { +- use self::HasVtableResult::*; +- +- match (*self, *rhs) { +- (x, y) if x == y => Some(cmp::Ordering::Equal), +- (BaseHasVtable, _) => Some(cmp::Ordering::Greater), +- (_, BaseHasVtable) => Some(cmp::Ordering::Less), +- (SelfHasVtable, _) => Some(cmp::Ordering::Greater), +- (_, SelfHasVtable) => Some(cmp::Ordering::Less), +- _ => unreachable!(), +- } +- } +-} +- + impl HasVtableResult { + /// Take the least upper bound of `self` and `rhs`. + pub fn join(self, rhs: Self) -> Self { +diff -up thunderbird-68.3.0/third_party/rust/bindgen/src/ir/analysis/sizedness.rs.bindgen thunderbird-68.3.0/third_party/rust/bindgen/src/ir/analysis/sizedness.rs +--- thunderbird-68.3.0/third_party/rust/bindgen/src/ir/analysis/sizedness.rs.bindgen 2019-12-01 15:29:26.000000000 +0100 ++++ thunderbird-68.3.0/third_party/rust/bindgen/src/ir/analysis/sizedness.rs 2019-12-04 11:33:09.632921362 +0100 +@@ -22,13 +22,14 @@ use {HashMap, Entry}; + /// + /// We initially assume that all types are `ZeroSized` and then update our + /// understanding as we learn more about each type. +-#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord)] ++#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] + pub enum SizednessResult { +- /// Has some size that is known to be greater than zero. That doesn't mean +- /// it has a static size, but it is not zero sized for sure. In other words, +- /// it might contain an incomplete array or some other dynamically sized +- /// type. +- NonZeroSized, ++ /// The type is zero-sized. ++ /// ++ /// This means that if it is a C++ type, and is not being used as a base ++ /// member, then we must add an `_address` byte to enforce the ++ /// unique-address-per-distinct-object-instance rule. ++ ZeroSized, + + /// Whether this type is zero-sized or not depends on whether a type + /// parameter is zero-sized or not. +@@ -52,12 +53,11 @@ pub enum SizednessResult { + /// https://github.com/rust-lang-nursery/rust-bindgen/issues/586 + DependsOnTypeParam, + +- /// The type is zero-sized. +- /// +- /// This means that if it is a C++ type, and is not being used as a base +- /// member, then we must add an `_address` byte to enforce the +- /// unique-address-per-distinct-object-instance rule. +- ZeroSized, ++ /// Has some size that is known to be greater than zero. That doesn't mean ++ /// it has a static size, but it is not zero sized for sure. In other words, ++ /// it might contain an incomplete array or some other dynamically sized ++ /// type. ++ NonZeroSized, + } + + impl Default for SizednessResult { +@@ -66,21 +66,6 @@ impl Default for SizednessResult { + } + } + +-impl cmp::PartialOrd for SizednessResult { +- fn partial_cmp(&self, rhs: &Self) -> Option { +- use self::SizednessResult::*; +- +- match (*self, *rhs) { +- (x, y) if x == y => Some(cmp::Ordering::Equal), +- (NonZeroSized, _) => Some(cmp::Ordering::Greater), +- (_, NonZeroSized) => Some(cmp::Ordering::Less), +- (DependsOnTypeParam, _) => Some(cmp::Ordering::Greater), +- (_, DependsOnTypeParam) => Some(cmp::Ordering::Less), +- _ => unreachable!(), +- } +- } +-} +- + impl SizednessResult { + /// Take the least upper bound of `self` and `rhs`. + pub fn join(self, rhs: Self) -> Self { +diff -up thunderbird-68.3.0/third_party/rust/bindgen/src/ir/derive.rs.bindgen thunderbird-68.3.0/third_party/rust/bindgen/src/ir/derive.rs +--- thunderbird-68.3.0/third_party/rust/bindgen/src/ir/derive.rs.bindgen 2019-12-01 15:29:26.000000000 +0100 ++++ thunderbird-68.3.0/third_party/rust/bindgen/src/ir/derive.rs 2019-12-04 11:33:09.632921362 +0100 +@@ -92,10 +92,10 @@ pub trait CanDeriveOrd { + /// + /// Initially we assume that we can derive trait for all types and then + /// update our understanding as we learn more about each type. +-#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord)] ++#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] + pub enum CanDerive { +- /// No, we cannot. +- No, ++ /// Yes, we can derive automatically. ++ Yes, + + /// The only thing that stops us from automatically deriving is that + /// array with more than maximum number of elements is used. +@@ -103,8 +103,8 @@ pub enum CanDerive { + /// This means we probably can "manually" implement such trait. + Manually, + +- /// Yes, we can derive automatically. +- Yes, ++ /// No, we cannot. ++ No, + } + + impl Default for CanDerive { +@@ -113,22 +113,6 @@ impl Default for CanDerive { + } + } + +-impl cmp::PartialOrd for CanDerive { +- fn partial_cmp(&self, rhs: &Self) -> Option { +- use self::CanDerive::*; +- +- let ordering = match (*self, *rhs) { +- (x, y) if x == y => cmp::Ordering::Equal, +- (No, _) => cmp::Ordering::Greater, +- (_, No) => cmp::Ordering::Less, +- (Manually, _) => cmp::Ordering::Greater, +- (_, Manually) => cmp::Ordering::Less, +- _ => unreachable!() +- }; +- Some(ordering) +- } +-} +- + impl CanDerive { + /// Take the least upper bound of `self` and `rhs`. + pub fn join(self, rhs: Self) -> Self { diff --git a/thunderbird.spec b/thunderbird.spec index 0dae2fc..27a31e1 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -124,6 +124,7 @@ Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch Patch416: firefox-SIOCGSTAMP.patch Patch417: build-aarch64-user_vfp.patch Patch418: mozilla-1512162.patch +Patch419: bindgen-d0dfc52706f23db9dc9d74642eeebd89d73cb8d0.patch Patch103: rhbz-1219542-s390-build.patch Patch105: thunderbird-debug.patch @@ -272,6 +273,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch416 -p1 -b .SIOCGSTAMP %patch417 -p1 -b .aarch64-user_vfp %patch418 -p1 -b .mozbz-1512162 +%patch419 -p1 -b .bindgen %patch306 -p1 -b .1353817 %if 0%{?disable_elfhack} From d82e2632af69053f0ce928165c917535654697d5 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 9 Dec 2019 11:39:35 +0100 Subject: [PATCH 095/402] Added fix for mzbz#1576268 --- mozilla-1576268.patch | 17 +++++++++++++++++ thunderbird.spec | 8 ++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 mozilla-1576268.patch diff --git a/mozilla-1576268.patch b/mozilla-1576268.patch new file mode 100644 index 0000000..85fd1a8 --- /dev/null +++ b/mozilla-1576268.patch @@ -0,0 +1,17 @@ +diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp +--- a/widget/gtk/nsClipboardWayland.cpp ++++ b/widget/gtk/nsClipboardWayland.cpp +@@ -195,6 +195,12 @@ + uint32_t all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | + WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; + ++ /* Default to move D&D action (Bug 1576268). ++ */ ++ if (dnd_actions == 0) { ++ all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; ++ } ++ + wl_data_offer_set_actions(mWaylandDataOffer, all_actions, dnd_actions); + + /* Workaround Wayland D&D architecture here. To get the data_device_drop() + diff --git a/thunderbird.spec b/thunderbird.spec index 27a31e1..4366938 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.3.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -138,6 +138,7 @@ Patch307: build-disable-elfhack.patch # Upstream patches Patch402: mozilla-526293.patch +Patch403: mozilla-1576268.patch %if %{official_branding} # Required by Mozilla Corporation @@ -281,8 +282,8 @@ debug %{name}, you want to install %{name}-debuginfo instead. %endif #cd .. - %patch402 -p1 -b .526293 +%patch403 -p1 -b .1576268 %if %{official_branding} # Required by Mozilla Corporation @@ -757,6 +758,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Mon Dec 9 2019 Martin Stransky - 68.3.0-2 +- Added fix for mzbz#1576268 + * Tue Dec 03 2019 Jan Horak - 68.3.0-1 - Update to 68.3.0 build2 From 386ee352fc13756c84f45189f11746b31436f0d1 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 17 Dec 2019 13:21:59 +0100 Subject: [PATCH 096/402] Update to 68.3.1 build1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index bc56042..ba2a053 100644 --- a/.gitignore +++ b/.gitignore @@ -276,3 +276,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.3.0.source.tar.xz /thunderbird-langpacks-68.3.0-20191203.tar.xz /lightning-langpacks-68.3.0.tar.xz +/thunderbird-68.3.1.source.tar.xz +/thunderbird-langpacks-68.3.1-20191217.tar.xz +/lightning-langpacks-68.3.1.tar.xz diff --git a/sources b/sources index 7ea25c4..2930400 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.3.0.source.tar.xz) = 94474f91a4e7b927b94698340c31015fda6f25533ec2a4aad0712bd6d2f9a528184345ed7ddb0ff25e207375391a5c6252506538e4a4992614cd152db28d8cd5 -SHA512 (thunderbird-langpacks-68.3.0-20191203.tar.xz) = a1f3931ddd7290e7e063b273515c5bb9307ce28045150b445af46f37d0f9ed96c8e86547271c384f6de8020fb07a9d5bb3744e824c2ceb1cb2d6ff3b8ccdc009 +SHA512 (thunderbird-68.3.1.source.tar.xz) = 2e24556e6bed7a8d75ad56f0e94e07483e021b8b1ddafcf0dc586c17c93ba1f6994194866a37b7fe23637804c351f0c24d365d39f327f0ee591a86b9560bbb03 +SHA512 (thunderbird-langpacks-68.3.1-20191217.tar.xz) = 66e8304ab168914a5451c35900c63def14bfbeb5cac84fe4d0589d6f0cd976a1386cc13de6831b3f14afb50010ea41eda62fd6085b684f672c80adf445ff7e75 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.3.0.tar.xz) = 88df26a4ea8214946ba738be79eb3aef09fd57fb5febbd56e92511dab2caa549d1d60dea313eec834225321d36752bd32d9f95fa29291663818a4314b4252a1c +SHA512 (lightning-langpacks-68.3.1.tar.xz) = 3daffead30dd63b0f5e8e56dedac57d6a1e7e43d89537d542574988506c2f602f2fb10c7ef9c5bf687e48216699febf78eaff7bf79e09269f42248302e9b23fc diff --git a/thunderbird.spec b/thunderbird.spec index 4366938..698c26e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.3.0 -Release: 2%{?dist} +Version: 68.3.1 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20191203.tar.xz +Source1: thunderbird-langpacks-%{version}-20191217.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -758,6 +758,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Dec 17 2019 Jan Horak - 68.3.1-1 +- Update to 68.3.1 build1 + * Mon Dec 9 2019 Martin Stransky - 68.3.0-2 - Added fix for mzbz#1576268 From bf94b0d376a369998232b01a99dae068ba7edc88 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Mon, 13 Jan 2020 13:03:42 +0100 Subject: [PATCH 097/402] Update to 68.4.1 build1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 10 +++++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index ba2a053..e447a09 100644 --- a/.gitignore +++ b/.gitignore @@ -279,3 +279,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.3.1.source.tar.xz /thunderbird-langpacks-68.3.1-20191217.tar.xz /lightning-langpacks-68.3.1.tar.xz +/thunderbird-68.4.1.source.tar.xz +/thunderbird-langpacks-68.4.1-20200113.tar.xz +/lightning-langpacks-68.4.1.tar.xz diff --git a/sources b/sources index 2930400..fcd75b0 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.3.1.source.tar.xz) = 2e24556e6bed7a8d75ad56f0e94e07483e021b8b1ddafcf0dc586c17c93ba1f6994194866a37b7fe23637804c351f0c24d365d39f327f0ee591a86b9560bbb03 -SHA512 (thunderbird-langpacks-68.3.1-20191217.tar.xz) = 66e8304ab168914a5451c35900c63def14bfbeb5cac84fe4d0589d6f0cd976a1386cc13de6831b3f14afb50010ea41eda62fd6085b684f672c80adf445ff7e75 +SHA512 (thunderbird-68.4.1.source.tar.xz) = 16cccbc2313472e6312e842a28079782238cb22e72b324bebaffefa4a2fe68fec9f2173f2c83f1caccc5522ab9145884b2e2a58e97e236f7aefa4c61764e08b7 +SHA512 (thunderbird-langpacks-68.4.1-20200113.tar.xz) = 7206a4eaf275e82dc866534a6e4f5231e601cc2870b570e37b2fbf7225c82250da2806f36da50e0b7078f633812971fb08b52e33988184acc3ee127cef652cd0 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.3.1.tar.xz) = 3daffead30dd63b0f5e8e56dedac57d6a1e7e43d89537d542574988506c2f602f2fb10c7ef9c5bf687e48216699febf78eaff7bf79e09269f42248302e9b23fc +SHA512 (lightning-langpacks-68.4.1.tar.xz) = 683e3fc7a2fc546cdaaf5332f15bd984850dec51c1234661d83095d98c8848bcb5d58ada054ceefd0c63104c3f29c3d548a4964d454c4be83448b3c8435bd754 diff --git a/thunderbird.spec b/thunderbird.spec index 698c26e..314dd75 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.3.1 +Version: 68.4.1 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20191217.tar.xz +Source1: thunderbird-langpacks-%{version}-20200113.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -274,7 +274,8 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch416 -p1 -b .SIOCGSTAMP %patch417 -p1 -b .aarch64-user_vfp %patch418 -p1 -b .mozbz-1512162 -%patch419 -p1 -b .bindgen +# most likely fixed +#%patch419 -p1 -b .bindgen %patch306 -p1 -b .1353817 %if 0%{?disable_elfhack} @@ -758,6 +759,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Mon Jan 13 2020 Jan Horak - 68.4.1-1 +- Update to 68.4.1 build1 + * Tue Dec 17 2019 Jan Horak - 68.3.1-1 - Update to 68.3.1 build1 From 85d33f669f3892a8e0793af1c2e25673e90b8f46 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 31 Jan 2020 01:31:56 +0000 Subject: [PATCH 098/402] - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 314dd75..b18b78e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.4.1 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -759,6 +759,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Fri Jan 31 2020 Fedora Release Engineering - 68.4.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + * Mon Jan 13 2020 Jan Horak - 68.4.1-1 - Update to 68.4.1 build1 From b3b0357cb11e5ed3fe7cfa4157282f4df9fe7070 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 14 Feb 2020 10:26:30 +0100 Subject: [PATCH 099/402] Update to 68.5 build1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index e447a09..494d98a 100644 --- a/.gitignore +++ b/.gitignore @@ -282,3 +282,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.4.1.source.tar.xz /thunderbird-langpacks-68.4.1-20200113.tar.xz /lightning-langpacks-68.4.1.tar.xz +/thunderbird-68.5.0.source.tar.xz +/thunderbird-langpacks-68.5.0-20200213.tar.xz +/lightning-langpacks-68.5.0.tar.xz diff --git a/sources b/sources index fcd75b0..4c72108 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.4.1.source.tar.xz) = 16cccbc2313472e6312e842a28079782238cb22e72b324bebaffefa4a2fe68fec9f2173f2c83f1caccc5522ab9145884b2e2a58e97e236f7aefa4c61764e08b7 -SHA512 (thunderbird-langpacks-68.4.1-20200113.tar.xz) = 7206a4eaf275e82dc866534a6e4f5231e601cc2870b570e37b2fbf7225c82250da2806f36da50e0b7078f633812971fb08b52e33988184acc3ee127cef652cd0 +SHA512 (thunderbird-68.5.0.source.tar.xz) = bb58a398f24d89eac5b1816f9d16edadbe65cdac6542e1f6798424c7ea18eb2d4ca46bb03f54c8c365e67d1dec44d3dfb36fbe4f85afe9ad80fbcc1f2984084b +SHA512 (thunderbird-langpacks-68.5.0-20200213.tar.xz) = 764ab12f6127d5b8ac5d4d124366f2b3d13df5d006861673fd3e457a6fad8e8c866939b82945a872e227c71ef42142a716f35adc4558888c5d96cc87117bb2e3 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.4.1.tar.xz) = 683e3fc7a2fc546cdaaf5332f15bd984850dec51c1234661d83095d98c8848bcb5d58ada054ceefd0c63104c3f29c3d548a4964d454c4be83448b3c8435bd754 +SHA512 (lightning-langpacks-68.5.0.tar.xz) = 9a66bff49231080349b33f50da96e84a9e6f1a7164f4f096299fed7d3db0b98bc54af094259ebbff5b4348d280223ffb079d3806ec99805afdf1900b91c1b20e diff --git a/thunderbird.spec b/thunderbird.spec index b18b78e..143012b 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.4.1 -Release: 2%{?dist} +Version: 68.5.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200113.tar.xz +Source1: thunderbird-langpacks-%{version}-20200213.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -759,6 +759,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Feb 13 2020 Jan Horak - 68.5.0-1 +- Update to 68.5.0 build1 + * Fri Jan 31 2020 Fedora Release Engineering - 68.4.1-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild From 1215f61eb700df5b54d5c5fc32ffcf827b2fdccd Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 3 Mar 2020 09:19:28 +0100 Subject: [PATCH 100/402] fix for myspell --- thunderbird-redhat-default-prefs.js | 2 ++ thunderbird.spec | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/thunderbird-redhat-default-prefs.js b/thunderbird-redhat-default-prefs.js index b2d6969..bca1328 100644 --- a/thunderbird-redhat-default-prefs.js +++ b/thunderbird-redhat-default-prefs.js @@ -20,6 +20,8 @@ pref("extensions.autoDisableScope", 0); /* For rhbz#1024232 */ pref("ui.SpellCheckerUnderlineStyle", 1); +/* Workaround for rhbz#1753011 */ +pref("spellchecker.dictionary_path", "/usr/share/myspell"); /* Workaround for rhbz#1134876 */ pref("javascript.options.baselinejit", false); /* Workaround for rhbz#1110291 */ diff --git a/thunderbird.spec b/thunderbird.spec index 143012b..ccbe4cb 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.5.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -759,6 +759,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Mar 3 2020 David Auer - 68.5.0-2 +- Fix spellcheck (rhbz#1753011) + * Thu Feb 13 2020 Jan Horak - 68.5.0-1 - Update to 68.5.0 build1 From 830d4087d008e503905e352ac12d91ede3af9dd5 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Mon, 16 Mar 2020 16:29:10 +0100 Subject: [PATCH 101/402] Update to 68.6 build2 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 494d98a..ede6b2b 100644 --- a/.gitignore +++ b/.gitignore @@ -285,3 +285,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.5.0.source.tar.xz /thunderbird-langpacks-68.5.0-20200213.tar.xz /lightning-langpacks-68.5.0.tar.xz +/thunderbird-68.6.0.source.tar.xz +/thunderbird-langpacks-68.6.0-20200313.tar.xz +/lightning-langpacks-68.6.0.tar.xz diff --git a/sources b/sources index 4c72108..2e76f98 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.5.0.source.tar.xz) = bb58a398f24d89eac5b1816f9d16edadbe65cdac6542e1f6798424c7ea18eb2d4ca46bb03f54c8c365e67d1dec44d3dfb36fbe4f85afe9ad80fbcc1f2984084b -SHA512 (thunderbird-langpacks-68.5.0-20200213.tar.xz) = 764ab12f6127d5b8ac5d4d124366f2b3d13df5d006861673fd3e457a6fad8e8c866939b82945a872e227c71ef42142a716f35adc4558888c5d96cc87117bb2e3 +SHA512 (thunderbird-68.6.0.source.tar.xz) = 3502cc42b594eebf3511219ae8e7fb8a13594534abfe7a40ec32e5a3f60343cfab7c652b161a5f33af46bd5e6f096e3abd4a407c8b307ce4693089b471a42c3e +SHA512 (thunderbird-langpacks-68.6.0-20200313.tar.xz) = 9f4d05f327e31c98a4da964cada02852d4a179bf7b72b4502946c4f626d00aae2bbe34ebe1fa4325c361d685c7992542fc9ad992f4e8cd4e9df40af1b54ece7b SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.5.0.tar.xz) = 9a66bff49231080349b33f50da96e84a9e6f1a7164f4f096299fed7d3db0b98bc54af094259ebbff5b4348d280223ffb079d3806ec99805afdf1900b91c1b20e +SHA512 (lightning-langpacks-68.6.0.tar.xz) = 0c25befe7ffbf90c7758e770cbe8f3c84529f7f2bbf28494f7cd4624e5586a89651fb50606aa721e0195a09a858412ec26f1f6710ca5c0b2573032fced806dad diff --git a/thunderbird.spec b/thunderbird.spec index ccbe4cb..c30fcc9 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.5.0 -Release: 2%{?dist} +Version: 68.6.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200213.tar.xz +Source1: thunderbird-langpacks-%{version}-20200313.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -759,6 +759,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Fri Mar 13 2020 Jan Horak - 68.6.0-1 +- Update to 68.6.0 build2 + * Wed Mar 3 2020 David Auer - 68.5.0-2 - Fix spellcheck (rhbz#1753011) From 2830b30ead70446ab4fdd539300b9e8a40fee40e Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 9 Apr 2020 16:11:22 +0200 Subject: [PATCH 102/402] Update to 68.7 build1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index ede6b2b..6882b82 100644 --- a/.gitignore +++ b/.gitignore @@ -288,3 +288,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.6.0.source.tar.xz /thunderbird-langpacks-68.6.0-20200313.tar.xz /lightning-langpacks-68.6.0.tar.xz +/thunderbird-68.7.0.source.tar.xz +/thunderbird-langpacks-68.7.0-20200409.tar.xz +/lightning-langpacks-68.7.0.tar.xz diff --git a/sources b/sources index 2e76f98..1f6c5c5 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.6.0.source.tar.xz) = 3502cc42b594eebf3511219ae8e7fb8a13594534abfe7a40ec32e5a3f60343cfab7c652b161a5f33af46bd5e6f096e3abd4a407c8b307ce4693089b471a42c3e -SHA512 (thunderbird-langpacks-68.6.0-20200313.tar.xz) = 9f4d05f327e31c98a4da964cada02852d4a179bf7b72b4502946c4f626d00aae2bbe34ebe1fa4325c361d685c7992542fc9ad992f4e8cd4e9df40af1b54ece7b +SHA512 (thunderbird-68.7.0.source.tar.xz) = fae763030b7a54930291a10f298b7fa4ffc400849082f576556b9040d095f1007ae686daf1241dff8b73bac35c14acf21c156a18a3e16d62a7719c6cc34e4d1f +SHA512 (thunderbird-langpacks-68.7.0-20200409.tar.xz) = ff93a72cd73b53b2b01644ce93a8d8399865c51a5e155e6d42fac9a969883000ed4c41fd21ec164abb3a2ea17cd57de072387b0dee229e216ac883759a509d36 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.6.0.tar.xz) = 0c25befe7ffbf90c7758e770cbe8f3c84529f7f2bbf28494f7cd4624e5586a89651fb50606aa721e0195a09a858412ec26f1f6710ca5c0b2573032fced806dad +SHA512 (lightning-langpacks-68.7.0.tar.xz) = 7747113be6f03f4ae60406a4c548a0a490051f272572aa68be732ec5c9d02f7c0097bcfa1ae95e95dcf756d43514cbbca69eae76070ad7139199e0884ceeb843 diff --git a/thunderbird.spec b/thunderbird.spec index c30fcc9..d2c1237 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.6.0 +Version: 68.7.0 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200313.tar.xz +Source1: thunderbird-langpacks-%{version}-20200409.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -759,6 +759,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Apr 09 2020 Jan Horak - 68.7.0-1 +- Update to 68.7.0 build1 + * Fri Mar 13 2020 Jan Horak - 68.6.0-1 - Update to 68.6.0 build2 From 9834f58e197860b6066c48aef1cbeebe13559cc2 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 15 Apr 2020 12:10:56 +0200 Subject: [PATCH 103/402] Removed gconf-2.0 build requirement, added perl-interpreter instead --- thunderbird.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index d2c1237..795ed27 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.7.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -196,7 +196,7 @@ BuildRequires: libvpx-devel >= %{libvpx_version} %endif BuildRequires: pulseaudio-libs-devel BuildRequires: libicu-devel -BuildRequires: GConf2-devel +BuildRequires: perl-interpreter Requires: mozilla-filesystem BuildRequires: yasm BuildRequires: dbus-glib-devel @@ -759,6 +759,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Apr 15 2020 Jan Horak - 68.7.0-2 +- Removed gconf-2.0 build requirement, added perl-interpreter instead to fulfill + perl dependency + * Thu Apr 09 2020 Jan Horak - 68.7.0-1 - Update to 68.7.0 build1 From 83804837537adbc7059b33e1f07a2e5b940c67a4 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 14 May 2020 17:42:46 +0200 Subject: [PATCH 104/402] Update to 68.8.0 build2 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 6882b82..02155df 100644 --- a/.gitignore +++ b/.gitignore @@ -291,3 +291,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.7.0.source.tar.xz /thunderbird-langpacks-68.7.0-20200409.tar.xz /lightning-langpacks-68.7.0.tar.xz +/thunderbird-68.8.0.source.tar.xz +/thunderbird-langpacks-68.8.0-20200514.tar.xz +/lightning-langpacks-68.8.0.tar.xz diff --git a/sources b/sources index 1f6c5c5..45d2c95 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.7.0.source.tar.xz) = fae763030b7a54930291a10f298b7fa4ffc400849082f576556b9040d095f1007ae686daf1241dff8b73bac35c14acf21c156a18a3e16d62a7719c6cc34e4d1f -SHA512 (thunderbird-langpacks-68.7.0-20200409.tar.xz) = ff93a72cd73b53b2b01644ce93a8d8399865c51a5e155e6d42fac9a969883000ed4c41fd21ec164abb3a2ea17cd57de072387b0dee229e216ac883759a509d36 +SHA512 (thunderbird-68.8.0.source.tar.xz) = 1af899913454e97ba3b08a090f775c0ce65ae6d8c1d31171017f09355a0bb126516d4770b4a4a0e774419497c404fa70dcfcafdf767c9caba0bf1d658c0d9350 +SHA512 (thunderbird-langpacks-68.8.0-20200514.tar.xz) = 1cbc851953968ff5d55b7434e4fc5825ce6706715c014413684755314387249edc1119fe9deef501faf388fab4c0fb71e81b4ff890da1651ce4c9a4e6c1b2649 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.7.0.tar.xz) = 7747113be6f03f4ae60406a4c548a0a490051f272572aa68be732ec5c9d02f7c0097bcfa1ae95e95dcf756d43514cbbca69eae76070ad7139199e0884ceeb843 +SHA512 (lightning-langpacks-68.8.0.tar.xz) = beee99530e77b9a1833c73b139edc7ac1ae84e25a414092744a5b6364f489784d38b1e931489032e0579b4980ecfdcdfbe05611069ce19bdb44a5707d4319197 diff --git a/thunderbird.spec b/thunderbird.spec index 795ed27..950c032 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.7.0 -Release: 2%{?dist} +Version: 68.8.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200409.tar.xz +Source1: thunderbird-langpacks-%{version}-20200514.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -759,6 +759,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu May 14 2020 Jan Horak - 68.8.0-1 +- Update to 68.8.0 build2 + * Wed Apr 15 2020 Jan Horak - 68.7.0-2 - Removed gconf-2.0 build requirement, added perl-interpreter instead to fulfill perl dependency From 0c083d7ada2af3e1f366018deb586f5a2ccf754b Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Fri, 15 May 2020 12:45:02 +0200 Subject: [PATCH 105/402] Use D-Bus remote on Wayland (rhbz#1817330) --- thunderbird-dbus-remote.patch | 43 +++++++++++++++++++++++++++++++++++ thunderbird.sh.in | 7 ++++++ thunderbird.spec | 7 +++++- 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 thunderbird-dbus-remote.patch diff --git a/thunderbird-dbus-remote.patch b/thunderbird-dbus-remote.patch new file mode 100644 index 0000000..6142e1e --- /dev/null +++ b/thunderbird-dbus-remote.patch @@ -0,0 +1,43 @@ +diff --git a/toolkit/components/remote/nsRemoteService.cpp b/toolkit/components/remote/nsRemoteService.cpp +--- a/toolkit/components/remote/nsRemoteService.cpp ++++ b/toolkit/components/remote/nsRemoteService.cpp +@@ -38,6 +38,10 @@ + #define START_TIMEOUT_SEC 5 + #define START_SLEEP_MSEC 100 + ++// When MOZ_DBUS_REMOTE is set both X11 and Wayland backends ++// use only DBus remote. ++#define DBUS_REMOTE_ENV "MOZ_DBUS_REMOTE" ++ + using namespace mozilla; + + extern int gArgc; +@@ -101,11 +105,11 @@ + bool useX11Remote = GDK_IS_X11_DISPLAY(gdk_display_get_default()); + + # if defined(MOZ_ENABLE_DBUS) +- if (!useX11Remote) { ++ if (!useX11Remote || getenv(DBUS_REMOTE_ENV)) { + client = new nsDBusRemoteClient(); + } + # endif +- if (useX11Remote) { ++ if (!client && useX11Remote) { + client = new nsXRemoteClient(); + } + #elif defined(XP_WIN) +@@ -150,11 +154,11 @@ + bool useX11Remote = GDK_IS_X11_DISPLAY(gdk_display_get_default()); + + # if defined(MOZ_ENABLE_DBUS) +- if (!useX11Remote) { ++ if (!useX11Remote || getenv(DBUS_REMOTE_ENV)) { + mRemoteServer = MakeUnique(); + } + # endif +- if (useX11Remote) { ++ if (!mRemoteServer && useX11Remote) { + mRemoteServer = MakeUnique(); + } + #elif defined(XP_WIN) + diff --git a/thunderbird.sh.in b/thunderbird.sh.in index 110ead1..a4173d6 100644 --- a/thunderbird.sh.in +++ b/thunderbird.sh.in @@ -74,6 +74,13 @@ export MOZ_ALLOW_DOWNGRADE=1 # export MOZ_DISABLE_LANGPACKS # +## +## Use D-Bus remote exclusively when there's Wayland display. +## +if [ "$WAYLAND_DISPLAY" ]; then + export MOZ_DBUS_REMOTE=1 +fi + ## ## Automatically installed langpacks are tracked by .fedora-langpack-install ## config file. diff --git a/thunderbird.spec b/thunderbird.spec index 950c032..45c04d2 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.8.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -139,6 +139,7 @@ Patch307: build-disable-elfhack.patch # Upstream patches Patch402: mozilla-526293.patch Patch403: mozilla-1576268.patch +Patch404: thunderbird-dbus-remote.patch %if %{official_branding} # Required by Mozilla Corporation @@ -285,6 +286,7 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch402 -p1 -b .526293 %patch403 -p1 -b .1576268 +%patch404 -p1 -b .thunderbird-dbus-remote %if %{official_branding} # Required by Mozilla Corporation @@ -759,6 +761,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Fri May 15 2020 Martin Stransky - 68.8.0-2 +- Use D-Bus remote on Wayland (rhbz#1817330). + * Thu May 14 2020 Jan Horak - 68.8.0-1 - Update to 68.8.0 build2 From a28d167ec79e690721240aa5e91de9c8d52395fd Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Mon, 8 Jun 2020 09:00:29 +0200 Subject: [PATCH 106/402] Update to 68.9.0 build1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 02155df..6669d64 100644 --- a/.gitignore +++ b/.gitignore @@ -294,3 +294,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.8.0.source.tar.xz /thunderbird-langpacks-68.8.0-20200514.tar.xz /lightning-langpacks-68.8.0.tar.xz +/thunderbird-68.9.0.source.tar.xz +/thunderbird-langpacks-68.9.0-20200608.tar.xz +/lightning-langpacks-68.9.0.tar.xz diff --git a/sources b/sources index 45d2c95..a7461e8 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.8.0.source.tar.xz) = 1af899913454e97ba3b08a090f775c0ce65ae6d8c1d31171017f09355a0bb126516d4770b4a4a0e774419497c404fa70dcfcafdf767c9caba0bf1d658c0d9350 -SHA512 (thunderbird-langpacks-68.8.0-20200514.tar.xz) = 1cbc851953968ff5d55b7434e4fc5825ce6706715c014413684755314387249edc1119fe9deef501faf388fab4c0fb71e81b4ff890da1651ce4c9a4e6c1b2649 +SHA512 (thunderbird-68.9.0.source.tar.xz) = 891472c95ba6ff46061131504e89010da512a84b0e1dea0482e603fd4c87f11e099280a245c7dd9fc9320c48229c26602565c089d86f1a1f4271b29b6fc606f0 +SHA512 (thunderbird-langpacks-68.9.0-20200608.tar.xz) = 6b909d9cba5b2aa688a5aa973b731857c5c058998e8ab549c44cd29a8df7e505ab3a8c09ae310a331fbe0526f26e6909bbb87cd6ecd5c58e7b7fc4eee135d1e2 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.8.0.tar.xz) = beee99530e77b9a1833c73b139edc7ac1ae84e25a414092744a5b6364f489784d38b1e931489032e0579b4980ecfdcdfbe05611069ce19bdb44a5707d4319197 +SHA512 (lightning-langpacks-68.9.0.tar.xz) = 37964c08c93f0a8a06783b96d34352f3137d9d0c1716e36d2c3efbb5c414eed530f8a507677df66ffd5f22e7846c9f7545df39a61808db3f89656bfe971e397f diff --git a/thunderbird.spec b/thunderbird.spec index 45c04d2..86d7ac6 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.8.0 -Release: 2%{?dist} +Version: 68.9.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200514.tar.xz +Source1: thunderbird-langpacks-%{version}-20200608.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -761,6 +761,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Mon Jun 08 2020 Jan Horak - 68.9.0-1 +- Update to 68.9.0 build1 + * Fri May 15 2020 Martin Stransky - 68.8.0-2 - Use D-Bus remote on Wayland (rhbz#1817330). From 2f6258248a97df769c525e9031c6cc0c2a303393 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 9 Jul 2020 08:01:38 +0200 Subject: [PATCH 107/402] Update to 68.10.0 build1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 6669d64..3bacf3d 100644 --- a/.gitignore +++ b/.gitignore @@ -297,3 +297,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.9.0.source.tar.xz /thunderbird-langpacks-68.9.0-20200608.tar.xz /lightning-langpacks-68.9.0.tar.xz +/thunderbird-68.10.0.source.tar.xz +/thunderbird-langpacks-68.10.0-20200709.tar.xz +/lightning-langpacks-68.10.0.tar.xz diff --git a/sources b/sources index a7461e8..d33f192 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.9.0.source.tar.xz) = 891472c95ba6ff46061131504e89010da512a84b0e1dea0482e603fd4c87f11e099280a245c7dd9fc9320c48229c26602565c089d86f1a1f4271b29b6fc606f0 -SHA512 (thunderbird-langpacks-68.9.0-20200608.tar.xz) = 6b909d9cba5b2aa688a5aa973b731857c5c058998e8ab549c44cd29a8df7e505ab3a8c09ae310a331fbe0526f26e6909bbb87cd6ecd5c58e7b7fc4eee135d1e2 +SHA512 (thunderbird-68.10.0.source.tar.xz) = 8db4e363b1542190d647babbeb2bca4f258e6bfe3bb67c4a4c8eedad702f956c6e2e1daaa552a45912b55215fa5f6fe0be77025de324ea6a0082ca849d132c89 +SHA512 (thunderbird-langpacks-68.10.0-20200709.tar.xz) = f04195506f79258198467d3eec8b8a94d04b0cd165a72e962edcba9e3e9c8b4288dc6ae7c55cf260a5971e766c7685ecad032f7f824905a36844dbeed155fb71 SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.9.0.tar.xz) = 37964c08c93f0a8a06783b96d34352f3137d9d0c1716e36d2c3efbb5c414eed530f8a507677df66ffd5f22e7846c9f7545df39a61808db3f89656bfe971e397f +SHA512 (lightning-langpacks-68.10.0.tar.xz) = 197e02effa94c2a6d920d42fde676270fd3c14319ee9a5845a6de4f6261e4e817d8a04e36dfddbbcdf736da45125a7d75859aed19adea16cbf6af029d62e516b diff --git a/thunderbird.spec b/thunderbird.spec index 86d7ac6..5481171 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.9.0 +Version: 68.10.0 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200608.tar.xz +Source1: thunderbird-langpacks-%{version}-20200709.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -761,6 +761,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Jul 09 2020 Jan Horak - 68.10.0-1 +- Update to 68.10.0 build1 + * Mon Jun 08 2020 Jan Horak - 68.9.0-1 - Update to 68.9.0 build1 From bb42baffb814221d5cf6ad9585a06e08b5527770 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 29 Jul 2020 12:27:47 +0000 Subject: [PATCH 108/402] - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 5481171..4df8859 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.10.0 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -761,6 +761,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Jul 29 2020 Fedora Release Engineering - 68.10.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + * Thu Jul 09 2020 Jan Horak - 68.10.0-1 - Update to 68.10.0 build1 From ac2c5163d42712b8a019d7656ddcffabeb420476 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 1 Aug 2020 09:30:05 +0000 Subject: [PATCH 109/402] - Second attempt - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- thunderbird.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 4df8859..da36b55 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -94,7 +94,7 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 68.10.0 -Release: 2%{?dist} +Release: 3%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -761,6 +761,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Sat Aug 01 2020 Fedora Release Engineering - 68.10.0-3 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + * Wed Jul 29 2020 Fedora Release Engineering - 68.10.0-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild From c59a1292a6424f6be48f81e4bb88671c4326e4ff Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 7 Aug 2020 09:57:03 +0200 Subject: [PATCH 110/402] Update to 68.11 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 9 ++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 3bacf3d..4472fa4 100644 --- a/.gitignore +++ b/.gitignore @@ -300,3 +300,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.10.0.source.tar.xz /thunderbird-langpacks-68.10.0-20200709.tar.xz /lightning-langpacks-68.10.0.tar.xz +/thunderbird-68.11.0.source.tar.xz +/thunderbird-langpacks-68.11.0-20200806.tar.xz +/lightning-langpacks-68.11.0.tar.xz diff --git a/sources b/sources index d33f192..8692f64 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.10.0.source.tar.xz) = 8db4e363b1542190d647babbeb2bca4f258e6bfe3bb67c4a4c8eedad702f956c6e2e1daaa552a45912b55215fa5f6fe0be77025de324ea6a0082ca849d132c89 -SHA512 (thunderbird-langpacks-68.10.0-20200709.tar.xz) = f04195506f79258198467d3eec8b8a94d04b0cd165a72e962edcba9e3e9c8b4288dc6ae7c55cf260a5971e766c7685ecad032f7f824905a36844dbeed155fb71 +SHA512 (thunderbird-68.11.0.source.tar.xz) = a98a3e427868b46213a05b71b476d963b019d6904a1ef3ec1de6ceac012a2ebd3693fa24691bc6b3c34961bec9cc7d11c3f634ce952d7427c0a76e0defc7de72 +SHA512 (thunderbird-langpacks-68.11.0-20200806.tar.xz) = edd03b6b9cb988417cf656688c19a8928f2fe27c7eeaceff50ad5224aed4bbe0e1e2b601ee078877f0244f5e951cd555b3f3c67fceb262c9d48238b2f83e3efe SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.10.0.tar.xz) = 197e02effa94c2a6d920d42fde676270fd3c14319ee9a5845a6de4f6261e4e817d8a04e36dfddbbcdf736da45125a7d75859aed19adea16cbf6af029d62e516b +SHA512 (lightning-langpacks-68.11.0.tar.xz) = 81eeb9613e495293b17efea1bca3d8bca317a36e865a5f7d70d52bd3bc04959ceeae586f38f266a080eec57ee9e490fa685f8f56b2ef93267b800ecbd692cc4f diff --git a/thunderbird.spec b/thunderbird.spec index da36b55..8f5cf7e 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.10.0 -Release: 3%{?dist} +Version: 68.11.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200709.tar.xz +Source1: thunderbird-langpacks-%{version}-20200806.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -761,6 +761,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Aug 06 2020 Jan Horak - 68.11.0-1 +- Update to 68.11.0 build1 + * Sat Aug 01 2020 Fedora Release Engineering - 68.10.0-3 - Second attempt - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild From 7c26b36cb943c6ea3693c1b4e4d09c58cee77d4f Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Tue, 8 Sep 2020 08:50:22 +0200 Subject: [PATCH 111/402] Update to 68.12.0 build1 --- .gitignore | 3 +++ sources | 6 +++--- thunderbird.spec | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 4472fa4..22cf058 100644 --- a/.gitignore +++ b/.gitignore @@ -303,3 +303,6 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.11.0.source.tar.xz /thunderbird-langpacks-68.11.0-20200806.tar.xz /lightning-langpacks-68.11.0.tar.xz +/thunderbird-68.12.0.source.tar.xz +/thunderbird-langpacks-68.12.0-20200908.tar.xz +/lightning-langpacks-68.12.0.tar.xz diff --git a/sources b/sources index 8692f64..18dad00 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (thunderbird-68.11.0.source.tar.xz) = a98a3e427868b46213a05b71b476d963b019d6904a1ef3ec1de6ceac012a2ebd3693fa24691bc6b3c34961bec9cc7d11c3f634ce952d7427c0a76e0defc7de72 -SHA512 (thunderbird-langpacks-68.11.0-20200806.tar.xz) = edd03b6b9cb988417cf656688c19a8928f2fe27c7eeaceff50ad5224aed4bbe0e1e2b601ee078877f0244f5e951cd555b3f3c67fceb262c9d48238b2f83e3efe +SHA512 (thunderbird-68.12.0.source.tar.xz) = e7559536a9e024747e3ac7c20e4ffde5adf57657d02109ea32c39bf736ad03707fc7a14a0d3f1c91fa6fd69ead3c38d6c32ce78bd468834d9ba7f77f728332c6 +SHA512 (thunderbird-langpacks-68.12.0-20200908.tar.xz) = 13545b356c39de218d38b1be5bd1d012628a39358e33b0e244f8a7375853539c2434898a9f90cf61b1977900eae729674bf7a1403357a3a088f19c231ef9c8fb SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.11.0.tar.xz) = 81eeb9613e495293b17efea1bca3d8bca317a36e865a5f7d70d52bd3bc04959ceeae586f38f266a080eec57ee9e490fa685f8f56b2ef93267b800ecbd692cc4f +SHA512 (lightning-langpacks-68.12.0.tar.xz) = 3a57d73166e63108172f8c4a218860e3618ca40c54d6c75a6e7e561f552d79bc4291aa6057be1630d8a2eedf1f7c0f39fa64e38ccce9c7dd470efd01a3afb075 diff --git a/thunderbird.spec b/thunderbird.spec index 8f5cf7e..7cb8e53 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -93,13 +93,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.11.0 +Version: 68.12.0 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200806.tar.xz +Source1: thunderbird-langpacks-%{version}-20200908.tar.xz # Locales for lightning Source2: lightning-langpacks-%{version}.tar.xz %endif @@ -761,6 +761,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Tue Sep 08 2020 Jan Horak - 68.12.0-1 +- Update to 68.12.0 build1 + * Thu Aug 06 2020 Jan Horak - 68.11.0-1 - Update to 68.11.0 build1 From e6c8a08e6065cb3b98f404217f29bcc8b4b26b96 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 30 Sep 2020 11:59:44 +0200 Subject: [PATCH 112/402] Update to 78.3.1 --- .gitignore | 2 ++ mozilla-1353817.patch | 12 ---------- mozilla-1576268.patch | 17 -------------- sources | 6 ++--- thunderbird-dbus-remote.patch | 43 ----------------------------------- thunderbird-debug.patch | 12 ---------- 6 files changed, 4 insertions(+), 88 deletions(-) delete mode 100644 mozilla-1353817.patch delete mode 100644 mozilla-1576268.patch delete mode 100644 thunderbird-dbus-remote.patch delete mode 100644 thunderbird-debug.patch diff --git a/.gitignore b/.gitignore index 22cf058..d309566 100644 --- a/.gitignore +++ b/.gitignore @@ -306,3 +306,5 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-68.12.0.source.tar.xz /thunderbird-langpacks-68.12.0-20200908.tar.xz /lightning-langpacks-68.12.0.tar.xz +/thunderbird-78.3.1.source.tar.xz +/thunderbird-langpacks-78.3.1-20200930.tar.xz diff --git a/mozilla-1353817.patch b/mozilla-1353817.patch deleted file mode 100644 index 8bdac06..0000000 --- a/mozilla-1353817.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up thunderbird-68.0/gfx/skia/skia/include/private/SkNx.h.1353817 thunderbird-68.0/gfx/skia/skia/include/private/SkNx.h ---- thunderbird-68.0/gfx/skia/skia/include/private/SkNx.h.1353817 2019-08-29 16:31:20.892290062 +0200 -+++ thunderbird-68.0/gfx/skia/skia/include/private/SkNx.h 2019-08-29 16:32:05.430436157 +0200 -@@ -416,7 +416,7 @@ typedef SkNx<8, uint32_t> Sk8u; - // Include platform specific specializations if available. - #if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 - #include "SkNx_sse.h" --#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON) -+#elif !defined(SKNX_NO_SIMD) && (defined(SK_ARM_HAS_NEON) || defined(SK_CPU_ARM64)) - #include "SkNx_neon.h" - #else - diff --git a/mozilla-1576268.patch b/mozilla-1576268.patch deleted file mode 100644 index 85fd1a8..0000000 --- a/mozilla-1576268.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp ---- a/widget/gtk/nsClipboardWayland.cpp -+++ b/widget/gtk/nsClipboardWayland.cpp -@@ -195,6 +195,12 @@ - uint32_t all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | - WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; - -+ /* Default to move D&D action (Bug 1576268). -+ */ -+ if (dnd_actions == 0) { -+ all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; -+ } -+ - wl_data_offer_set_actions(mWaylandDataOffer, all_actions, dnd_actions); - - /* Workaround Wayland D&D architecture here. To get the data_device_drop() - diff --git a/sources b/sources index 18dad00..a1aa120 100644 --- a/sources +++ b/sources @@ -1,4 +1,2 @@ -SHA512 (thunderbird-68.12.0.source.tar.xz) = e7559536a9e024747e3ac7c20e4ffde5adf57657d02109ea32c39bf736ad03707fc7a14a0d3f1c91fa6fd69ead3c38d6c32ce78bd468834d9ba7f77f728332c6 -SHA512 (thunderbird-langpacks-68.12.0-20200908.tar.xz) = 13545b356c39de218d38b1be5bd1d012628a39358e33b0e244f8a7375853539c2434898a9f90cf61b1977900eae729674bf7a1403357a3a088f19c231ef9c8fb -SHA512 (cbindgen-vendor.tar.xz) = 88afa0bc6af525cbb46bc75578b90419b28b95b396d5002fbf299a78a173681b840096ff83ef6e48553d1a5e0aa04e79383ab4d09bf431f3b864fcbacc7de46d -SHA512 (lightning-langpacks-68.12.0.tar.xz) = 3a57d73166e63108172f8c4a218860e3618ca40c54d6c75a6e7e561f552d79bc4291aa6057be1630d8a2eedf1f7c0f39fa64e38ccce9c7dd470efd01a3afb075 +SHA512 (thunderbird-78.3.1.source.tar.xz) = 16b05e51776ba16503bc5fba02a6d0b5050a206e264a4707544354ad76af61902fd2dcf5d97b82b432dc69362ccd18543a0acccd80e06648e6c6f470886da450 +SHA512 (thunderbird-langpacks-78.3.1-20200930.tar.xz) = 649ed59bdf7b988ca482b3bdb1dd2ea31741daeacc17c783f54e3fc65ac4ac17569d2cc54f357752bd0835914db5f59d638a781634d89a10acd3eee2acb9eb94 diff --git a/thunderbird-dbus-remote.patch b/thunderbird-dbus-remote.patch deleted file mode 100644 index 6142e1e..0000000 --- a/thunderbird-dbus-remote.patch +++ /dev/null @@ -1,43 +0,0 @@ -diff --git a/toolkit/components/remote/nsRemoteService.cpp b/toolkit/components/remote/nsRemoteService.cpp ---- a/toolkit/components/remote/nsRemoteService.cpp -+++ b/toolkit/components/remote/nsRemoteService.cpp -@@ -38,6 +38,10 @@ - #define START_TIMEOUT_SEC 5 - #define START_SLEEP_MSEC 100 - -+// When MOZ_DBUS_REMOTE is set both X11 and Wayland backends -+// use only DBus remote. -+#define DBUS_REMOTE_ENV "MOZ_DBUS_REMOTE" -+ - using namespace mozilla; - - extern int gArgc; -@@ -101,11 +105,11 @@ - bool useX11Remote = GDK_IS_X11_DISPLAY(gdk_display_get_default()); - - # if defined(MOZ_ENABLE_DBUS) -- if (!useX11Remote) { -+ if (!useX11Remote || getenv(DBUS_REMOTE_ENV)) { - client = new nsDBusRemoteClient(); - } - # endif -- if (useX11Remote) { -+ if (!client && useX11Remote) { - client = new nsXRemoteClient(); - } - #elif defined(XP_WIN) -@@ -150,11 +154,11 @@ - bool useX11Remote = GDK_IS_X11_DISPLAY(gdk_display_get_default()); - - # if defined(MOZ_ENABLE_DBUS) -- if (!useX11Remote) { -+ if (!useX11Remote || getenv(DBUS_REMOTE_ENV)) { - mRemoteServer = MakeUnique(); - } - # endif -- if (useX11Remote) { -+ if (!mRemoteServer && useX11Remote) { - mRemoteServer = MakeUnique(); - } - #elif defined(XP_WIN) - diff --git a/thunderbird-debug.patch b/thunderbird-debug.patch deleted file mode 100644 index c502851..0000000 --- a/thunderbird-debug.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up thunderbird-60.6.1/intl/locale/LocaleService.cpp.debug thunderbird-60.6.1/intl/locale/LocaleService.cpp ---- thunderbird-60.6.1/intl/locale/LocaleService.cpp.debug 2019-05-15 08:15:14.602872505 +0200 -+++ thunderbird-60.6.1/intl/locale/LocaleService.cpp 2019-05-15 08:15:53.717635322 +0200 -@@ -643,8 +643,6 @@ LocaleService::GetDefaultLocale(nsACStri - // just use our hard-coded default below. - GetGREFileContents("update.locale", &locale); - locale.Trim(" \t\n\r"); -- // This should never be empty. -- MOZ_ASSERT(!locale.IsEmpty()); - if (SanitizeForBCP47(locale, true)) { - mDefaultLocale.Assign(locale); - } From 3df4a73bb96b492e1820fc5addf199959ff63054 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 30 Sep 2020 12:01:15 +0200 Subject: [PATCH 113/402] Removed obsolte lightning langpacks --- thunderbird-mozconfig | 1 - thunderbird.spec | 54 ++++++------------------------------------- 2 files changed, 7 insertions(+), 48 deletions(-) diff --git a/thunderbird-mozconfig b/thunderbird-mozconfig index 805c81c..15ae03d 100644 --- a/thunderbird-mozconfig +++ b/thunderbird-mozconfig @@ -14,7 +14,6 @@ ac_add_options --disable-strip # temporary disable system cairo, because compilation fails ac_add_options --disable-necko-wifi ac_add_options --disable-updater -ac_add_options --enable-startup-notification ac_add_options --with-system-icu # lightning related diff --git a/thunderbird.spec b/thunderbird.spec index 7cb8e53..0f7bb13 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -13,7 +13,6 @@ ExcludeArch: s390x # Hardened build? %define hardened_build 1 -%define system_sqlite 0 %define system_ffi 1 %define build_langpacks 1 @@ -26,20 +25,14 @@ ExcludeArch: s390x %endif %if %{?system_nss} -%global nspr_version 4.10.6 +%global nspr_version 4.26.0 %global nspr_build_version %(pkg-config --silence-errors --modversion nspr 2>/dev/null || echo 65536) -%global nss_version 3.16.2.3 +%global nss_version 3.55.0 %global nss_build_version %(pkg-config --silence-errors --modversion nss 2>/dev/null || echo 65536) %endif %define freetype_version 2.1.9 -%if %{?system_sqlite} -%define sqlite_version 3.8.4.2 -# The actual sqlite version (see #480989): -%global sqlite_build_version %(pkg-config --silence-errors --modversion sqlite3 2>/dev/null || echo 65536) -%endif - %define libnotify_version 0.4 %define _default_patch_fuzz 2 @@ -93,15 +86,13 @@ ExcludeArch: s390x Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 68.12.0 +Version: 78.3.1 Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200908.tar.xz -# Locales for lightning -Source2: lightning-langpacks-%{version}.tar.xz +Source1: thunderbird-langpacks-%{version}-20200930.tar.xz %endif Source3: get-calendar-langpacks.sh Source4: cbindgen-vendor.tar.xz @@ -126,20 +117,16 @@ Patch417: build-aarch64-user_vfp.patch Patch418: mozilla-1512162.patch Patch419: bindgen-d0dfc52706f23db9dc9d74642eeebd89d73cb8d0.patch Patch103: rhbz-1219542-s390-build.patch -Patch105: thunderbird-debug.patch # PPC fix Patch304: mozilla-1245783.patch Patch305: build-big-endian.patch -Patch306: mozilla-1353817.patch Patch307: build-disable-elfhack.patch # Fedora specific patches # Upstream patches Patch402: mozilla-526293.patch -Patch403: mozilla-1576268.patch -Patch404: thunderbird-dbus-remote.patch %if %{official_branding} # Required by Mozilla Corporation @@ -179,10 +166,6 @@ BuildRequires: clang-libs %if 0%{?build_with_clang} BuildRequires: lld %endif -%if %{?system_sqlite} -BuildRequires: sqlite-devel >= %{sqlite_version} -Requires: sqlite >= %{sqlite_build_version} -%endif %if %{?system_ffi} BuildRequires: libffi-devel %endif @@ -256,7 +239,6 @@ debug %{name}, you want to install %{name}-debuginfo instead. %ifarch s390 %patch103 -p1 -b .rhbz-1219542-s390-build %endif -%patch105 -p1 -b .debug %patch304 -p1 -b .1245783 # Patch for big endian platforms only @@ -278,15 +260,12 @@ debug %{name}, you want to install %{name}-debuginfo instead. # most likely fixed #%patch419 -p1 -b .bindgen -%patch306 -p1 -b .1353817 %if 0%{?disable_elfhack} %patch307 -p1 -b .elfhack %endif #cd .. %patch402 -p1 -b .526293 -%patch403 -p1 -b .1576268 -%patch404 -p1 -b .thunderbird-dbus-remote %if %{official_branding} # Required by Mozilla Corporation @@ -315,11 +294,6 @@ echo "ac_add_options --without-system-nss" >> .mozconfig echo "ac_add_options --disable-jemalloc" >> .mozconfig %endif -%if %{?system_sqlite} -echo "ac_add_options --enable-system-sqlite" >> .mozconfig -%else -echo "ac_add_options --disable-system-sqlite" >> .mozconfig -%endif %if %{?system_ffi} echo "ac_add_options --enable-system-ffi" >> .mozconfig @@ -414,17 +388,6 @@ env CARGO_HOME=.cargo cargo install cbindgen export PATH=`pwd`/.cargo/bin:$PATH %endif -%if %{?system_sqlite} -# Do not proceed with build if the sqlite require would be broken: -# make sure the minimum requirement is non-empty, ... -sqlite_version=$(expr "%{sqlite_version}" : '\([0-9]*\.\)[0-9]*\.') || exit 1 -# ... and that major number of the computed build-time version matches: -case "%{sqlite_build_version}" in - "$sqlite_version"*) ;; - *) exit 1 ;; -esac -%endif - %if 0%{?big_endian} echo "Generate big endian version of config/external/icu/data/icud58l.dat" ./mach python intl/icu_sources_data.py . @@ -614,12 +577,6 @@ for langpack in `ls thunderbird-langpacks/*.xpi`; do done %{__rm} -rf thunderbird-langpacks -# lightning langpacks install -cd %{buildroot}%{langpackdir} -%{__tar} xf %{SOURCE2} -chmod a+r *.xpi -cd - -%endif # build_langpacks # Get rid of devel package and its debugsymbols %{__rm} -rf $RPM_BUILD_ROOT%{_libdir}/%{name}-devel-%{version} @@ -761,6 +718,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Sep 30 2020 Jan Horak - 78.3.1-1 +- Update to 78.3.1 build1 + * Tue Sep 08 2020 Jan Horak - 68.12.0-1 - Update to 68.12.0 build1 From b240e6ad3cf4ad8024b50dd0644425626db8cfd8 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 30 Sep 2020 12:02:33 +0200 Subject: [PATCH 114/402] Removed obsolte lightning langpacks --- thunderbird.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/thunderbird.spec b/thunderbird.spec index 0f7bb13..307f9d9 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -557,6 +557,7 @@ rm -f $RPM_BUILD_ROOT/%{_bindir}/thunderbird # Install langpacks %{__rm} -f %{name}.lang # Delete for --short-circuit option touch %{name}.lang + %if %{build_langpacks} %{__mkdir_p} %{buildroot}%{langpackdir} %{__tar} xf %{SOURCE1} @@ -576,6 +577,7 @@ for langpack in `ls thunderbird-langpacks/*.xpi`; do echo "%%lang($language) %{langpackdir}/${extensionID}.xpi" >> %{name}.lang done %{__rm} -rf thunderbird-langpacks +%endif # Get rid of devel package and its debugsymbols From c2a0d6743d620d4937d36abca356d75ca190c7ba Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 30 Sep 2020 12:06:33 +0200 Subject: [PATCH 115/402] Added correct cbindgen source --- .gitignore | 1 + sources | 1 + thunderbird.spec | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d309566..3470aab 100644 --- a/.gitignore +++ b/.gitignore @@ -308,3 +308,4 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /lightning-langpacks-68.12.0.tar.xz /thunderbird-78.3.1.source.tar.xz /thunderbird-langpacks-78.3.1-20200930.tar.xz +/cbindgen-vendor-0.14.3.tar.xz diff --git a/sources b/sources index a1aa120..7662177 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ SHA512 (thunderbird-78.3.1.source.tar.xz) = 16b05e51776ba16503bc5fba02a6d0b5050a206e264a4707544354ad76af61902fd2dcf5d97b82b432dc69362ccd18543a0acccd80e06648e6c6f470886da450 SHA512 (thunderbird-langpacks-78.3.1-20200930.tar.xz) = 649ed59bdf7b988ca482b3bdb1dd2ea31741daeacc17c783f54e3fc65ac4ac17569d2cc54f357752bd0835914db5f59d638a781634d89a10acd3eee2acb9eb94 +SHA512 (cbindgen-vendor-0.14.3.tar.xz) = 33c8d28547674121f690eea0d3ebac33926a39caacac787bf8ed8b346478822e74da5a4a1f57ab4df4105fa8376739a2ece888845a85bc5712aaed20e4a508bc diff --git a/thunderbird.spec b/thunderbird.spec index 307f9d9..8585475 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -95,7 +95,7 @@ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_ Source1: thunderbird-langpacks-%{version}-20200930.tar.xz %endif Source3: get-calendar-langpacks.sh -Source4: cbindgen-vendor.tar.xz +Source4: cbindgen-vendor-0.14.3.tar.xz Source10: thunderbird-mozconfig Source11: thunderbird-mozconfig-branded From e02a35b9e5fde28d07370d85d7a968502d09e2c1 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 30 Sep 2020 12:17:46 +0200 Subject: [PATCH 116/402] use disable-jit instead of disable-ion --- thunderbird.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 8585475..140265b 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -316,7 +316,7 @@ echo "ac_add_options --enable-system-ffi" >> .mozconfig %endif %ifarch aarch64 -echo "ac_add_options --disable-ion" >> .mozconfig +echo "ac_add_options --disable-jit" >> .mozconfig %endif %ifnarch %{ix86} x86_64 From dba412efad92e5f6df52564f4f5a5fc4ac1ca33a Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 1 Oct 2020 11:33:12 +0200 Subject: [PATCH 117/402] Disable lto and fixing CK_GCM_PARAMS_V3 buildproblems with system nss --- thunderbird.spec | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/thunderbird.spec b/thunderbird.spec index 140265b..82f3bde 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -369,6 +369,9 @@ echo 'export NODEJS="%{_buildrootdir}/bin/node-stdout-nonblocking-wrapper"' >> . #=============================================================================== %build +# Disable LTO to work around rhbz#1883904 +%define _lto_cflags %{nil} + %if 0%{?use_bundled_cbindgen} mkdir -p my_rust_vendor @@ -448,6 +451,10 @@ echo "ac_add_options --enable-linker=gold" >> .mozconfig %endif %endif +# We don't want thunderbird to use CK_GCM_PARAMS_V3 in nss +MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -DNSS_PKCS11_3_0_STRICT" + + export CFLAGS=`echo $MOZ_OPT_FLAGS |sed -e 's/-fpermissive//g'` export CXXFLAGS=$MOZ_OPT_FLAGS export LDFLAGS=$MOZ_LINK_FLAGS From abf2a5e4bf9880ca6e88d5af5f19a0d59005b4de Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 1 Oct 2020 15:39:45 +0200 Subject: [PATCH 118/402] Fixing shebangs --- thunderbird.spec | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/thunderbird.spec b/thunderbird.spec index 82f3bde..b84406d 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -366,6 +366,13 @@ echo "ac_add_options --disable-crashreporter" >> .mozconfig echo 'export NODEJS="%{_buildrootdir}/bin/node-stdout-nonblocking-wrapper"' >> .mozconfig +# Remove executable bit to make brp-mangle-shebangs happy. +chmod -x third_party/rust/itertools/src/lib.rs +chmod a-x third_party/rust/gfx-backend-vulkan/src/*.rs +chmod a-x third_party/rust/gfx-hal/src/*.rs +chmod a-x third_party/rust/ash/src/extensions/ext/*.rs +chmod a-x third_party/rust/ash/src/extensions/khr/*.rs + #=============================================================================== %build From 0c1be68a8792786af480169c253eadd3cbace7bc Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 2 Oct 2020 19:51:21 +0200 Subject: [PATCH 119/402] Fixing missing files --- thunderbird.spec | 2 -- 1 file changed, 2 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index b84406d..46aae66 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -704,7 +704,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{mozappdir}/*.so %{mozappdir}/platform.ini %{mozappdir}/application.ini -%{mozappdir}/blocklist.xml %{mozappdir}/features/*.xpi %exclude %{mozappdir}/removed-files %{_datadir}/icons/hicolor/16x16/apps/thunderbird.png @@ -727,7 +726,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{mozappdir}/dependentlibs.list %{mozappdir}/distribution %{mozappdir}/fonts -%{mozappdir}/chrome.manifest %{mozappdir}/pingsender %{mozappdir}/gtk2/libmozgtk.so From ba38d87f3a0110ed0ec4fe0b837a1857feaa8484 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 7 Oct 2020 11:21:02 +0200 Subject: [PATCH 120/402] Reenable s390x as https://pagure.io/koji/issue/1418 seems to be fixed --- thunderbird.spec | 3 --- 1 file changed, 3 deletions(-) diff --git a/thunderbird.spec b/thunderbird.spec index 46aae66..0c8ba74 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -1,9 +1,6 @@ # Disabled arm due to rhbz#1658940 ExcludeArch: armv7hl -# Disabled due to https://pagure.io/fedora-infrastructure/issue/7581 -ExcludeArch: s390x - # Use system nspr/nss? %define system_nss 1 From 468086f54595a175243fa393fb45e7fcac310b79 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 7 Oct 2020 11:22:17 +0200 Subject: [PATCH 121/402] Reenable s390x as https://pagure.io/koji/issue/1418 seems to be fixed --- thunderbird.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thunderbird.spec b/thunderbird.spec index 0c8ba74..0552558 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -84,7 +84,7 @@ ExcludeArch: armv7hl Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird Version: 78.3.1 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz @@ -729,6 +729,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Wed Oct 07 2020 Jan Horak - 78.3.1-2 +- Reenable s390x + * Wed Sep 30 2020 Jan Horak - 78.3.1-1 - Update to 78.3.1 build1 From bbe0d15c7e2f5b6f7cfb370a9e638793ae62ac44 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 9 Oct 2020 10:22:55 +0200 Subject: [PATCH 122/402] Removed obsolete patches --- build-big-endian.patch | 84 -------------------------------------- build-icu-big-endian.patch | 12 ------ thunderbird.spec | 8 +--- 3 files changed, 2 insertions(+), 102 deletions(-) delete mode 100644 build-big-endian.patch delete mode 100644 build-icu-big-endian.patch diff --git a/build-big-endian.patch b/build-big-endian.patch deleted file mode 100644 index e8ec439..0000000 --- a/build-big-endian.patch +++ /dev/null @@ -1,84 +0,0 @@ -diff -up firefox-60.0/gfx/skia/skia/include/core/SkColorPriv.h.big-endian firefox-60.0/gfx/skia/skia/include/core/SkColorPriv.h ---- firefox-60.0/gfx/skia/skia/include/core/SkColorPriv.h.big-endian 2018-04-09 22:50:48.000000000 +0200 -+++ firefox-60.0/gfx/skia/skia/include/core/SkColorPriv.h 2018-04-18 11:51:38.748680174 +0200 -@@ -54,18 +54,19 @@ static inline U8CPU SkUnitScalarClampToB - * - * Here we enforce this constraint. - */ -- -+/* - #ifdef SK_CPU_BENDIAN - #define SK_RGBA_R32_SHIFT 24 - #define SK_RGBA_G32_SHIFT 16 - #define SK_RGBA_B32_SHIFT 8 - #define SK_RGBA_A32_SHIFT 0 - #else -+*/ - #define SK_RGBA_R32_SHIFT 0 - #define SK_RGBA_G32_SHIFT 8 - #define SK_RGBA_B32_SHIFT 16 - #define SK_RGBA_A32_SHIFT 24 --#endif -+/*#endif*/ - - #define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24) - #define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24) -diff -up firefox-60.0/gfx/skia/skia/include/core/SkImageInfo.h.big-endian firefox-60.0/gfx/skia/skia/include/core/SkImageInfo.h ---- firefox-60.0/gfx/skia/skia/include/core/SkImageInfo.h.big-endian 2018-04-09 22:50:48.000000000 +0200 -+++ firefox-60.0/gfx/skia/skia/include/core/SkImageInfo.h 2018-04-18 11:51:38.748680174 +0200 -@@ -84,7 +84,8 @@ enum SkColorType { - #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) - kN32_SkColorType = kRGBA_8888_SkColorType, - #else -- #error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order" -+ //#error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order" -+ kN32_SkColorType = kBGRA_8888_SkColorType - #endif - }; - -diff -up firefox-60.0/gfx/skia/skia/include/gpu/GrTypes.h.big-endian firefox-60.0/gfx/skia/skia/include/gpu/GrTypes.h ---- firefox-60.0/gfx/skia/skia/include/gpu/GrTypes.h.big-endian 2018-04-09 22:50:48.000000000 +0200 -+++ firefox-60.0/gfx/skia/skia/include/gpu/GrTypes.h 2018-04-18 11:51:38.748680174 +0200 -@@ -344,15 +344,13 @@ enum GrPixelConfig { - static const int kGrPixelConfigCnt = kLast_GrPixelConfig + 1; - - // Aliases for pixel configs that match skia's byte order. --#ifndef SK_CPU_LENDIAN -- #error "Skia gpu currently assumes little endian" --#endif - #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) - static const GrPixelConfig kSkia8888_GrPixelConfig = kBGRA_8888_GrPixelConfig; - #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) - static const GrPixelConfig kSkia8888_GrPixelConfig = kRGBA_8888_GrPixelConfig; - #else -- #error "SK_*32_SHIFT values must correspond to GL_BGRA or GL_RGBA format." -+ static const GrPixelConfig kSkia8888_GrPixelConfig = kBGRA_8888_GrPixelConfig; -+ static const GrPixelConfig kSkiaGamma8888_GrPixelConfig = kSBGRA_8888_GrPixelConfig; - #endif - - /** -diff -up firefox-60.0/gfx/skia/skia/src/core/SkColorData.h.big-endian firefox-60.0/gfx/skia/skia/src/core/SkColorData.h ---- firefox-60.0/gfx/skia/skia/src/core/SkColorData.h.big-endian 2018-04-18 13:42:06.980476156 +0200 -+++ firefox-60.0/gfx/skia/skia/src/core/SkColorData.h 2018-04-18 13:42:50.493520552 +0200 -@@ -31,18 +31,19 @@ - * - * Here we enforce this constraint. - */ -- -+/* - #ifdef SK_CPU_BENDIAN - #define SK_BGRA_B32_SHIFT 24 - #define SK_BGRA_G32_SHIFT 16 - #define SK_BGRA_R32_SHIFT 8 - #define SK_BGRA_A32_SHIFT 0 - #else -+*/ - #define SK_BGRA_B32_SHIFT 0 - #define SK_BGRA_G32_SHIFT 8 - #define SK_BGRA_R32_SHIFT 16 - #define SK_BGRA_A32_SHIFT 24 --#endif -+//#endif - - #if defined(SK_PMCOLOR_IS_RGBA) && defined(SK_PMCOLOR_IS_BGRA) - #error "can't define PMCOLOR to be RGBA and BGRA" diff --git a/build-icu-big-endian.patch b/build-icu-big-endian.patch deleted file mode 100644 index 68fbea1..0000000 --- a/build-icu-big-endian.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up mozilla-aurora/build/autoconf/icu.m4.icu-endian mozilla-aurora/build/autoconf/icu.m4 ---- mozilla-aurora/build/autoconf/icu.m4.icu-endian 2016-12-09 09:11:01.227317790 +0100 -+++ mozilla-aurora/build/autoconf/icu.m4 2016-12-09 09:18:40.608712247 +0100 -@@ -78,7 +78,7 @@ if test -n "$USE_ICU"; then - # TODO: the l is actually endian-dependent - # We could make this set as 'l' or 'b' for little or big, respectively, - # but we'd need to check in a big-endian version of the file. -- ICU_DATA_FILE="icudt${version}l.dat" -+ ICU_DATA_FILE="icudt${version}b.dat" - - dnl We won't build ICU data as a separate file when building - dnl JS standalone so that embedders don't have to deal with it. diff --git a/thunderbird.spec b/thunderbird.spec index 0552558..ecf7ec1 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -106,7 +106,6 @@ Source32: node-stdout-nonblocking-wrapper # Build patches Patch9: mozilla-build-arm.patch -Patch26: build-icu-big-endian.patch Patch226: rhbz-1354671.patch Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch Patch416: firefox-SIOCGSTAMP.patch @@ -117,7 +116,6 @@ Patch103: rhbz-1219542-s390-build.patch # PPC fix Patch304: mozilla-1245783.patch -Patch305: build-big-endian.patch Patch307: build-disable-elfhack.patch # Fedora specific patches @@ -239,10 +237,8 @@ debug %{name}, you want to install %{name}-debuginfo instead. %patch304 -p1 -b .1245783 # Patch for big endian platforms only -%if 0%{?big_endian} -%patch26 -p1 -b .icu -%patch305 -p1 -b .big-endian -%endif +#%if 0%{?big_endian} +#%endif #ARM run-time patch %ifarch aarch64 From 369276051224554aa375a73da18537ccc7302854 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 22 Oct 2020 14:14:18 +0200 Subject: [PATCH 123/402] update to 78.4.0 --- .gitignore | 2 ++ sources | 5 ++--- thunderbird-redhat-default-prefs.js | 2 ++ thunderbird.spec | 9 ++++++--- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 3470aab..a6a5784 100644 --- a/.gitignore +++ b/.gitignore @@ -309,3 +309,5 @@ thunderbird-langpacks-3.1.2-20100803.tar.bz2 /thunderbird-78.3.1.source.tar.xz /thunderbird-langpacks-78.3.1-20200930.tar.xz /cbindgen-vendor-0.14.3.tar.xz +/thunderbird-78.4.0.source.tar.xz +/thunderbird-langpacks-78.4.0-20201022.tar.xz diff --git a/sources b/sources index 7662177..cbc5c37 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ -SHA512 (thunderbird-78.3.1.source.tar.xz) = 16b05e51776ba16503bc5fba02a6d0b5050a206e264a4707544354ad76af61902fd2dcf5d97b82b432dc69362ccd18543a0acccd80e06648e6c6f470886da450 -SHA512 (thunderbird-langpacks-78.3.1-20200930.tar.xz) = 649ed59bdf7b988ca482b3bdb1dd2ea31741daeacc17c783f54e3fc65ac4ac17569d2cc54f357752bd0835914db5f59d638a781634d89a10acd3eee2acb9eb94 -SHA512 (cbindgen-vendor-0.14.3.tar.xz) = 33c8d28547674121f690eea0d3ebac33926a39caacac787bf8ed8b346478822e74da5a4a1f57ab4df4105fa8376739a2ece888845a85bc5712aaed20e4a508bc +SHA512 (thunderbird-78.4.0.source.tar.xz) = 0536a59286dec2f05e3fa00bdcc4f2e52139d9c53d5c086e0074d0d7c6a3b01bbb4beee2c996ffecace2950d1b8b35e2731e6c681ece804b1505acd26f58b308 +SHA512 (thunderbird-langpacks-78.4.0-20201022.tar.xz) = 4430e33dce1404941aad3122f755bfb540fba8fb4ea4a2b4f1f6e564375b8663bf1f341183527fd598f79fb7500c71219aea21e44484ee5dd891cd510750ec70 diff --git a/thunderbird-redhat-default-prefs.js b/thunderbird-redhat-default-prefs.js index bca1328..db95fec 100644 --- a/thunderbird-redhat-default-prefs.js +++ b/thunderbird-redhat-default-prefs.js @@ -30,4 +30,6 @@ pref("network.negotiate-auth.allow-insecure-ntlm-v1", true); pref("security.use_mozillapkix_verification", false); /* Use OS settings for UI language */ pref("intl.locale.requested", ""); +/* Disable telemetry */ +pref("datareporting.healthreport.uploadEnabled", false); diff --git a/thunderbird.spec b/thunderbird.spec index ecf7ec1..e8de2c4 100644 --- a/thunderbird.spec +++ b/thunderbird.spec @@ -83,13 +83,13 @@ ExcludeArch: armv7hl Summary: Mozilla Thunderbird mail/newsgroup client Name: thunderbird -Version: 78.3.1 -Release: 2%{?dist} +Version: 78.4.0 +Release: 1%{?dist} URL: http://www.mozilla.org/projects/thunderbird/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: ftp://ftp.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz %if %{build_langpacks} -Source1: thunderbird-langpacks-%{version}-20200930.tar.xz +Source1: thunderbird-langpacks-%{version}-20201022.tar.xz %endif Source3: get-calendar-langpacks.sh Source4: cbindgen-vendor-0.14.3.tar.xz @@ -725,6 +725,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #=============================================================================== %changelog +* Thu Oct 22 2020 Jan Horak - 78.4.0-1 +- Update to 78.4.0 build1 + * Wed Oct 07 2020 Jan Horak - 78.3.1-2 - Reenable s390x From a818ffcbaf7f1867af26a169d7dc0d1bb5330507 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Thu, 22 Oct 2020 15:01:01 +0200 Subject: [PATCH 124/402] Fixed sources --- sources | 1 + 1 file changed, 1 insertion(+) diff --git a/sources b/sources index cbc5c37..7095e19 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ SHA512 (thunderbird-78.4.0.source.tar.xz) = 0536a59286dec2f05e3fa00bdcc4f2e52139d9c53d5c086e0074d0d7c6a3b01bbb4beee2c996ffecace2950d1b8b35e2731e6c681ece804b1505acd26f58b308 SHA512 (thunderbird-langpacks-78.4.0-20201022.tar.xz) = 4430e33dce1404941aad3122f755bfb540fba8fb4ea4a2b4f1f6e564375b8663bf1f341183527fd598f79fb7500c71219aea21e44484ee5dd891cd510750ec70 +SHA512 (cbindgen-vendor-0.14.3.tar.xz) = 33c8d28547674121f690eea0d3ebac33926a39caacac787bf8ed8b346478822e74da5a4a1f57ab4df4105fa8376739a2ece888845a85bc5712aaed20e4a508bc From 14aa15c9b8cee6431903e093f3ad0f66d82f54b5 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 23 Oct 2020 11:50:20 +0200 Subject: [PATCH 125/402] Disabled telemetry --- thunderbird-redhat-default-prefs.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/thunderbird-redhat-default-prefs.js b/thunderbird-redhat-default-prefs.js index db95fec..c590a50 100644 --- a/thunderbird-redhat-default-prefs.js +++ b/thunderbird-redhat-default-prefs.js @@ -32,4 +32,5 @@ pref("security.use_mozillapkix_verification", false); pref("intl.locale.requested", ""); /* Disable telemetry */ pref("datareporting.healthreport.uploadEnabled", false); - +pref("datareporting.policy.dataSubmissionEnabled", false); +pref("toolkit.telemetry.archive.enabled", false); From 86967ddc206310ba7bb9eb57a933031909288ce2 Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Fri, 23 Oct 2020 13:33:38 +0200 Subject: [PATCH 126/402] Rust 1.47 build patch added --- rust-1.47.patch | 35276 +++++++++++++++++++++++++++++++++++++++++++++ thunderbird.spec | 2 + 2 files changed, 35278 insertions(+) create mode 100644 rust-1.47.patch diff --git a/rust-1.47.patch b/rust-1.47.patch new file mode 100644 index 0000000..65441a1 --- /dev/null +++ b/rust-1.47.patch @@ -0,0 +1,35276 @@ + +# HG changeset patch +# User Emilio Cobos Álvarez +# Date 1599584448 0 +# Node ID 85c38ea4d34969797eb5d24265cd90cc6841e6ae +# Parent 5aa243a2fe9d77578dd95ce3ab3a2aa6c1e92604 +Bug 1663715 - Update syn and proc-macro2 so that Firefox can build on Rust nightly again. r=froydnj, a=RyanVM + +Generated with: + + cargo update -p syn --precise 1.0.40 + ./mach vendor rust + +Rust issue: https://github.com/rust-lang/rust/issues/76482 + +Differential Revision: https://phabricator.services.mozilla.com/D89473 + +diff --git a/Cargo.lock b/Cargo.lock +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -3712,19 +3712,19 @@ checksum = "ecd45702f76d6d3c75a80564378a + dependencies = [ + "proc-macro2", + "quote", + "syn", + ] + + [[package]] + name = "proc-macro2" +-version = "1.0.5" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" ++version = "1.0.20" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29" + dependencies = [ + "unicode-xid", + ] + + [[package]] + name = "procedural-masquerade" + version = "0.1.1" + source = "registry+https://github.com/rust-lang/crates.io-index" +@@ -4642,19 +4642,19 @@ dependencies = [ + "cc", + "gleam", + "glsl-to-cxx", + "webrender_build", + ] + + [[package]] + name = "syn" +-version = "1.0.5" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" ++version = "1.0.40" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350" + dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", + ] + + [[package]] + name = "sync-guid" +diff --git a/third_party/rust/proc-macro2/.cargo-checksum.json b/third_party/rust/proc-macro2/.cargo-checksum.json +--- a/third_party/rust/proc-macro2/.cargo-checksum.json ++++ b/third_party/rust/proc-macro2/.cargo-checksum.json +@@ -1,1 +1,1 @@ +-{"files":{"Cargo.toml":"e2c1fc6ed317eeef8462fcd192f6b6389e1d84f0d7afeac78f12c23903deddf8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"362a2156f7645528061b6e8487a2eb0f32f1693012ed82ee57afa05c039bba0d","build.rs":"0cc6e2cb919ddbff59cf1d810283939f97a59f0037540c0f2ee3453237635ff8","src/fallback.rs":"5c6379a90735e27abcc40253b223158c6b1e5784f3850bc423335363e87ef038","src/lib.rs":"ae5251296ad3fcd8b600919a993fec0afd8b56da3e11fef6bc7265b273129936","src/strnom.rs":"37f7791f73f123817ad5403af1d4e2a0714be27401729a2d451bc80b1f26bac9","src/wrapper.rs":"81372e910604217a625aa71c47d43e65f4e008456eae93ac39325c9abf10701a","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"c2652e3ae1dfcb94d2e6313b29712c5dcbd0fe62026913e67bb7cebd7560aade","tests/test.rs":"8c427be9cba1fa8d4a16647e53e3545e5863e29e2c0b311c93c9dd1399abf6a1"},"package":"90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0"} +\ No newline at end of file ++{"files":{"Cargo.toml":"c20c4c52342e65ea11ad8382edc636e628e8f8c5ab7cffddc32426b2fe8fe4cd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"e1f9d4fc22cff2c049f166a403b41458632a94357890d31cf0e3ad83807fb430","build.rs":"332185d7ad4c859210f5edd7a76bc95146c8277726a2f81417f34927c4424d68","src/detection.rs":"9d25d896889e65330858f2d6f6223c1b98cd1dad189813ad4161ff189fbda2b8","src/fallback.rs":"239f9a25c0f2ab57592288d944c7f1a0f887536b6d4dc2428a17640af8d10a41","src/lib.rs":"2b1d98424c9b23b547dabf85554120e5e65472026a0f3f711b3a097bca7c32fe","src/parse.rs":"500edee9773132e27e44d0fdaa042b1cb9451e29e65124493986f51710c0664c","src/wrapper.rs":"d36c0dced7ec0e7585c1f935cda836080bcae6de1de3d7851d962e9e11a3ac48","tests/comments.rs":"ea6cbe6f4c8852e6a0612893c7d4f2c144a2e6a134a6c3db641a320cbfc3c800","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"c2652e3ae1dfcb94d2e6313b29712c5dcbd0fe62026913e67bb7cebd7560aade","tests/test.rs":"310c856e27ff61c9ec7f0a5cd96031aac02971557b1621f5e17b089d58e79bcd","tests/test_fmt.rs":"745dfdc41d09c5308c221395eb43f2041f0a1413d2927a813bc2ad4554438fe2"},"package":"175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29"} +\ No newline at end of file +diff --git a/third_party/rust/proc-macro2/Cargo.toml b/third_party/rust/proc-macro2/Cargo.toml +--- a/third_party/rust/proc-macro2/Cargo.toml ++++ b/third_party/rust/proc-macro2/Cargo.toml +@@ -8,36 +8,35 @@ + # If you believe there's an error in this file please file an + # issue against the rust-lang/cargo repository. If you're + # editing this file be aware that the upstream Cargo.toml + # will likely look very different (and much more reasonable) + + [package] + edition = "2018" + name = "proc-macro2" +-version = "1.0.5" +-authors = ["Alex Crichton "] +-description = "A stable implementation of the upcoming new `proc_macro` API. Comes with an\noption, off by default, to also reimplement itself in terms of the upstream\nunstable API.\n" +-homepage = "https://github.com/alexcrichton/proc-macro2" ++version = "1.0.20" ++authors = ["Alex Crichton ", "David Tolnay "] ++description = "A substitute implementation of the compiler's `proc_macro` API to decouple\ntoken-based libraries from the procedural macro use case.\n" + documentation = "https://docs.rs/proc-macro2" + readme = "README.md" + keywords = ["macros"] ++categories = ["development-tools::procedural-macro-helpers"] + license = "MIT OR Apache-2.0" + repository = "https://github.com/alexcrichton/proc-macro2" + [package.metadata.docs.rs] + rustc-args = ["--cfg", "procmacro2_semver_exempt"] + rustdoc-args = ["--cfg", "procmacro2_semver_exempt"] ++targets = ["x86_64-unknown-linux-gnu"] + +-[lib] +-name = "proc_macro2" ++[package.metadata.playground] ++features = ["span-locations"] + [dependencies.unicode-xid] + version = "0.2" + [dev-dependencies.quote] + version = "1.0" + default_features = false + + [features] + default = ["proc-macro"] + nightly = [] + proc-macro = [] + span-locations = [] +-[badges.travis-ci] +-repository = "alexcrichton/proc-macro2" +diff --git a/third_party/rust/proc-macro2/README.md b/third_party/rust/proc-macro2/README.md +--- a/third_party/rust/proc-macro2/README.md ++++ b/third_party/rust/proc-macro2/README.md +@@ -1,11 +1,11 @@ + # proc-macro2 + +-[![Build Status](https://api.travis-ci.com/alexcrichton/proc-macro2.svg?branch=master)](https://travis-ci.com/alexcrichton/proc-macro2) ++[![Build Status](https://img.shields.io/github/workflow/status/alexcrichton/proc-macro2/build%20and%20test)](https://github.com/alexcrichton/proc-macro2/actions) + [![Latest Version](https://img.shields.io/crates/v/proc-macro2.svg)](https://crates.io/crates/proc-macro2) + [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2) + + A wrapper around the procedural macro API of the compiler's `proc_macro` crate. + This library serves two purposes: + + - **Bring proc-macro-like functionality to other contexts like build.rs and + main.rs.** Types from `proc_macro` are entirely specific to procedural macros +diff --git a/third_party/rust/proc-macro2/build.rs b/third_party/rust/proc-macro2/build.rs +--- a/third_party/rust/proc-macro2/build.rs ++++ b/third_party/rust/proc-macro2/build.rs +@@ -9,16 +9,20 @@ + // "wrap_proc_macro" + // Wrap types from libproc_macro rather than polyfilling the whole API. + // Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set, + // because we can't emulate the unstable API without emulating everything + // else. Also enabled unconditionally on nightly, in which case the + // procmacro2_semver_exempt surface area is implemented by using the + // nightly-only proc_macro API. + // ++// "hygiene" ++// Enable Span::mixed_site() and non-dummy behavior of Span::resolved_at ++// and Span::located_at. Enabled on Rust 1.45+. ++// + // "proc_macro_span" + // Enable non-dummy behavior of Span::start and Span::end methods which + // requires an unstable compiler feature. Enabled when building with + // nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable + // features. + // + // "super_unstable" + // Implement the semver exempt API in terms of the nightly-only proc_macro +@@ -52,16 +56,24 @@ fn main() { + // https://github.com/alexcrichton/proc-macro2/issues/147 + println!("cargo:rustc-cfg=procmacro2_semver_exempt"); + } + + if semver_exempt || cfg!(feature = "span-locations") { + println!("cargo:rustc-cfg=span_locations"); + } + ++ if version.minor < 39 { ++ println!("cargo:rustc-cfg=no_bind_by_move_pattern_guard"); ++ } ++ ++ if version.minor >= 45 { ++ println!("cargo:rustc-cfg=hygiene"); ++ } ++ + let target = env::var("TARGET").unwrap(); + if !enable_use_proc_macro(&target) { + return; + } + + println!("cargo:rustc-cfg=use_proc_macro"); + + if version.nightly || !semver_exempt { +diff --git a/third_party/rust/proc-macro2/src/detection.rs b/third_party/rust/proc-macro2/src/detection.rs +new file mode 100644 +--- /dev/null ++++ b/third_party/rust/proc-macro2/src/detection.rs +@@ -0,0 +1,67 @@ ++use std::panic::{self, PanicInfo}; ++use std::sync::atomic::*; ++use std::sync::Once; ++ ++static WORKS: AtomicUsize = AtomicUsize::new(0); ++static INIT: Once = Once::new(); ++ ++pub(crate) fn inside_proc_macro() -> bool { ++ match WORKS.load(Ordering::SeqCst) { ++ 1 => return false, ++ 2 => return true, ++ _ => {} ++ } ++ ++ INIT.call_once(initialize); ++ inside_proc_macro() ++} ++ ++pub(crate) fn force_fallback() { ++ WORKS.store(1, Ordering::SeqCst); ++} ++ ++pub(crate) fn unforce_fallback() { ++ initialize(); ++} ++ ++// Swap in a null panic hook to avoid printing "thread panicked" to stderr, ++// then use catch_unwind to determine whether the compiler's proc_macro is ++// working. When proc-macro2 is used from outside of a procedural macro all ++// of the proc_macro crate's APIs currently panic. ++// ++// The Once is to prevent the possibility of this ordering: ++// ++// thread 1 calls take_hook, gets the user's original hook ++// thread 1 calls set_hook with the null hook ++// thread 2 calls take_hook, thinks null hook is the original hook ++// thread 2 calls set_hook with the null hook ++// thread 1 calls set_hook with the actual original hook ++// thread 2 calls set_hook with what it thinks is the original hook ++// ++// in which the user's hook has been lost. ++// ++// There is still a race condition where a panic in a different thread can ++// happen during the interval that the user's original panic hook is ++// unregistered such that their hook is incorrectly not called. This is ++// sufficiently unlikely and less bad than printing panic messages to stderr ++// on correct use of this crate. Maybe there is a libstd feature request ++// here. For now, if a user needs to guarantee that this failure mode does ++// not occur, they need to call e.g. `proc_macro2::Span::call_site()` from ++// the main thread before launching any other threads. ++fn initialize() { ++ type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; ++ ++ let null_hook: Box = Box::new(|_panic_info| { /* ignore */ }); ++ let sanity_check = &*null_hook as *const PanicHook; ++ let original_hook = panic::take_hook(); ++ panic::set_hook(null_hook); ++ ++ let works = panic::catch_unwind(proc_macro::Span::call_site).is_ok(); ++ WORKS.store(works as usize + 1, Ordering::SeqCst); ++ ++ let hopefully_null_hook = panic::take_hook(); ++ panic::set_hook(original_hook); ++ if sanity_check != &*hopefully_null_hook { ++ panic!("observed race condition in proc_macro2::inside_proc_macro"); ++ } ++} +diff --git a/third_party/rust/proc-macro2/src/fallback.rs b/third_party/rust/proc-macro2/src/fallback.rs +--- a/third_party/rust/proc-macro2/src/fallback.rs ++++ b/third_party/rust/proc-macro2/src/fallback.rs +@@ -1,41 +1,121 @@ ++use crate::parse::{token_stream, Cursor}; ++use crate::{Delimiter, Spacing, TokenTree}; + #[cfg(span_locations)] + use std::cell::RefCell; + #[cfg(span_locations)] + use std::cmp; +-use std::fmt; +-use std::iter; ++use std::fmt::{self, Debug, Display}; ++use std::iter::FromIterator; ++use std::mem; + use std::ops::RangeBounds; + #[cfg(procmacro2_semver_exempt)] + use std::path::Path; + use std::path::PathBuf; + use std::str::FromStr; + use std::vec; +- +-use crate::strnom::{block_comment, skip_whitespace, whitespace, word_break, Cursor, PResult}; +-use crate::{Delimiter, Punct, Spacing, TokenTree}; + use unicode_xid::UnicodeXID; + ++/// Force use of proc-macro2's fallback implementation of the API for now, even ++/// if the compiler's implementation is available. ++pub fn force() { ++ #[cfg(wrap_proc_macro)] ++ crate::detection::force_fallback(); ++} ++ ++/// Resume using the compiler's implementation of the proc macro API if it is ++/// available. ++pub fn unforce() { ++ #[cfg(wrap_proc_macro)] ++ crate::detection::unforce_fallback(); ++} ++ + #[derive(Clone)] +-pub struct TokenStream { +- inner: Vec, ++pub(crate) struct TokenStream { ++ pub(crate) inner: Vec, + } + + #[derive(Debug)] +-pub struct LexError; ++pub(crate) struct LexError; + + impl TokenStream { + pub fn new() -> TokenStream { + TokenStream { inner: Vec::new() } + } + + pub fn is_empty(&self) -> bool { + self.inner.len() == 0 + } ++ ++ fn take_inner(&mut self) -> Vec { ++ mem::replace(&mut self.inner, Vec::new()) ++ } ++ ++ fn push_token(&mut self, token: TokenTree) { ++ // https://github.com/alexcrichton/proc-macro2/issues/235 ++ match token { ++ #[cfg(not(no_bind_by_move_pattern_guard))] ++ TokenTree::Literal(crate::Literal { ++ #[cfg(wrap_proc_macro)] ++ inner: crate::imp::Literal::Fallback(literal), ++ #[cfg(not(wrap_proc_macro))] ++ inner: literal, ++ .. ++ }) if literal.text.starts_with('-') => { ++ push_negative_literal(self, literal); ++ } ++ #[cfg(no_bind_by_move_pattern_guard)] ++ TokenTree::Literal(crate::Literal { ++ #[cfg(wrap_proc_macro)] ++ inner: crate::imp::Literal::Fallback(literal), ++ #[cfg(not(wrap_proc_macro))] ++ inner: literal, ++ .. ++ }) => { ++ if literal.text.starts_with('-') { ++ push_negative_literal(self, literal); ++ } else { ++ self.inner ++ .push(TokenTree::Literal(crate::Literal::_new_stable(literal))); ++ } ++ } ++ _ => self.inner.push(token), ++ } ++ ++ #[cold] ++ fn push_negative_literal(stream: &mut TokenStream, mut literal: Literal) { ++ literal.text.remove(0); ++ let mut punct = crate::Punct::new('-', Spacing::Alone); ++ punct.set_span(crate::Span::_new_stable(literal.span)); ++ stream.inner.push(TokenTree::Punct(punct)); ++ stream ++ .inner ++ .push(TokenTree::Literal(crate::Literal::_new_stable(literal))); ++ } ++ } ++} ++ ++// Nonrecursive to prevent stack overflow. ++impl Drop for TokenStream { ++ fn drop(&mut self) { ++ while let Some(token) = self.inner.pop() { ++ let group = match token { ++ TokenTree::Group(group) => group.inner, ++ _ => continue, ++ }; ++ #[cfg(wrap_proc_macro)] ++ let group = match group { ++ crate::imp::Group::Fallback(group) => group, ++ _ => continue, ++ }; ++ let mut group = group; ++ self.inner.extend(group.stream.take_inner()); ++ } ++ } + } + + #[cfg(span_locations)] + fn get_cursor(src: &str) -> Cursor { + // Create a dummy file & add it to the source map + SOURCE_MAP.with(|cm| { + let mut cm = cm.borrow_mut(); + let name = format!("", cm.files.len()); +@@ -54,68 +134,49 @@ fn get_cursor(src: &str) -> Cursor { + + impl FromStr for TokenStream { + type Err = LexError; + + fn from_str(src: &str) -> Result { + // Create a dummy file & add it to the source map + let cursor = get_cursor(src); + +- match token_stream(cursor) { +- Ok((input, output)) => { +- if skip_whitespace(input).len() != 0 { +- Err(LexError) +- } else { +- Ok(output) +- } +- } +- Err(LexError) => Err(LexError), ++ let (rest, tokens) = token_stream(cursor)?; ++ if rest.is_empty() { ++ Ok(tokens) ++ } else { ++ Err(LexError) + } + } + } + +-impl fmt::Display for TokenStream { ++impl Display for TokenStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut joint = false; + for (i, tt) in self.inner.iter().enumerate() { + if i != 0 && !joint { + write!(f, " ")?; + } + joint = false; +- match *tt { +- TokenTree::Group(ref tt) => { +- let (start, end) = match tt.delimiter() { +- Delimiter::Parenthesis => ("(", ")"), +- Delimiter::Brace => ("{", "}"), +- Delimiter::Bracket => ("[", "]"), +- Delimiter::None => ("", ""), +- }; +- if tt.stream().into_iter().next().is_none() { +- write!(f, "{} {}", start, end)? +- } else { +- write!(f, "{} {} {}", start, tt.stream(), end)? +- } ++ match tt { ++ TokenTree::Group(tt) => Display::fmt(tt, f), ++ TokenTree::Ident(tt) => Display::fmt(tt, f), ++ TokenTree::Punct(tt) => { ++ joint = tt.spacing() == Spacing::Joint; ++ Display::fmt(tt, f) + } +- TokenTree::Ident(ref tt) => write!(f, "{}", tt)?, +- TokenTree::Punct(ref tt) => { +- write!(f, "{}", tt.as_char())?; +- match tt.spacing() { +- Spacing::Alone => {} +- Spacing::Joint => joint = true, +- } +- } +- TokenTree::Literal(ref tt) => write!(f, "{}", tt)?, +- } ++ TokenTree::Literal(tt) => Display::fmt(tt, f), ++ }? + } + + Ok(()) + } + } + +-impl fmt::Debug for TokenStream { ++impl Debug for TokenStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("TokenStream ")?; + f.debug_list().entries(self.clone()).finish() + } + } + + #[cfg(use_proc_macro)] + impl From for TokenStream { +@@ -134,122 +195,107 @@ impl From for proc_macro::T + .to_string() + .parse() + .expect("failed to parse to compiler tokens") + } + } + + impl From for TokenStream { + fn from(tree: TokenTree) -> TokenStream { +- TokenStream { inner: vec![tree] } ++ let mut stream = TokenStream::new(); ++ stream.push_token(tree); ++ stream + } + } + +-impl iter::FromIterator for TokenStream { +- fn from_iter>(streams: I) -> Self { +- let mut v = Vec::new(); +- +- for token in streams.into_iter() { +- v.push(token); +- } +- +- TokenStream { inner: v } ++impl FromIterator for TokenStream { ++ fn from_iter>(tokens: I) -> Self { ++ let mut stream = TokenStream::new(); ++ stream.extend(tokens); ++ stream + } + } + +-impl iter::FromIterator for TokenStream { ++impl FromIterator for TokenStream { + fn from_iter>(streams: I) -> Self { + let mut v = Vec::new(); + +- for stream in streams.into_iter() { +- v.extend(stream.inner); ++ for mut stream in streams { ++ v.extend(stream.take_inner()); + } + + TokenStream { inner: v } + } + } + + impl Extend for TokenStream { +- fn extend>(&mut self, streams: I) { +- self.inner.extend(streams); ++ fn extend>(&mut self, tokens: I) { ++ tokens.into_iter().for_each(|token| self.push_token(token)); + } + } + + impl Extend for TokenStream { + fn extend>(&mut self, streams: I) { +- self.inner +- .extend(streams.into_iter().flat_map(|stream| stream)); ++ self.inner.extend(streams.into_iter().flatten()); + } + } + +-pub type TokenTreeIter = vec::IntoIter; ++pub(crate) type TokenTreeIter = vec::IntoIter; + + impl IntoIterator for TokenStream { + type Item = TokenTree; + type IntoIter = TokenTreeIter; + +- fn into_iter(self) -> TokenTreeIter { +- self.inner.into_iter() ++ fn into_iter(mut self) -> TokenTreeIter { ++ self.take_inner().into_iter() + } + } + + #[derive(Clone, PartialEq, Eq)] +-pub struct SourceFile { ++pub(crate) struct SourceFile { + path: PathBuf, + } + + impl SourceFile { + /// Get the path to this source file as a string. + pub fn path(&self) -> PathBuf { + self.path.clone() + } + + pub fn is_real(&self) -> bool { + // XXX(nika): Support real files in the future? + false + } + } + +-impl fmt::Debug for SourceFile { ++impl Debug for SourceFile { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("SourceFile") + .field("path", &self.path()) + .field("is_real", &self.is_real()) + .finish() + } + } + + #[derive(Clone, Copy, Debug, PartialEq, Eq)] +-pub struct LineColumn { ++pub(crate) struct LineColumn { + pub line: usize, + pub column: usize, + } + + #[cfg(span_locations)] + thread_local! { + static SOURCE_MAP: RefCell = RefCell::new(SourceMap { + // NOTE: We start with a single dummy file which all call_site() and + // def_site() spans reference. +- files: vec![{ ++ files: vec![FileInfo { + #[cfg(procmacro2_semver_exempt)] +- { +- FileInfo { +- name: "".to_owned(), +- span: Span { lo: 0, hi: 0 }, +- lines: vec![0], +- } +- } +- +- #[cfg(not(procmacro2_semver_exempt))] +- { +- FileInfo { +- span: Span { lo: 0, hi: 0 }, +- lines: vec![0], +- } +- } ++ name: "".to_owned(), ++ span: Span { lo: 0, hi: 0 }, ++ lines: vec![0], + }], + }); + } + + #[cfg(span_locations)] + struct FileInfo { + #[cfg(procmacro2_semver_exempt)] + name: String, +@@ -277,26 +323,31 @@ impl FileInfo { + } + } + + fn span_within(&self, span: Span) -> bool { + span.lo >= self.span.lo && span.hi <= self.span.hi + } + } + +-/// Computesthe offsets of each line in the given source string. ++/// Computes the offsets of each line in the given source string ++/// and the total number of characters + #[cfg(span_locations)] +-fn lines_offsets(s: &str) -> Vec { ++fn lines_offsets(s: &str) -> (usize, Vec) { + let mut lines = vec![0]; +- let mut prev = 0; +- while let Some(len) = s[prev..].find('\n') { +- prev += len + 1; +- lines.push(prev); ++ let mut total = 0; ++ ++ for ch in s.chars() { ++ total += 1; ++ if ch == '\n' { ++ lines.push(total); ++ } + } +- lines ++ ++ (total, lines) + } + + #[cfg(span_locations)] + struct SourceMap { + files: Vec, + } + + #[cfg(span_locations)] +@@ -305,81 +356,83 @@ impl SourceMap { + // Add 1 so there's always space between files. + // + // We'll always have at least 1 file, as we initialize our files list + // with a dummy file. + self.files.last().unwrap().span.hi + 1 + } + + fn add_file(&mut self, name: &str, src: &str) -> Span { +- let lines = lines_offsets(src); ++ let (len, lines) = lines_offsets(src); + let lo = self.next_start_pos(); + // XXX(nika): Shouild we bother doing a checked cast or checked add here? + let span = Span { + lo, +- hi: lo + (src.len() as u32), ++ hi: lo + (len as u32), + }; + +- #[cfg(procmacro2_semver_exempt)] + self.files.push(FileInfo { ++ #[cfg(procmacro2_semver_exempt)] + name: name.to_owned(), + span, + lines, + }); + + #[cfg(not(procmacro2_semver_exempt))] +- self.files.push(FileInfo { span, lines }); + let _ = name; + + span + } + + fn fileinfo(&self, span: Span) -> &FileInfo { + for file in &self.files { + if file.span_within(span) { + return file; + } + } + panic!("Invalid span with no related FileInfo!"); + } + } + + #[derive(Clone, Copy, PartialEq, Eq)] +-pub struct Span { ++pub(crate) struct Span { + #[cfg(span_locations)] +- lo: u32, ++ pub(crate) lo: u32, + #[cfg(span_locations)] +- hi: u32, ++ pub(crate) hi: u32, + } + + impl Span { + #[cfg(not(span_locations))] + pub fn call_site() -> Span { + Span {} + } + + #[cfg(span_locations)] + pub fn call_site() -> Span { + Span { lo: 0, hi: 0 } + } + ++ #[cfg(hygiene)] ++ pub fn mixed_site() -> Span { ++ Span::call_site() ++ } ++ + #[cfg(procmacro2_semver_exempt)] + pub fn def_site() -> Span { + Span::call_site() + } + +- #[cfg(procmacro2_semver_exempt)] + pub fn resolved_at(&self, _other: Span) -> Span { + // Stable spans consist only of line/column information, so + // `resolved_at` and `located_at` only select which span the + // caller wants line/column information from. + *self + } + +- #[cfg(procmacro2_semver_exempt)] + pub fn located_at(&self, other: Span) -> Span { + other + } + + #[cfg(procmacro2_semver_exempt)] + pub fn source_file(&self) -> SourceFile { + SOURCE_MAP.with(|cm| { + let cm = cm.borrow(); +@@ -422,36 +475,69 @@ impl Span { + return None; + } + Some(Span { + lo: cmp::min(self.lo, other.lo), + hi: cmp::max(self.hi, other.hi), + }) + }) + } ++ ++ #[cfg(not(span_locations))] ++ fn first_byte(self) -> Self { ++ self ++ } ++ ++ #[cfg(span_locations)] ++ fn first_byte(self) -> Self { ++ Span { ++ lo: self.lo, ++ hi: cmp::min(self.lo.saturating_add(1), self.hi), ++ } ++ } ++ ++ #[cfg(not(span_locations))] ++ fn last_byte(self) -> Self { ++ self ++ } ++ ++ #[cfg(span_locations)] ++ fn last_byte(self) -> Self { ++ Span { ++ lo: cmp::max(self.hi.saturating_sub(1), self.lo), ++ hi: self.hi, ++ } ++ } + } + +-impl fmt::Debug for Span { ++impl Debug for Span { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- #[cfg(procmacro2_semver_exempt)] ++ #[cfg(span_locations)] + return write!(f, "bytes({}..{})", self.lo, self.hi); + +- #[cfg(not(procmacro2_semver_exempt))] ++ #[cfg(not(span_locations))] + write!(f, "Span") + } + } + +-pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { +- if cfg!(procmacro2_semver_exempt) { ++pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { ++ #[cfg(span_locations)] ++ { ++ if span.lo == 0 && span.hi == 0 { ++ return; ++ } ++ } ++ ++ if cfg!(span_locations) { + debug.field("span", &span); + } + } + + #[derive(Clone)] +-pub struct Group { ++pub(crate) struct Group { + delimiter: Delimiter, + stream: TokenStream, + span: Span, + } + + impl Group { + pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { + Group { +@@ -469,58 +555,67 @@ impl Group { + self.stream.clone() + } + + pub fn span(&self) -> Span { + self.span + } + + pub fn span_open(&self) -> Span { +- self.span ++ self.span.first_byte() + } + + pub fn span_close(&self) -> Span { +- self.span ++ self.span.last_byte() + } + + pub fn set_span(&mut self, span: Span) { + self.span = span; + } + } + +-impl fmt::Display for Group { ++impl Display for Group { ++ // We attempt to match libproc_macro's formatting. ++ // Empty parens: () ++ // Nonempty parens: (...) ++ // Empty brackets: [] ++ // Nonempty brackets: [...] ++ // Empty braces: { } ++ // Nonempty braces: { ... } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- let (left, right) = match self.delimiter { ++ let (open, close) = match self.delimiter { + Delimiter::Parenthesis => ("(", ")"), +- Delimiter::Brace => ("{", "}"), ++ Delimiter::Brace => ("{ ", "}"), + Delimiter::Bracket => ("[", "]"), + Delimiter::None => ("", ""), + }; + +- f.write_str(left)?; +- self.stream.fmt(f)?; +- f.write_str(right)?; ++ f.write_str(open)?; ++ Display::fmt(&self.stream, f)?; ++ if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() { ++ f.write_str(" ")?; ++ } ++ f.write_str(close)?; + + Ok(()) + } + } + +-impl fmt::Debug for Group { ++impl Debug for Group { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut debug = fmt.debug_struct("Group"); + debug.field("delimiter", &self.delimiter); + debug.field("stream", &self.stream); +- #[cfg(procmacro2_semver_exempt)] +- debug.field("span", &self.span); ++ debug_span_field_if_nontrivial(&mut debug, self.span); + debug.finish() + } + } + + #[derive(Clone)] +-pub struct Ident { ++pub(crate) struct Ident { + sym: String, + span: Span, + raw: bool, + } + + impl Ident { + fn _new(string: &str, raw: bool, span: Span) -> Ident { + validate_ident(string); +@@ -544,26 +639,24 @@ impl Ident { + self.span + } + + pub fn set_span(&mut self, span: Span) { + self.span = span; + } + } + +-#[inline] +-fn is_ident_start(c: char) -> bool { ++pub(crate) fn is_ident_start(c: char) -> bool { + ('a' <= c && c <= 'z') + || ('A' <= c && c <= 'Z') + || c == '_' + || (c > '\x7f' && UnicodeXID::is_xid_start(c)) + } + +-#[inline] +-fn is_ident_continue(c: char) -> bool { ++pub(crate) fn is_ident_continue(c: char) -> bool { + ('a' <= c && c <= 'z') + || ('A' <= c && c <= 'Z') + || c == '_' + || ('0' <= c && c <= '9') + || (c > '\x7f' && UnicodeXID::is_xid_continue(c)) + } + + fn validate_ident(string: &str) { +@@ -610,49 +703,49 @@ where + if self.raw { + other.starts_with("r#") && self.sym == other[2..] + } else { + self.sym == other + } + } + } + +-impl fmt::Display for Ident { ++impl Display for Ident { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.raw { +- "r#".fmt(f)?; ++ f.write_str("r#")?; + } +- self.sym.fmt(f) ++ Display::fmt(&self.sym, f) + } + } + +-impl fmt::Debug for Ident { ++impl Debug for Ident { + // Ident(proc_macro), Ident(r#union) +- #[cfg(not(procmacro2_semver_exempt))] ++ #[cfg(not(span_locations))] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut debug = f.debug_tuple("Ident"); + debug.field(&format_args!("{}", self)); + debug.finish() + } + + // Ident { + // sym: proc_macro, + // span: bytes(128..138) + // } +- #[cfg(procmacro2_semver_exempt)] ++ #[cfg(span_locations)] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut debug = f.debug_struct("Ident"); + debug.field("sym", &format_args!("{}", self)); +- debug.field("span", &self.span); ++ debug_span_field_if_nontrivial(&mut debug, self.span); + debug.finish() + } + } + + #[derive(Clone)] +-pub struct Literal { ++pub(crate) struct Literal { + text: String, + span: Span, + } + + macro_rules! suffixed_numbers { + ($($name:ident => $kind:ident,)*) => ($( + pub fn $name(n: $kind) -> Literal { + Literal::_new(format!(concat!("{}", stringify!($kind)), n)) +@@ -664,17 +757,17 @@ macro_rules! unsuffixed_numbers { + ($($name:ident => $kind:ident,)*) => ($( + pub fn $name(n: $kind) -> Literal { + Literal::_new(n.to_string()) + } + )*) + } + + impl Literal { +- fn _new(text: String) -> Literal { ++ pub(crate) fn _new(text: String) -> Literal { + Literal { + text, + span: Span::call_site(), + } + } + + suffixed_numbers! { + u8_suffixed => u8, +@@ -706,61 +799,62 @@ impl Literal { + i32_unsuffixed => i32, + i64_unsuffixed => i64, + i128_unsuffixed => i128, + isize_unsuffixed => isize, + } + + pub fn f32_unsuffixed(f: f32) -> Literal { + let mut s = f.to_string(); +- if !s.contains(".") { ++ if !s.contains('.') { + s.push_str(".0"); + } + Literal::_new(s) + } + + pub fn f64_unsuffixed(f: f64) -> Literal { + let mut s = f.to_string(); +- if !s.contains(".") { ++ if !s.contains('.') { + s.push_str(".0"); + } + Literal::_new(s) + } + + pub fn string(t: &str) -> Literal { + let mut text = String::with_capacity(t.len() + 2); + text.push('"'); + for c in t.chars() { + if c == '\'' { +- // escape_default turns this into "\'" which is unnecessary. ++ // escape_debug turns this into "\'" which is unnecessary. + text.push(c); + } else { +- text.extend(c.escape_default()); ++ text.extend(c.escape_debug()); + } + } + text.push('"'); + Literal::_new(text) + } + + pub fn character(t: char) -> Literal { + let mut text = String::new(); + text.push('\''); + if t == '"' { +- // escape_default turns this into '\"' which is unnecessary. ++ // escape_debug turns this into '\"' which is unnecessary. + text.push(t); + } else { +- text.extend(t.escape_default()); ++ text.extend(t.escape_debug()); + } + text.push('\''); + Literal::_new(text) + } + + pub fn byte_string(bytes: &[u8]) -> Literal { + let mut escaped = "b\"".to_string(); + for b in bytes { ++ #[allow(clippy::match_overlapping_arm)] + match *b { + b'\0' => escaped.push_str(r"\0"), + b'\t' => escaped.push_str(r"\t"), + b'\n' => escaped.push_str(r"\n"), + b'\r' => escaped.push_str(r"\r"), + b'"' => escaped.push_str("\\\""), + b'\\' => escaped.push_str("\\\\"), + b'\x20'..=b'\x7E' => escaped.push(*b as char), +@@ -779,656 +873,22 @@ impl Literal { + self.span = span; + } + + pub fn subspan>(&self, _range: R) -> Option { + None + } + } + +-impl fmt::Display for Literal { ++impl Display for Literal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.text.fmt(f) +- } +-} +- +-impl fmt::Debug for Literal { +- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +- let mut debug = fmt.debug_struct("Literal"); +- debug.field("lit", &format_args!("{}", self.text)); +- #[cfg(procmacro2_semver_exempt)] +- debug.field("span", &self.span); +- debug.finish() +- } +-} +- +-fn token_stream(mut input: Cursor) -> PResult { +- let mut trees = Vec::new(); +- loop { +- let input_no_ws = skip_whitespace(input); +- if input_no_ws.rest.len() == 0 { +- break; +- } +- if let Ok((a, tokens)) = doc_comment(input_no_ws) { +- input = a; +- trees.extend(tokens); +- continue; +- } +- +- let (a, tt) = match token_tree(input_no_ws) { +- Ok(p) => p, +- Err(_) => break, +- }; +- trees.push(tt); +- input = a; +- } +- Ok((input, TokenStream { inner: trees })) +-} +- +-#[cfg(not(span_locations))] +-fn spanned<'a, T>( +- input: Cursor<'a>, +- f: fn(Cursor<'a>) -> PResult<'a, T>, +-) -> PResult<'a, (T, crate::Span)> { +- let (a, b) = f(skip_whitespace(input))?; +- Ok((a, ((b, crate::Span::_new_stable(Span::call_site()))))) +-} +- +-#[cfg(span_locations)] +-fn spanned<'a, T>( +- input: Cursor<'a>, +- f: fn(Cursor<'a>) -> PResult<'a, T>, +-) -> PResult<'a, (T, crate::Span)> { +- let input = skip_whitespace(input); +- let lo = input.off; +- let (a, b) = f(input)?; +- let hi = a.off; +- let span = crate::Span::_new_stable(Span { lo, hi }); +- Ok((a, (b, span))) +-} +- +-fn token_tree(input: Cursor) -> PResult { +- let (rest, (mut tt, span)) = spanned(input, token_kind)?; +- tt.set_span(span); +- Ok((rest, tt)) +-} +- +-named!(token_kind -> TokenTree, alt!( +- map!(group, |g| TokenTree::Group(crate::Group::_new_stable(g))) +- | +- map!(literal, |l| TokenTree::Literal(crate::Literal::_new_stable(l))) // must be before symbol +- | +- map!(op, TokenTree::Punct) +- | +- symbol_leading_ws +-)); +- +-named!(group -> Group, alt!( +- delimited!( +- punct!("("), +- token_stream, +- punct!(")") +- ) => { |ts| Group::new(Delimiter::Parenthesis, ts) } +- | +- delimited!( +- punct!("["), +- token_stream, +- punct!("]") +- ) => { |ts| Group::new(Delimiter::Bracket, ts) } +- | +- delimited!( +- punct!("{"), +- token_stream, +- punct!("}") +- ) => { |ts| Group::new(Delimiter::Brace, ts) } +-)); +- +-fn symbol_leading_ws(input: Cursor) -> PResult { +- symbol(skip_whitespace(input)) +-} +- +-fn symbol(input: Cursor) -> PResult { +- let raw = input.starts_with("r#"); +- let rest = input.advance((raw as usize) << 1); +- +- let (rest, sym) = symbol_not_raw(rest)?; +- +- if !raw { +- let ident = crate::Ident::new(sym, crate::Span::call_site()); +- return Ok((rest, ident.into())); +- } +- +- if sym == "_" { +- return Err(LexError); +- } +- +- let ident = crate::Ident::_new_raw(sym, crate::Span::call_site()); +- Ok((rest, ident.into())) +-} +- +-fn symbol_not_raw(input: Cursor) -> PResult<&str> { +- let mut chars = input.char_indices(); +- +- match chars.next() { +- Some((_, ch)) if is_ident_start(ch) => {} +- _ => return Err(LexError), +- } +- +- let mut end = input.len(); +- for (i, ch) in chars { +- if !is_ident_continue(ch) { +- end = i; +- break; +- } +- } +- +- Ok((input.advance(end), &input.rest[..end])) +-} +- +-fn literal(input: Cursor) -> PResult { +- let input_no_ws = skip_whitespace(input); +- +- match literal_nocapture(input_no_ws) { +- Ok((a, ())) => { +- let start = input.len() - input_no_ws.len(); +- let len = input_no_ws.len() - a.len(); +- let end = start + len; +- Ok((a, Literal::_new(input.rest[start..end].to_string()))) +- } +- Err(LexError) => Err(LexError), ++ Display::fmt(&self.text, f) + } + } + +-named!(literal_nocapture -> (), alt!( +- string +- | +- byte_string +- | +- byte +- | +- character +- | +- float +- | +- int +-)); +- +-named!(string -> (), alt!( +- quoted_string +- | +- preceded!( +- punct!("r"), +- raw_string +- ) => { |_| () } +-)); +- +-named!(quoted_string -> (), do_parse!( +- punct!("\"") >> +- cooked_string >> +- tag!("\"") >> +- option!(symbol_not_raw) >> +- (()) +-)); +- +-fn cooked_string(input: Cursor) -> PResult<()> { +- let mut chars = input.char_indices().peekable(); +- while let Some((byte_offset, ch)) = chars.next() { +- match ch { +- '"' => { +- return Ok((input.advance(byte_offset), ())); +- } +- '\r' => { +- if let Some((_, '\n')) = chars.next() { +- // ... +- } else { +- break; +- } +- } +- '\\' => match chars.next() { +- Some((_, 'x')) => { +- if !backslash_x_char(&mut chars) { +- break; +- } +- } +- Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\')) +- | Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {} +- Some((_, 'u')) => { +- if !backslash_u(&mut chars) { +- break; +- } +- } +- Some((_, '\n')) | Some((_, '\r')) => { +- while let Some(&(_, ch)) = chars.peek() { +- if ch.is_whitespace() { +- chars.next(); +- } else { +- break; +- } +- } +- } +- _ => break, +- }, +- _ch => {} +- } +- } +- Err(LexError) +-} +- +-named!(byte_string -> (), alt!( +- delimited!( +- punct!("b\""), +- cooked_byte_string, +- tag!("\"") +- ) => { |_| () } +- | +- preceded!( +- punct!("br"), +- raw_string +- ) => { |_| () } +-)); +- +-fn cooked_byte_string(mut input: Cursor) -> PResult<()> { +- let mut bytes = input.bytes().enumerate(); +- 'outer: while let Some((offset, b)) = bytes.next() { +- match b { +- b'"' => { +- return Ok((input.advance(offset), ())); +- } +- b'\r' => { +- if let Some((_, b'\n')) = bytes.next() { +- // ... +- } else { +- break; +- } +- } +- b'\\' => match bytes.next() { +- Some((_, b'x')) => { +- if !backslash_x_byte(&mut bytes) { +- break; +- } +- } +- Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\')) +- | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {} +- Some((newline, b'\n')) | Some((newline, b'\r')) => { +- let rest = input.advance(newline + 1); +- for (offset, ch) in rest.char_indices() { +- if !ch.is_whitespace() { +- input = rest.advance(offset); +- bytes = input.bytes().enumerate(); +- continue 'outer; +- } +- } +- break; +- } +- _ => break, +- }, +- b if b < 0x80 => {} +- _ => break, +- } +- } +- Err(LexError) +-} +- +-fn raw_string(input: Cursor) -> PResult<()> { +- let mut chars = input.char_indices(); +- let mut n = 0; +- while let Some((byte_offset, ch)) = chars.next() { +- match ch { +- '"' => { +- n = byte_offset; +- break; +- } +- '#' => {} +- _ => return Err(LexError), +- } +- } +- for (byte_offset, ch) in chars { +- match ch { +- '"' if input.advance(byte_offset + 1).starts_with(&input.rest[..n]) => { +- let rest = input.advance(byte_offset + 1 + n); +- return Ok((rest, ())); +- } +- '\r' => {} +- _ => {} +- } +- } +- Err(LexError) +-} +- +-named!(byte -> (), do_parse!( +- punct!("b") >> +- tag!("'") >> +- cooked_byte >> +- tag!("'") >> +- (()) +-)); +- +-fn cooked_byte(input: Cursor) -> PResult<()> { +- let mut bytes = input.bytes().enumerate(); +- let ok = match bytes.next().map(|(_, b)| b) { +- Some(b'\\') => match bytes.next().map(|(_, b)| b) { +- Some(b'x') => backslash_x_byte(&mut bytes), +- Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'') +- | Some(b'"') => true, +- _ => false, +- }, +- b => b.is_some(), +- }; +- if ok { +- match bytes.next() { +- Some((offset, _)) => { +- if input.chars().as_str().is_char_boundary(offset) { +- Ok((input.advance(offset), ())) +- } else { +- Err(LexError) +- } +- } +- None => Ok((input.advance(input.len()), ())), +- } +- } else { +- Err(LexError) +- } +-} +- +-named!(character -> (), do_parse!( +- punct!("'") >> +- cooked_char >> +- tag!("'") >> +- (()) +-)); +- +-fn cooked_char(input: Cursor) -> PResult<()> { +- let mut chars = input.char_indices(); +- let ok = match chars.next().map(|(_, ch)| ch) { +- Some('\\') => match chars.next().map(|(_, ch)| ch) { +- Some('x') => backslash_x_char(&mut chars), +- Some('u') => backslash_u(&mut chars), +- Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => { +- true +- } +- _ => false, +- }, +- ch => ch.is_some(), +- }; +- if ok { +- match chars.next() { +- Some((idx, _)) => Ok((input.advance(idx), ())), +- None => Ok((input.advance(input.len()), ())), +- } +- } else { +- Err(LexError) ++impl Debug for Literal { ++ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { ++ let mut debug = fmt.debug_struct("Literal"); ++ debug.field("lit", &format_args!("{}", self.text)); ++ debug_span_field_if_nontrivial(&mut debug, self.span); ++ debug.finish() + } + } +- +-macro_rules! next_ch { +- ($chars:ident @ $pat:pat $(| $rest:pat)*) => { +- match $chars.next() { +- Some((_, ch)) => match ch { +- $pat $(| $rest)* => ch, +- _ => return false, +- }, +- None => return false +- } +- }; +-} +- +-fn backslash_x_char(chars: &mut I) -> bool +-where +- I: Iterator, +-{ +- next_ch!(chars @ '0'..='7'); +- next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); +- true +-} +- +-fn backslash_x_byte(chars: &mut I) -> bool +-where +- I: Iterator, +-{ +- next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); +- next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); +- true +-} +- +-fn backslash_u(chars: &mut I) -> bool +-where +- I: Iterator, +-{ +- next_ch!(chars @ '{'); +- next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); +- loop { +- let c = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F' | '_' | '}'); +- if c == '}' { +- return true; +- } +- } +-} +- +-fn float(input: Cursor) -> PResult<()> { +- let (mut rest, ()) = float_digits(input)?; +- if let Some(ch) = rest.chars().next() { +- if is_ident_start(ch) { +- rest = symbol_not_raw(rest)?.0; +- } +- } +- word_break(rest) +-} +- +-fn float_digits(input: Cursor) -> PResult<()> { +- let mut chars = input.chars().peekable(); +- match chars.next() { +- Some(ch) if ch >= '0' && ch <= '9' => {} +- _ => return Err(LexError), +- } +- +- let mut len = 1; +- let mut has_dot = false; +- let mut has_exp = false; +- while let Some(&ch) = chars.peek() { +- match ch { +- '0'..='9' | '_' => { +- chars.next(); +- len += 1; +- } +- '.' => { +- if has_dot { +- break; +- } +- chars.next(); +- if chars +- .peek() +- .map(|&ch| ch == '.' || is_ident_start(ch)) +- .unwrap_or(false) +- { +- return Err(LexError); +- } +- len += 1; +- has_dot = true; +- } +- 'e' | 'E' => { +- chars.next(); +- len += 1; +- has_exp = true; +- break; +- } +- _ => break, +- } +- } +- +- let rest = input.advance(len); +- if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) { +- return Err(LexError); +- } +- +- if has_exp { +- let mut has_exp_value = false; +- while let Some(&ch) = chars.peek() { +- match ch { +- '+' | '-' => { +- if has_exp_value { +- break; +- } +- chars.next(); +- len += 1; +- } +- '0'..='9' => { +- chars.next(); +- len += 1; +- has_exp_value = true; +- } +- '_' => { +- chars.next(); +- len += 1; +- } +- _ => break, +- } +- } +- if !has_exp_value { +- return Err(LexError); +- } +- } +- +- Ok((input.advance(len), ())) +-} +- +-fn int(input: Cursor) -> PResult<()> { +- let (mut rest, ()) = digits(input)?; +- if let Some(ch) = rest.chars().next() { +- if is_ident_start(ch) { +- rest = symbol_not_raw(rest)?.0; +- } +- } +- word_break(rest) +-} +- +-fn digits(mut input: Cursor) -> PResult<()> { +- let base = if input.starts_with("0x") { +- input = input.advance(2); +- 16 +- } else if input.starts_with("0o") { +- input = input.advance(2); +- 8 +- } else if input.starts_with("0b") { +- input = input.advance(2); +- 2 +- } else { +- 10 +- }; +- +- let mut len = 0; +- let mut empty = true; +- for b in input.bytes() { +- let digit = match b { +- b'0'..=b'9' => (b - b'0') as u64, +- b'a'..=b'f' => 10 + (b - b'a') as u64, +- b'A'..=b'F' => 10 + (b - b'A') as u64, +- b'_' => { +- if empty && base == 10 { +- return Err(LexError); +- } +- len += 1; +- continue; +- } +- _ => break, +- }; +- if digit >= base { +- return Err(LexError); +- } +- len += 1; +- empty = false; +- } +- if empty { +- Err(LexError) +- } else { +- Ok((input.advance(len), ())) +- } +-} +- +-fn op(input: Cursor) -> PResult { +- let input = skip_whitespace(input); +- match op_char(input) { +- Ok((rest, '\'')) => { +- symbol(rest)?; +- Ok((rest, Punct::new('\'', Spacing::Joint))) +- } +- Ok((rest, ch)) => { +- let kind = match op_char(rest) { +- Ok(_) => Spacing::Joint, +- Err(LexError) => Spacing::Alone, +- }; +- Ok((rest, Punct::new(ch, kind))) +- } +- Err(LexError) => Err(LexError), +- } +-} +- +-fn op_char(input: Cursor) -> PResult { +- if input.starts_with("//") || input.starts_with("/*") { +- // Do not accept `/` of a comment as an op. +- return Err(LexError); +- } +- +- let mut chars = input.chars(); +- let first = match chars.next() { +- Some(ch) => ch, +- None => { +- return Err(LexError); +- } +- }; +- let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; +- if recognized.contains(first) { +- Ok((input.advance(first.len_utf8()), first)) +- } else { +- Err(LexError) +- } +-} +- +-fn doc_comment(input: Cursor) -> PResult> { +- let mut trees = Vec::new(); +- let (rest, ((comment, inner), span)) = spanned(input, doc_comment_contents)?; +- trees.push(TokenTree::Punct(Punct::new('#', Spacing::Alone))); +- if inner { +- trees.push(Punct::new('!', Spacing::Alone).into()); +- } +- let mut stream = vec![ +- TokenTree::Ident(crate::Ident::new("doc", span)), +- TokenTree::Punct(Punct::new('=', Spacing::Alone)), +- TokenTree::Literal(crate::Literal::string(comment)), +- ]; +- for tt in stream.iter_mut() { +- tt.set_span(span); +- } +- let group = Group::new(Delimiter::Bracket, stream.into_iter().collect()); +- trees.push(crate::Group::_new_stable(group).into()); +- for tt in trees.iter_mut() { +- tt.set_span(span); +- } +- Ok((rest, trees)) +-} +- +-named!(doc_comment_contents -> (&str, bool), alt!( +- do_parse!( +- punct!("//!") >> +- s: take_until_newline_or_eof!() >> +- ((s, true)) +- ) +- | +- do_parse!( +- option!(whitespace) >> +- peek!(tag!("/*!")) >> +- s: block_comment >> +- ((s, true)) +- ) +- | +- do_parse!( +- punct!("///") >> +- not!(tag!("/")) >> +- s: take_until_newline_or_eof!() >> +- ((s, false)) +- ) +- | +- do_parse!( +- option!(whitespace) >> +- peek!(tuple!(tag!("/**"), not!(tag!("*")))) >> +- s: block_comment >> +- ((s, false)) +- ) +-)); +diff --git a/third_party/rust/proc-macro2/src/lib.rs b/third_party/rust/proc-macro2/src/lib.rs +--- a/third_party/rust/proc-macro2/src/lib.rs ++++ b/third_party/rust/proc-macro2/src/lib.rs +@@ -73,37 +73,44 @@ + //! + //! # Thread-Safety + //! + //! Most types in this crate are `!Sync` because the underlying compiler + //! types make use of thread-local memory, meaning they cannot be accessed from + //! a different thread. + + // Proc-macro2 types in rustdoc of other crates get linked to here. +-#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.5")] ++#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.20")] + #![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))] + #![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))] ++#![allow(clippy::needless_doctest_main)] + + #[cfg(use_proc_macro)] + extern crate proc_macro; + + use std::cmp::Ordering; +-use std::fmt; ++use std::fmt::{self, Debug, Display}; + use std::hash::{Hash, Hasher}; + use std::iter::FromIterator; + use std::marker; + use std::ops::RangeBounds; + #[cfg(procmacro2_semver_exempt)] + use std::path::PathBuf; + use std::rc::Rc; + use std::str::FromStr; + +-#[macro_use] +-mod strnom; +-mod fallback; ++mod parse; ++ ++#[cfg(wrap_proc_macro)] ++mod detection; ++ ++// Public for proc_macro2::fallback::force() and unforce(), but those are quite ++// a niche use case so we omit it from rustdoc. ++#[doc(hidden)] ++pub mod fallback; + + #[cfg(not(wrap_proc_macro))] + use crate::fallback as imp; + #[path = "wrapper.rs"] + #[cfg(wrap_proc_macro)] + mod imp; + + /// An abstract stream of tokens, or more concretely a sequence of token trees. +@@ -223,32 +230,32 @@ impl FromIterator for Token + TokenStream::_new(streams.into_iter().map(|i| i.inner).collect()) + } + } + + /// Prints the token stream as a string that is supposed to be losslessly + /// convertible back into the same token stream (modulo spans), except for + /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative + /// numeric literals. +-impl fmt::Display for TokenStream { ++impl Display for TokenStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Display::fmt(&self.inner, f) + } + } + + /// Prints token in a form convenient for debugging. +-impl fmt::Debug for TokenStream { ++impl Debug for TokenStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Debug::fmt(&self.inner, f) + } + } + +-impl fmt::Debug for LexError { ++impl Debug for LexError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Debug::fmt(&self.inner, f) + } + } + + /// The source file of a given `Span`. + /// + /// This type is semver exempt and not exposed by default. + #[cfg(procmacro2_semver_exempt)] + #[derive(Clone, PartialEq, Eq)] +@@ -286,19 +293,19 @@ impl SourceFile { + /// Returns `true` if this source file is a real source file, and not + /// generated by an external macro's expansion. + pub fn is_real(&self) -> bool { + self.inner.is_real() + } + } + + #[cfg(procmacro2_semver_exempt)] +-impl fmt::Debug for SourceFile { ++impl Debug for SourceFile { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Debug::fmt(&self.inner, f) + } + } + + /// A line-column pair representing the start or end of a `Span`. + /// + /// This type is semver exempt and not exposed by default. + #[cfg(span_locations)] + #[derive(Copy, Clone, Debug, PartialEq, Eq)] +@@ -306,16 +313,32 @@ pub struct LineColumn { + /// The 1-indexed line in the source file on which the span starts or ends + /// (inclusive). + pub line: usize, + /// The 0-indexed column (in UTF-8 characters) in the source file on which + /// the span starts or ends (inclusive). + pub column: usize, + } + ++#[cfg(span_locations)] ++impl Ord for LineColumn { ++ fn cmp(&self, other: &Self) -> Ordering { ++ self.line ++ .cmp(&other.line) ++ .then(self.column.cmp(&other.column)) ++ } ++} ++ ++#[cfg(span_locations)] ++impl PartialOrd for LineColumn { ++ fn partial_cmp(&self, other: &Self) -> Option { ++ Some(self.cmp(other)) ++ } ++} ++ + /// A region of source code, along with macro expansion information. + #[derive(Copy, Clone)] + pub struct Span { + inner: imp::Span, + _marker: marker::PhantomData>, + } + + impl Span { +@@ -337,38 +360,42 @@ impl Span { + /// + /// Identifiers created with this span will be resolved as if they were + /// written directly at the macro call location (call-site hygiene) and + /// other code at the macro call site will be able to refer to them as well. + pub fn call_site() -> Span { + Span::_new(imp::Span::call_site()) + } + ++ /// The span located at the invocation of the procedural macro, but with ++ /// local variables, labels, and `$crate` resolved at the definition site ++ /// of the macro. This is the same hygiene behavior as `macro_rules`. ++ /// ++ /// This function requires Rust 1.45 or later. ++ #[cfg(hygiene)] ++ pub fn mixed_site() -> Span { ++ Span::_new(imp::Span::mixed_site()) ++ } ++ + /// A span that resolves at the macro definition site. + /// + /// This method is semver exempt and not exposed by default. + #[cfg(procmacro2_semver_exempt)] + pub fn def_site() -> Span { + Span::_new(imp::Span::def_site()) + } + + /// Creates a new span with the same line/column information as `self` but + /// that resolves symbols as though it were at `other`. +- /// +- /// This method is semver exempt and not exposed by default. +- #[cfg(procmacro2_semver_exempt)] + pub fn resolved_at(&self, other: Span) -> Span { + Span::_new(self.inner.resolved_at(other.inner)) + } + + /// Creates a new span with the same name resolution behavior as `self` but + /// with the line/column information of `other`. +- /// +- /// This method is semver exempt and not exposed by default. +- #[cfg(procmacro2_semver_exempt)] + pub fn located_at(&self, other: Span) -> Span { + Span::_new(self.inner.located_at(other.inner)) + } + + /// Convert `proc_macro2::Span` to `proc_macro::Span`. + /// + /// This method is available when building with a nightly compiler, or when + /// building with rustc 1.29+ *without* semver exempt features. +@@ -434,19 +461,19 @@ impl Span { + /// This method is semver exempt and not exposed by default. + #[cfg(procmacro2_semver_exempt)] + pub fn eq(&self, other: &Span) -> bool { + self.inner.eq(&other.inner) + } + } + + /// Prints a span in a form convenient for debugging. +-impl fmt::Debug for Span { ++impl Debug for Span { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Debug::fmt(&self.inner, f) + } + } + + /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`). + #[derive(Clone)] + pub enum TokenTree { + /// A token stream surrounded by bracket delimiters. + Group(Group), +@@ -457,35 +484,35 @@ pub enum TokenTree { + /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc. + Literal(Literal), + } + + impl TokenTree { + /// Returns the span of this tree, delegating to the `span` method of + /// the contained token or a delimited stream. + pub fn span(&self) -> Span { +- match *self { +- TokenTree::Group(ref t) => t.span(), +- TokenTree::Ident(ref t) => t.span(), +- TokenTree::Punct(ref t) => t.span(), +- TokenTree::Literal(ref t) => t.span(), ++ match self { ++ TokenTree::Group(t) => t.span(), ++ TokenTree::Ident(t) => t.span(), ++ TokenTree::Punct(t) => t.span(), ++ TokenTree::Literal(t) => t.span(), + } + } + + /// Configures the span for *only this token*. + /// + /// Note that if this token is a `Group` then this method will not configure + /// the span of each of the internal tokens, this will simply delegate to + /// the `set_span` method of each variant. + pub fn set_span(&mut self, span: Span) { +- match *self { +- TokenTree::Group(ref mut t) => t.set_span(span), +- TokenTree::Ident(ref mut t) => t.set_span(span), +- TokenTree::Punct(ref mut t) => t.set_span(span), +- TokenTree::Literal(ref mut t) => t.set_span(span), ++ match self { ++ TokenTree::Group(t) => t.set_span(span), ++ TokenTree::Ident(t) => t.set_span(span), ++ TokenTree::Punct(t) => t.set_span(span), ++ TokenTree::Literal(t) => t.set_span(span), + } + } + } + + impl From for TokenTree { + fn from(g: Group) -> TokenTree { + TokenTree::Group(g) + } +@@ -508,42 +535,42 @@ impl From for TokenTree { + TokenTree::Literal(g) + } + } + + /// Prints the token tree as a string that is supposed to be losslessly + /// convertible back into the same token tree (modulo spans), except for + /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative + /// numeric literals. +-impl fmt::Display for TokenTree { ++impl Display for TokenTree { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- match *self { +- TokenTree::Group(ref t) => t.fmt(f), +- TokenTree::Ident(ref t) => t.fmt(f), +- TokenTree::Punct(ref t) => t.fmt(f), +- TokenTree::Literal(ref t) => t.fmt(f), ++ match self { ++ TokenTree::Group(t) => Display::fmt(t, f), ++ TokenTree::Ident(t) => Display::fmt(t, f), ++ TokenTree::Punct(t) => Display::fmt(t, f), ++ TokenTree::Literal(t) => Display::fmt(t, f), + } + } + } + + /// Prints token tree in a form convenient for debugging. +-impl fmt::Debug for TokenTree { ++impl Debug for TokenTree { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Each of these has the name in the struct type in the derived debug, + // so don't bother with an extra layer of indirection +- match *self { +- TokenTree::Group(ref t) => t.fmt(f), +- TokenTree::Ident(ref t) => { ++ match self { ++ TokenTree::Group(t) => Debug::fmt(t, f), ++ TokenTree::Ident(t) => { + let mut debug = f.debug_struct("Ident"); + debug.field("sym", &format_args!("{}", t)); + imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner); + debug.finish() + } +- TokenTree::Punct(ref t) => t.fmt(f), +- TokenTree::Literal(ref t) => t.fmt(f), ++ TokenTree::Punct(t) => Debug::fmt(t, f), ++ TokenTree::Literal(t) => Debug::fmt(t, f), + } + } + } + + /// A delimited token stream. + /// + /// A `Group` internally contains a `TokenStream` which is surrounded by + /// `Delimiter`s. +@@ -646,25 +673,25 @@ impl Group { + pub fn set_span(&mut self, span: Span) { + self.inner.set_span(span.inner) + } + } + + /// Prints the group as a string that should be losslessly convertible back + /// into the same group (modulo spans), except for possibly `TokenTree::Group`s + /// with `Delimiter::None` delimiters. +-impl fmt::Display for Group { ++impl Display for Group { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +- fmt::Display::fmt(&self.inner, formatter) ++ Display::fmt(&self.inner, formatter) + } + } + +-impl fmt::Debug for Group { ++impl Debug for Group { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +- fmt::Debug::fmt(&self.inner, formatter) ++ Debug::fmt(&self.inner, formatter) + } + } + + /// An `Punct` is an single punctuation character like `+`, `-` or `#`. + /// + /// Multicharacter operators like `+=` are represented as two instances of + /// `Punct` with different forms of `Spacing` returned. + #[derive(Clone)] +@@ -725,23 +752,23 @@ impl Punct { + /// Configure the span for this punctuation character. + pub fn set_span(&mut self, span: Span) { + self.span = span; + } + } + + /// Prints the punctuation character as a string that should be losslessly + /// convertible back into the same character. +-impl fmt::Display for Punct { ++impl Display for Punct { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.op.fmt(f) ++ Display::fmt(&self.op, f) + } + } + +-impl fmt::Debug for Punct { ++impl Debug for Punct { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut debug = fmt.debug_struct("Punct"); + debug.field("op", &self.op); + debug.field("spacing", &self.spacing); + imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner); + debug.finish() + } + } +@@ -915,25 +942,25 @@ impl Ord for Ident { + impl Hash for Ident { + fn hash(&self, hasher: &mut H) { + self.to_string().hash(hasher) + } + } + + /// Prints the identifier as a string that should be losslessly convertible back + /// into the same identifier. +-impl fmt::Display for Ident { ++impl Display for Ident { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Display::fmt(&self.inner, f) + } + } + +-impl fmt::Debug for Ident { ++impl Debug for Ident { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Debug::fmt(&self.inner, f) + } + } + + /// A literal string (`"hello"`), byte string (`b"hello"`), character (`'a'`), + /// byte character (`b'a'`), an integer or floating point number with or without + /// a suffix (`1`, `1u8`, `2.3`, `2.3f32`). + /// + /// Boolean literals like `true` and `false` do not belong here, they are +@@ -1135,36 +1162,36 @@ impl Literal { + /// nightly compiler, this method will always return `None`. + /// + /// [`proc_macro::Literal::subspan`]: https://doc.rust-lang.org/proc_macro/struct.Literal.html#method.subspan + pub fn subspan>(&self, range: R) -> Option { + self.inner.subspan(range).map(Span::_new) + } + } + +-impl fmt::Debug for Literal { ++impl Debug for Literal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Debug::fmt(&self.inner, f) + } + } + +-impl fmt::Display for Literal { ++impl Display for Literal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Display::fmt(&self.inner, f) + } + } + + /// Public implementation details for the `TokenStream` type, such as iterators. + pub mod token_stream { +- use std::fmt; ++ use crate::{imp, TokenTree}; ++ use std::fmt::{self, Debug}; + use std::marker; + use std::rc::Rc; + + pub use crate::TokenStream; +- use crate::{imp, TokenTree}; + + /// An iterator over `TokenStream`'s `TokenTree`s. + /// + /// The iteration is "shallow", e.g. the iterator doesn't recurse into + /// delimited groups, and returns whole groups as token trees. + #[derive(Clone)] + pub struct IntoIter { + inner: imp::TokenTreeIter, +@@ -1174,19 +1201,19 @@ pub mod token_stream { + impl Iterator for IntoIter { + type Item = TokenTree; + + fn next(&mut self) -> Option { + self.inner.next() + } + } + +- impl fmt::Debug for IntoIter { ++ impl Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +- self.inner.fmt(f) ++ Debug::fmt(&self.inner, f) + } + } + + impl IntoIterator for TokenStream { + type Item = TokenTree; + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { +diff --git a/third_party/rust/proc-macro2/src/parse.rs b/third_party/rust/proc-macro2/src/parse.rs +new file mode 100644 +--- /dev/null ++++ b/third_party/rust/proc-macro2/src/parse.rs +@@ -0,0 +1,791 @@ ++use crate::fallback::{ ++ is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream, ++}; ++use crate::{Delimiter, Punct, Spacing, TokenTree}; ++use std::str::{Bytes, CharIndices, Chars}; ++use unicode_xid::UnicodeXID; ++ ++#[derive(Copy, Clone, Eq, PartialEq)] ++pub(crate) struct Cursor<'a> { ++ pub rest: &'a str, ++ #[cfg(span_locations)] ++ pub off: u32, ++} ++ ++impl<'a> Cursor<'a> { ++ fn advance(&self, bytes: usize) -> Cursor<'a> { ++ let (_front, rest) = self.rest.split_at(bytes); ++ Cursor { ++ rest, ++ #[cfg(span_locations)] ++ off: self.off + _front.chars().count() as u32, ++ } ++ } ++ ++ fn starts_with(&self, s: &str) -> bool { ++ self.rest.starts_with(s) ++ } ++ ++ pub(crate) fn is_empty(&self) -> bool { ++ self.rest.is_empty() ++ } ++ ++ fn len(&self) -> usize { ++ self.rest.len() ++ } ++ ++ fn as_bytes(&self) -> &'a [u8] { ++ self.rest.as_bytes() ++ } ++ ++ fn bytes(&self) -> Bytes<'a> { ++ self.rest.bytes() ++ } ++ ++ fn chars(&self) -> Chars<'a> { ++ self.rest.chars() ++ } ++ ++ fn char_indices(&self) -> CharIndices<'a> { ++ self.rest.char_indices() ++ } ++ ++ fn parse(&self, tag: &str) -> Result, LexError> { ++ if self.starts_with(tag) { ++ Ok(self.advance(tag.len())) ++ } else { ++ Err(LexError) ++ } ++ } ++} ++ ++type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>; ++ ++fn skip_whitespace(input: Cursor) -> Cursor { ++ let mut s = input; ++ ++ while !s.is_empty() { ++ let byte = s.as_bytes()[0]; ++ if byte == b'/' { ++ if s.starts_with("//") ++ && (!s.starts_with("///") || s.starts_with("////")) ++ && !s.starts_with("//!") ++ { ++ let (cursor, _) = take_until_newline_or_eof(s); ++ s = cursor; ++ continue; ++ } else if s.starts_with("/**/") { ++ s = s.advance(4); ++ continue; ++ } else if s.starts_with("/*") ++ && (!s.starts_with("/**") || s.starts_with("/***")) ++ && !s.starts_with("/*!") ++ { ++ match block_comment(s) { ++ Ok((rest, _)) => { ++ s = rest; ++ continue; ++ } ++ Err(LexError) => return s, ++ } ++ } ++ } ++ match byte { ++ b' ' | 0x09..=0x0d => { ++ s = s.advance(1); ++ continue; ++ } ++ b if b <= 0x7f => {} ++ _ => { ++ let ch = s.chars().next().unwrap(); ++ if is_whitespace(ch) { ++ s = s.advance(ch.len_utf8()); ++ continue; ++ } ++ } ++ } ++ return s; ++ } ++ s ++} ++ ++fn block_comment(input: Cursor) -> PResult<&str> { ++ if !input.starts_with("/*") { ++ return Err(LexError); ++ } ++ ++ let mut depth = 0; ++ let bytes = input.as_bytes(); ++ let mut i = 0; ++ let upper = bytes.len() - 1; ++ ++ while i < upper { ++ if bytes[i] == b'/' && bytes[i + 1] == b'*' { ++ depth += 1; ++ i += 1; // eat '*' ++ } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { ++ depth -= 1; ++ if depth == 0 { ++ return Ok((input.advance(i + 2), &input.rest[..i + 2])); ++ } ++ i += 1; // eat '/' ++ } ++ i += 1; ++ } ++ ++ Err(LexError) ++} ++ ++fn is_whitespace(ch: char) -> bool { ++ // Rust treats left-to-right mark and right-to-left mark as whitespace ++ ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' ++} ++ ++fn word_break(input: Cursor) -> Result { ++ match input.chars().next() { ++ Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError), ++ Some(_) | None => Ok(input), ++ } ++} ++ ++pub(crate) fn token_stream(mut input: Cursor) -> PResult { ++ let mut trees = Vec::new(); ++ let mut stack = Vec::new(); ++ ++ loop { ++ input = skip_whitespace(input); ++ ++ if let Ok((rest, tt)) = doc_comment(input) { ++ trees.extend(tt); ++ input = rest; ++ continue; ++ } ++ ++ #[cfg(span_locations)] ++ let lo = input.off; ++ ++ let first = match input.bytes().next() { ++ Some(first) => first, ++ None => break, ++ }; ++ ++ if let Some(open_delimiter) = match first { ++ b'(' => Some(Delimiter::Parenthesis), ++ b'[' => Some(Delimiter::Bracket), ++ b'{' => Some(Delimiter::Brace), ++ _ => None, ++ } { ++ input = input.advance(1); ++ let frame = (open_delimiter, trees); ++ #[cfg(span_locations)] ++ let frame = (lo, frame); ++ stack.push(frame); ++ trees = Vec::new(); ++ } else if let Some(close_delimiter) = match first { ++ b')' => Some(Delimiter::Parenthesis), ++ b']' => Some(Delimiter::Bracket), ++ b'}' => Some(Delimiter::Brace), ++ _ => None, ++ } { ++ input = input.advance(1); ++ let frame = stack.pop().ok_or(LexError)?; ++ #[cfg(span_locations)] ++ let (lo, frame) = frame; ++ let (open_delimiter, outer) = frame; ++ if open_delimiter != close_delimiter { ++ return Err(LexError); ++ } ++ let mut g = Group::new(open_delimiter, TokenStream { inner: trees }); ++ g.set_span(Span { ++ #[cfg(span_locations)] ++ lo, ++ #[cfg(span_locations)] ++ hi: input.off, ++ }); ++ trees = outer; ++ trees.push(TokenTree::Group(crate::Group::_new_stable(g))); ++ } else { ++ let (rest, mut tt) = leaf_token(input)?; ++ tt.set_span(crate::Span::_new_stable(Span { ++ #[cfg(span_locations)] ++ lo, ++ #[cfg(span_locations)] ++ hi: rest.off, ++ })); ++ trees.push(tt); ++ input = rest; ++ } ++ } ++ ++ if stack.is_empty() { ++ Ok((input, TokenStream { inner: trees })) ++ } else { ++ Err(LexError) ++ } ++} ++ ++fn leaf_token(input: Cursor) -> PResult { ++ if let Ok((input, l)) = literal(input) { ++ // must be parsed before ident ++ Ok((input, TokenTree::Literal(crate::Literal::_new_stable(l)))) ++ } else if let Ok((input, p)) = op(input) { ++ Ok((input, TokenTree::Punct(p))) ++ } else if let Ok((input, i)) = ident(input) { ++ Ok((input, TokenTree::Ident(i))) ++ } else { ++ Err(LexError) ++ } ++} ++ ++fn ident(input: Cursor) -> PResult { ++ let raw = input.starts_with("r#"); ++ let rest = input.advance((raw as usize) << 1); ++ ++ let (rest, sym) = ident_not_raw(rest)?; ++ ++ if !raw { ++ let ident = crate::Ident::new(sym, crate::Span::call_site()); ++ return Ok((rest, ident)); ++ } ++ ++ if sym == "_" { ++ return Err(LexError); ++ } ++ ++ let ident = crate::Ident::_new_raw(sym, crate::Span::call_site()); ++ Ok((rest, ident)) ++} ++ ++fn ident_not_raw(input: Cursor) -> PResult<&str> { ++ let mut chars = input.char_indices(); ++ ++ match chars.next() { ++ Some((_, ch)) if is_ident_start(ch) => {} ++ _ => return Err(LexError), ++ } ++ ++ let mut end = input.len(); ++ for (i, ch) in chars { ++ if !is_ident_continue(ch) { ++ end = i; ++ break; ++ } ++ } ++ ++ Ok((input.advance(end), &input.rest[..end])) ++} ++ ++fn literal(input: Cursor) -> PResult { ++ match literal_nocapture(input) { ++ Ok(a) => { ++ let end = input.len() - a.len(); ++ Ok((a, Literal::_new(input.rest[..end].to_string()))) ++ } ++ Err(LexError) => Err(LexError), ++ } ++} ++ ++fn literal_nocapture(input: Cursor) -> Result { ++ if let Ok(ok) = string(input) { ++ Ok(ok) ++ } else if let Ok(ok) = byte_string(input) { ++ Ok(ok) ++ } else if let Ok(ok) = byte(input) { ++ Ok(ok) ++ } else if let Ok(ok) = character(input) { ++ Ok(ok) ++ } else if let Ok(ok) = float(input) { ++ Ok(ok) ++ } else if let Ok(ok) = int(input) { ++ Ok(ok) ++ } else { ++ Err(LexError) ++ } ++} ++ ++fn literal_suffix(input: Cursor) -> Cursor { ++ match ident_not_raw(input) { ++ Ok((input, _)) => input, ++ Err(LexError) => input, ++ } ++} ++ ++fn string(input: Cursor) -> Result { ++ if let Ok(input) = input.parse("\"") { ++ cooked_string(input) ++ } else if let Ok(input) = input.parse("r") { ++ raw_string(input) ++ } else { ++ Err(LexError) ++ } ++} ++ ++fn cooked_string(input: Cursor) -> Result { ++ let mut chars = input.char_indices().peekable(); ++ ++ while let Some((i, ch)) = chars.next() { ++ match ch { ++ '"' => { ++ let input = input.advance(i + 1); ++ return Ok(literal_suffix(input)); ++ } ++ '\r' => { ++ if let Some((_, '\n')) = chars.next() { ++ // ... ++ } else { ++ break; ++ } ++ } ++ '\\' => match chars.next() { ++ Some((_, 'x')) => { ++ if !backslash_x_char(&mut chars) { ++ break; ++ } ++ } ++ Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\')) ++ | Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {} ++ Some((_, 'u')) => { ++ if !backslash_u(&mut chars) { ++ break; ++ } ++ } ++ Some((_, '\n')) | Some((_, '\r')) => { ++ while let Some(&(_, ch)) = chars.peek() { ++ if ch.is_whitespace() { ++ chars.next(); ++ } else { ++ break; ++ } ++ } ++ } ++ _ => break, ++ }, ++ _ch => {} ++ } ++ } ++ Err(LexError) ++} ++ ++fn byte_string(input: Cursor) -> Result { ++ if let Ok(input) = input.parse("b\"") { ++ cooked_byte_string(input) ++ } else if let Ok(input) = input.parse("br") { ++ raw_string(input) ++ } else { ++ Err(LexError) ++ } ++} ++ ++fn cooked_byte_string(mut input: Cursor) -> Result { ++ let mut bytes = input.bytes().enumerate(); ++ 'outer: while let Some((offset, b)) = bytes.next() { ++ match b { ++ b'"' => { ++ let input = input.advance(offset + 1); ++ return Ok(literal_suffix(input)); ++ } ++ b'\r' => { ++ if let Some((_, b'\n')) = bytes.next() { ++ // ... ++ } else { ++ break; ++ } ++ } ++ b'\\' => match bytes.next() { ++ Some((_, b'x')) => { ++ if !backslash_x_byte(&mut bytes) { ++ break; ++ } ++ } ++ Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\')) ++ | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {} ++ Some((newline, b'\n')) | Some((newline, b'\r')) => { ++ let rest = input.advance(newline + 1); ++ for (offset, ch) in rest.char_indices() { ++ if !ch.is_whitespace() { ++ input = rest.advance(offset); ++ bytes = input.bytes().enumerate(); ++ continue 'outer; ++ } ++ } ++ break; ++ } ++ _ => break, ++ }, ++ b if b < 0x80 => {} ++ _ => break, ++ } ++ } ++ Err(LexError) ++} ++ ++fn raw_string(input: Cursor) -> Result { ++ let mut chars = input.char_indices(); ++ let mut n = 0; ++ while let Some((i, ch)) = chars.next() { ++ match ch { ++ '"' => { ++ n = i; ++ break; ++ } ++ '#' => {} ++ _ => return Err(LexError), ++ } ++ } ++ for (i, ch) in chars { ++ match ch { ++ '"' if input.rest[i + 1..].starts_with(&input.rest[..n]) => { ++ let rest = input.advance(i + 1 + n); ++ return Ok(literal_suffix(rest)); ++ } ++ '\r' => {} ++ _ => {} ++ } ++ } ++ Err(LexError) ++} ++ ++fn byte(input: Cursor) -> Result { ++ let input = input.parse("b'")?; ++ let mut bytes = input.bytes().enumerate(); ++ let ok = match bytes.next().map(|(_, b)| b) { ++ Some(b'\\') => match bytes.next().map(|(_, b)| b) { ++ Some(b'x') => backslash_x_byte(&mut bytes), ++ Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'') ++ | Some(b'"') => true, ++ _ => false, ++ }, ++ b => b.is_some(), ++ }; ++ if !ok { ++ return Err(LexError); ++ } ++ let (offset, _) = bytes.next().ok_or(LexError)?; ++ if !input.chars().as_str().is_char_boundary(offset) { ++ return Err(LexError); ++ } ++ let input = input.advance(offset).parse("'")?; ++ Ok(literal_suffix(input)) ++} ++ ++fn character(input: Cursor) -> Result { ++ let input = input.parse("'")?; ++ let mut chars = input.char_indices(); ++ let ok = match chars.next().map(|(_, ch)| ch) { ++ Some('\\') => match chars.next().map(|(_, ch)| ch) { ++ Some('x') => backslash_x_char(&mut chars), ++ Some('u') => backslash_u(&mut chars), ++ Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => { ++ true ++ } ++ _ => false, ++ }, ++ ch => ch.is_some(), ++ }; ++ if !ok { ++ return Err(LexError); ++ } ++ let (idx, _) = chars.next().ok_or(LexError)?; ++ let input = input.advance(idx).parse("'")?; ++ Ok(literal_suffix(input)) ++} ++ ++macro_rules! next_ch { ++ ($chars:ident @ $pat:pat $(| $rest:pat)*) => { ++ match $chars.next() { ++ Some((_, ch)) => match ch { ++ $pat $(| $rest)* => ch, ++ _ => return false, ++ }, ++ None => return false, ++ } ++ }; ++} ++ ++fn backslash_x_char(chars: &mut I) -> bool ++where ++ I: Iterator, ++{ ++ next_ch!(chars @ '0'..='7'); ++ next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); ++ true ++} ++ ++fn backslash_x_byte(chars: &mut I) -> bool ++where ++ I: Iterator, ++{ ++ next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); ++ next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); ++ true ++} ++ ++fn backslash_u(chars: &mut I) -> bool ++where ++ I: Iterator, ++{ ++ next_ch!(chars @ '{'); ++ next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); ++ loop { ++ let c = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F' | '_' | '}'); ++ if c == '}' { ++ return true; ++ } ++ } ++} ++ ++fn float(input: Cursor) -> Result { ++ let mut rest = float_digits(input)?; ++ if let Some(ch) = rest.chars().next() { ++ if is_ident_start(ch) { ++ rest = ident_not_raw(rest)?.0; ++ } ++ } ++ word_break(rest) ++} ++ ++fn float_digits(input: Cursor) -> Result { ++ let mut chars = input.chars().peekable(); ++ match chars.next() { ++ Some(ch) if ch >= '0' && ch <= '9' => {} ++ _ => return Err(LexError), ++ } ++ ++ let mut len = 1; ++ let mut has_dot = false; ++ let mut has_exp = false; ++ while let Some(&ch) = chars.peek() { ++ match ch { ++ '0'..='9' | '_' => { ++ chars.next(); ++ len += 1; ++ } ++ '.' => { ++ if has_dot { ++ break; ++ } ++ chars.next(); ++ if chars ++ .peek() ++ .map(|&ch| ch == '.' || is_ident_start(ch)) ++ .unwrap_or(false) ++ { ++ return Err(LexError); ++ } ++ len += 1; ++ has_dot = true; ++ } ++ 'e' | 'E' => { ++ chars.next(); ++ len += 1; ++ has_exp = true; ++ break; ++ } ++ _ => break, ++ } ++ } ++ ++ let rest = input.advance(len); ++ if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) { ++ return Err(LexError); ++ } ++ ++ if has_exp { ++ let mut has_exp_value = false; ++ while let Some(&ch) = chars.peek() { ++ match ch { ++ '+' | '-' => { ++ if has_exp_value { ++ break; ++ } ++ chars.next(); ++ len += 1; ++ } ++ '0'..='9' => { ++ chars.next(); ++ len += 1; ++ has_exp_value = true; ++ } ++ '_' => { ++ chars.next(); ++ len += 1; ++ } ++ _ => break, ++ } ++ } ++ if !has_exp_value { ++ return Err(LexError); ++ } ++ } ++ ++ Ok(input.advance(len)) ++} ++ ++fn int(input: Cursor) -> Result { ++ let mut rest = digits(input)?; ++ if let Some(ch) = rest.chars().next() { ++ if is_ident_start(ch) { ++ rest = ident_not_raw(rest)?.0; ++ } ++ } ++ word_break(rest) ++} ++ ++fn digits(mut input: Cursor) -> Result { ++ let base = if input.starts_with("0x") { ++ input = input.advance(2); ++ 16 ++ } else if input.starts_with("0o") { ++ input = input.advance(2); ++ 8 ++ } else if input.starts_with("0b") { ++ input = input.advance(2); ++ 2 ++ } else { ++ 10 ++ }; ++ ++ let mut len = 0; ++ let mut empty = true; ++ for b in input.bytes() { ++ let digit = match b { ++ b'0'..=b'9' => (b - b'0') as u64, ++ b'a'..=b'f' => 10 + (b - b'a') as u64, ++ b'A'..=b'F' => 10 + (b - b'A') as u64, ++ b'_' => { ++ if empty && base == 10 { ++ return Err(LexError); ++ } ++ len += 1; ++ continue; ++ } ++ _ => break, ++ }; ++ if digit >= base { ++ return Err(LexError); ++ } ++ len += 1; ++ empty = false; ++ } ++ if empty { ++ Err(LexError) ++ } else { ++ Ok(input.advance(len)) ++ } ++} ++ ++fn op(input: Cursor) -> PResult { ++ match op_char(input) { ++ Ok((rest, '\'')) => { ++ ident(rest)?; ++ Ok((rest, Punct::new('\'', Spacing::Joint))) ++ } ++ Ok((rest, ch)) => { ++ let kind = match op_char(rest) { ++ Ok(_) => Spacing::Joint, ++ Err(LexError) => Spacing::Alone, ++ }; ++ Ok((rest, Punct::new(ch, kind))) ++ } ++ Err(LexError) => Err(LexError), ++ } ++} ++ ++fn op_char(input: Cursor) -> PResult { ++ if input.starts_with("//") || input.starts_with("/*") { ++ // Do not accept `/` of a comment as an op. ++ return Err(LexError); ++ } ++ ++ let mut chars = input.chars(); ++ let first = match chars.next() { ++ Some(ch) => ch, ++ None => { ++ return Err(LexError); ++ } ++ }; ++ let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; ++ if recognized.contains(first) { ++ Ok((input.advance(first.len_utf8()), first)) ++ } else { ++ Err(LexError) ++ } ++} ++ ++fn doc_comment(input: Cursor) -> PResult> { ++ #[cfg(span_locations)] ++ let lo = input.off; ++ let (rest, (comment, inner)) = doc_comment_contents(input)?; ++ let span = crate::Span::_new_stable(Span { ++ #[cfg(span_locations)] ++ lo, ++ #[cfg(span_locations)] ++ hi: rest.off, ++ }); ++ ++ let mut scan_for_bare_cr = comment; ++ while let Some(cr) = scan_for_bare_cr.find('\r') { ++ let rest = &scan_for_bare_cr[cr + 1..]; ++ if !rest.starts_with('\n') { ++ return Err(LexError); ++ } ++ scan_for_bare_cr = rest; ++ } ++ ++ let mut trees = Vec::new(); ++ trees.push(TokenTree::Punct(Punct::new('#', Spacing::Alone))); ++ if inner { ++ trees.push(Punct::new('!', Spacing::Alone).into()); ++ } ++ let mut stream = vec![ ++ TokenTree::Ident(crate::Ident::new("doc", span)), ++ TokenTree::Punct(Punct::new('=', Spacing::Alone)), ++ TokenTree::Literal(crate::Literal::string(comment)), ++ ]; ++ for tt in stream.iter_mut() { ++ tt.set_span(span); ++ } ++ let group = Group::new(Delimiter::Bracket, stream.into_iter().collect()); ++ trees.push(crate::Group::_new_stable(group).into()); ++ for tt in trees.iter_mut() { ++ tt.set_span(span); ++ } ++ Ok((rest, trees)) ++} ++ ++fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> { ++ if input.starts_with("//!") { ++ let input = input.advance(3); ++ let (input, s) = take_until_newline_or_eof(input); ++ Ok((input, (s, true))) ++ } else if input.starts_with("/*!") { ++ let (input, s) = block_comment(input)?; ++ Ok((input, (&s[3..s.len() - 2], true))) ++ } else if input.starts_with("///") { ++ let input = input.advance(3); ++ if input.starts_with("/") { ++ return Err(LexError); ++ } ++ let (input, s) = take_until_newline_or_eof(input); ++ Ok((input, (s, false))) ++ } else if input.starts_with("/**") && !input.rest[3..].starts_with('*') { ++ let (input, s) = block_comment(input)?; ++ Ok((input, (&s[3..s.len() - 2], false))) ++ } else { ++ Err(LexError) ++ } ++} ++ ++fn take_until_newline_or_eof(input: Cursor) -> (Cursor, &str) { ++ let chars = input.char_indices(); ++ ++ for (i, ch) in chars { ++ if ch == '\n' { ++ return (input.advance(i), &input.rest[..i]); ++ } else if ch == '\r' && input.rest[i + 1..].starts_with('\n') { ++ return (input.advance(i + 1), &input.rest[..i]); ++ } ++ } ++ ++ (input.advance(input.len()), input.rest) ++} +diff --git a/third_party/rust/proc-macro2/src/strnom.rs b/third_party/rust/proc-macro2/src/strnom.rs +deleted file mode 100644 +--- a/third_party/rust/proc-macro2/src/strnom.rs ++++ /dev/null +@@ -1,391 +0,0 @@ +-//! Adapted from [`nom`](https://github.com/Geal/nom). +- +-use crate::fallback::LexError; +-use std::str::{Bytes, CharIndices, Chars}; +-use unicode_xid::UnicodeXID; +- +-#[derive(Copy, Clone, Eq, PartialEq)] +-pub struct Cursor<'a> { +- pub rest: &'a str, +- #[cfg(span_locations)] +- pub off: u32, +-} +- +-impl<'a> Cursor<'a> { +- #[cfg(not(span_locations))] +- pub fn advance(&self, amt: usize) -> Cursor<'a> { +- Cursor { +- rest: &self.rest[amt..], +- } +- } +- #[cfg(span_locations)] +- pub fn advance(&self, amt: usize) -> Cursor<'a> { +- Cursor { +- rest: &self.rest[amt..], +- off: self.off + (amt as u32), +- } +- } +- +- pub fn find(&self, p: char) -> Option { +- self.rest.find(p) +- } +- +- pub fn starts_with(&self, s: &str) -> bool { +- self.rest.starts_with(s) +- } +- +- pub fn is_empty(&self) -> bool { +- self.rest.is_empty() +- } +- +- pub fn len(&self) -> usize { +- self.rest.len() +- } +- +- pub fn as_bytes(&self) -> &'a [u8] { +- self.rest.as_bytes() +- } +- +- pub fn bytes(&self) -> Bytes<'a> { +- self.rest.bytes() +- } +- +- pub fn chars(&self) -> Chars<'a> { +- self.rest.chars() +- } +- +- pub fn char_indices(&self) -> CharIndices<'a> { +- self.rest.char_indices() +- } +-} +- +-pub type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>; +- +-pub fn whitespace(input: Cursor) -> PResult<()> { +- if input.is_empty() { +- return Err(LexError); +- } +- +- let bytes = input.as_bytes(); +- let mut i = 0; +- while i < bytes.len() { +- let s = input.advance(i); +- if bytes[i] == b'/' { +- if s.starts_with("//") +- && (!s.starts_with("///") || s.starts_with("////")) +- && !s.starts_with("//!") +- { +- if let Some(len) = s.find('\n') { +- i += len + 1; +- continue; +- } +- break; +- } else if s.starts_with("/**/") { +- i += 4; +- continue; +- } else if s.starts_with("/*") +- && (!s.starts_with("/**") || s.starts_with("/***")) +- && !s.starts_with("/*!") +- { +- let (_, com) = block_comment(s)?; +- i += com.len(); +- continue; +- } +- } +- match bytes[i] { +- b' ' | 0x09..=0x0d => { +- i += 1; +- continue; +- } +- b if b <= 0x7f => {} +- _ => { +- let ch = s.chars().next().unwrap(); +- if is_whitespace(ch) { +- i += ch.len_utf8(); +- continue; +- } +- } +- } +- return if i > 0 { Ok((s, ())) } else { Err(LexError) }; +- } +- Ok((input.advance(input.len()), ())) +-} +- +-pub fn block_comment(input: Cursor) -> PResult<&str> { +- if !input.starts_with("/*") { +- return Err(LexError); +- } +- +- let mut depth = 0; +- let bytes = input.as_bytes(); +- let mut i = 0; +- let upper = bytes.len() - 1; +- while i < upper { +- if bytes[i] == b'/' && bytes[i + 1] == b'*' { +- depth += 1; +- i += 1; // eat '*' +- } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { +- depth -= 1; +- if depth == 0 { +- return Ok((input.advance(i + 2), &input.rest[..i + 2])); +- } +- i += 1; // eat '/' +- } +- i += 1; +- } +- Err(LexError) +-} +- +-pub fn skip_whitespace(input: Cursor) -> Cursor { +- match whitespace(input) { +- Ok((rest, _)) => rest, +- Err(LexError) => input, +- } +-} +- +-fn is_whitespace(ch: char) -> bool { +- // Rust treats left-to-right mark and right-to-left mark as whitespace +- ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' +-} +- +-pub fn word_break(input: Cursor) -> PResult<()> { +- match input.chars().next() { +- Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError), +- Some(_) | None => Ok((input, ())), +- } +-} +- +-macro_rules! named { +- ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => { +- fn $name<'a>(i: Cursor<'a>) -> $crate::strnom::PResult<'a, $o> { +- $submac!(i, $($args)*) +- } +- }; +-} +- +-macro_rules! alt { +- ($i:expr, $e:ident | $($rest:tt)*) => { +- alt!($i, call!($e) | $($rest)*) +- }; +- +- ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => { +- match $subrule!($i, $($args)*) { +- res @ Ok(_) => res, +- _ => alt!($i, $($rest)*) +- } +- }; +- +- ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => { +- match $subrule!($i, $($args)*) { +- Ok((i, o)) => Ok((i, $gen(o))), +- Err(LexError) => alt!($i, $($rest)*) +- } +- }; +- +- ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => { +- alt!($i, call!($e) => { $gen } | $($rest)*) +- }; +- +- ($i:expr, $e:ident => { $gen:expr }) => { +- alt!($i, call!($e) => { $gen }) +- }; +- +- ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => { +- match $subrule!($i, $($args)*) { +- Ok((i, o)) => Ok((i, $gen(o))), +- Err(LexError) => Err(LexError), +- } +- }; +- +- ($i:expr, $e:ident) => { +- alt!($i, call!($e)) +- }; +- +- ($i:expr, $subrule:ident!( $($args:tt)*)) => { +- $subrule!($i, $($args)*) +- }; +-} +- +-macro_rules! do_parse { +- ($i:expr, ( $($rest:expr),* )) => { +- Ok(($i, ( $($rest),* ))) +- }; +- +- ($i:expr, $e:ident >> $($rest:tt)*) => { +- do_parse!($i, call!($e) >> $($rest)*) +- }; +- +- ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => { +- match $submac!($i, $($args)*) { +- Err(LexError) => Err(LexError), +- Ok((i, _)) => do_parse!(i, $($rest)*), +- } +- }; +- +- ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => { +- do_parse!($i, $field: call!($e) >> $($rest)*) +- }; +- +- ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => { +- match $submac!($i, $($args)*) { +- Err(LexError) => Err(LexError), +- Ok((i, o)) => { +- let $field = o; +- do_parse!(i, $($rest)*) +- }, +- } +- }; +-} +- +-macro_rules! peek { +- ($i:expr, $submac:ident!( $($args:tt)* )) => { +- match $submac!($i, $($args)*) { +- Ok((_, o)) => Ok(($i, o)), +- Err(LexError) => Err(LexError), +- } +- }; +-} +- +-macro_rules! call { +- ($i:expr, $fun:expr $(, $args:expr)*) => { +- $fun($i $(, $args)*) +- }; +-} +- +-macro_rules! option { +- ($i:expr, $f:expr) => { +- match $f($i) { +- Ok((i, o)) => Ok((i, Some(o))), +- Err(LexError) => Ok(($i, None)), +- } +- }; +-} +- +-macro_rules! take_until_newline_or_eof { +- ($i:expr,) => {{ +- if $i.len() == 0 { +- Ok(($i, "")) +- } else { +- match $i.find('\n') { +- Some(i) => Ok(($i.advance(i), &$i.rest[..i])), +- None => Ok(($i.advance($i.len()), &$i.rest[..$i.len()])), +- } +- } +- }}; +-} +- +-macro_rules! tuple { +- ($i:expr, $($rest:tt)*) => { +- tuple_parser!($i, (), $($rest)*) +- }; +-} +- +-/// Do not use directly. Use `tuple!`. +-macro_rules! tuple_parser { +- ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => { +- tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*) +- }; +- +- ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => { +- match $submac!($i, $($args)*) { +- Err(LexError) => Err(LexError), +- Ok((i, o)) => tuple_parser!(i, (o), $($rest)*), +- } +- }; +- +- ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => { +- match $submac!($i, $($args)*) { +- Err(LexError) => Err(LexError), +- Ok((i, o)) => tuple_parser!(i, ($($parsed)* , o), $($rest)*), +- } +- }; +- +- ($i:expr, ($($parsed:tt),*), $e:ident) => { +- tuple_parser!($i, ($($parsed),*), call!($e)) +- }; +- +- ($i:expr, (), $submac:ident!( $($args:tt)* )) => { +- $submac!($i, $($args)*) +- }; +- +- ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => { +- match $submac!($i, $($args)*) { +- Err(LexError) => Err(LexError), +- Ok((i, o)) => Ok((i, ($($parsed),*, o))) +- } +- }; +- +- ($i:expr, ($($parsed:expr),*)) => { +- Ok(($i, ($($parsed),*))) +- }; +-} +- +-macro_rules! not { +- ($i:expr, $submac:ident!( $($args:tt)* )) => { +- match $submac!($i, $($args)*) { +- Ok((_, _)) => Err(LexError), +- Err(LexError) => Ok(($i, ())), +- } +- }; +-} +- +-macro_rules! tag { +- ($i:expr, $tag:expr) => { +- if $i.starts_with($tag) { +- Ok(($i.advance($tag.len()), &$i.rest[..$tag.len()])) +- } else { +- Err(LexError) +- } +- }; +-} +- +-macro_rules! punct { +- ($i:expr, $punct:expr) => { +- $crate::strnom::punct($i, $punct) +- }; +-} +- +-/// Do not use directly. Use `punct!`. +-pub fn punct<'a>(input: Cursor<'a>, token: &'static str) -> PResult<'a, &'a str> { +- let input = skip_whitespace(input); +- if input.starts_with(token) { +- Ok((input.advance(token.len()), token)) +- } else { +- Err(LexError) +- } +-} +- +-macro_rules! preceded { +- ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => { +- match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) { +- Ok((remaining, (_, o))) => Ok((remaining, o)), +- Err(LexError) => Err(LexError), +- } +- }; +- +- ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => { +- preceded!($i, $submac!($($args)*), call!($g)) +- }; +-} +- +-macro_rules! delimited { +- ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => { +- match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) { +- Err(LexError) => Err(LexError), +- Ok((i1, (_, o, _))) => Ok((i1, o)) +- } +- }; +-} +- +-macro_rules! map { +- ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => { +- match $submac!($i, $($args)*) { +- Err(LexError) => Err(LexError), +- Ok((i, o)) => Ok((i, call!(o, $g))) +- } +- }; +- +- ($i:expr, $f:expr, $g:expr) => { +- map!($i, call!($f), $g) +- }; +-} +diff --git a/third_party/rust/proc-macro2/src/wrapper.rs b/third_party/rust/proc-macro2/src/wrapper.rs +--- a/third_party/rust/proc-macro2/src/wrapper.rs ++++ b/third_party/rust/proc-macro2/src/wrapper.rs +@@ -1,96 +1,39 @@ +-use std::fmt; +-use std::iter; ++use crate::detection::inside_proc_macro; ++use crate::{fallback, Delimiter, Punct, Spacing, TokenTree}; ++use std::fmt::{self, Debug, Display}; ++use std::iter::FromIterator; + use std::ops::RangeBounds; +-use std::panic::{self, PanicInfo}; ++use std::panic; + #[cfg(super_unstable)] + use std::path::PathBuf; + use std::str::FromStr; + +-use crate::{fallback, Delimiter, Punct, Spacing, TokenTree}; +- + #[derive(Clone)] +-pub enum TokenStream { ++pub(crate) enum TokenStream { + Compiler(DeferredTokenStream), + Fallback(fallback::TokenStream), + } + + // Work around https://github.com/rust-lang/rust/issues/65080. + // In `impl Extend for TokenStream` which is used heavily by quote, + // we hold on to the appended tokens and do proc_macro::TokenStream::extend as + // late as possible to batch together consecutive uses of the Extend impl. + #[derive(Clone)] +-pub struct DeferredTokenStream { ++pub(crate) struct DeferredTokenStream { + stream: proc_macro::TokenStream, + extra: Vec, + } + +-pub enum LexError { ++pub(crate) enum LexError { + Compiler(proc_macro::LexError), + Fallback(fallback::LexError), + } + +-fn nightly_works() -> bool { +- use std::sync::atomic::*; +- use std::sync::Once; +- +- static WORKS: AtomicUsize = AtomicUsize::new(0); +- static INIT: Once = Once::new(); +- +- match WORKS.load(Ordering::SeqCst) { +- 1 => return false, +- 2 => return true, +- _ => {} +- } +- +- // Swap in a null panic hook to avoid printing "thread panicked" to stderr, +- // then use catch_unwind to determine whether the compiler's proc_macro is +- // working. When proc-macro2 is used from outside of a procedural macro all +- // of the proc_macro crate's APIs currently panic. +- // +- // The Once is to prevent the possibility of this ordering: +- // +- // thread 1 calls take_hook, gets the user's original hook +- // thread 1 calls set_hook with the null hook +- // thread 2 calls take_hook, thinks null hook is the original hook +- // thread 2 calls set_hook with the null hook +- // thread 1 calls set_hook with the actual original hook +- // thread 2 calls set_hook with what it thinks is the original hook +- // +- // in which the user's hook has been lost. +- // +- // There is still a race condition where a panic in a different thread can +- // happen during the interval that the user's original panic hook is +- // unregistered such that their hook is incorrectly not called. This is +- // sufficiently unlikely and less bad than printing panic messages to stderr +- // on correct use of this crate. Maybe there is a libstd feature request +- // here. For now, if a user needs to guarantee that this failure mode does +- // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from +- // the main thread before launching any other threads. +- INIT.call_once(|| { +- type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; +- +- let null_hook: Box = Box::new(|_panic_info| { /* ignore */ }); +- let sanity_check = &*null_hook as *const PanicHook; +- let original_hook = panic::take_hook(); +- panic::set_hook(null_hook); +- +- let works = panic::catch_unwind(|| proc_macro::Span::call_site()).is_ok(); +- WORKS.store(works as usize + 1, Ordering::SeqCst); +- +- let hopefully_null_hook = panic::take_hook(); +- panic::set_hook(original_hook); +- if sanity_check != &*hopefully_null_hook { +- panic!("observed race condition in proc_macro2::nightly_works"); +- } +- }); +- nightly_works() +-} +- + fn mismatch() -> ! { + panic!("stable/nightly mismatch") + } + + impl DeferredTokenStream { + fn new(stream: proc_macro::TokenStream) -> Self { + DeferredTokenStream { + stream, +@@ -98,28 +41,33 @@ impl DeferredTokenStream { + } + } + + fn is_empty(&self) -> bool { + self.stream.is_empty() && self.extra.is_empty() + } + + fn evaluate_now(&mut self) { +- self.stream.extend(self.extra.drain(..)); ++ // If-check provides a fast short circuit for the common case of `extra` ++ // being empty, which saves a round trip over the proc macro bridge. ++ // Improves macro expansion time in winrt by 6% in debug mode. ++ if !self.extra.is_empty() { ++ self.stream.extend(self.extra.drain(..)); ++ } + } + + fn into_token_stream(mut self) -> proc_macro::TokenStream { + self.evaluate_now(); + self.stream + } + } + + impl TokenStream { + pub fn new() -> TokenStream { +- if nightly_works() { ++ if inside_proc_macro() { + TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new())) + } else { + TokenStream::Fallback(fallback::TokenStream::new()) + } + } + + pub fn is_empty(&self) -> bool { + match self { +@@ -142,31 +90,37 @@ impl TokenStream { + } + } + } + + impl FromStr for TokenStream { + type Err = LexError; + + fn from_str(src: &str) -> Result { +- if nightly_works() { ++ if inside_proc_macro() { + Ok(TokenStream::Compiler(DeferredTokenStream::new( +- src.parse()?, ++ proc_macro_parse(src)?, + ))) + } else { + Ok(TokenStream::Fallback(src.parse()?)) + } + } + } + +-impl fmt::Display for TokenStream { ++// Work around https://github.com/rust-lang/rust/issues/58736. ++fn proc_macro_parse(src: &str) -> Result { ++ panic::catch_unwind(|| src.parse().map_err(LexError::Compiler)) ++ .unwrap_or(Err(LexError::Fallback(fallback::LexError))) ++} ++ ++impl Display for TokenStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { +- TokenStream::Compiler(tts) => tts.clone().into_token_stream().fmt(f), +- TokenStream::Fallback(tts) => tts.fmt(f), ++ TokenStream::Compiler(tts) => Display::fmt(&tts.clone().into_token_stream(), f), ++ TokenStream::Fallback(tts) => Display::fmt(tts, f), + } + } + } + + impl From for TokenStream { + fn from(inner: proc_macro::TokenStream) -> TokenStream { + TokenStream::Compiler(DeferredTokenStream::new(inner)) + } +@@ -182,17 +136,17 @@ impl From for proc_macro::T + } + + impl From for TokenStream { + fn from(inner: fallback::TokenStream) -> TokenStream { + TokenStream::Fallback(inner) + } + } + +-// Assumes nightly_works(). ++// Assumes inside_proc_macro(). + fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree { + match token { + TokenTree::Group(tt) => tt.inner.unwrap_nightly().into(), + TokenTree::Punct(tt) => { + let spacing = match tt.spacing() { + Spacing::Joint => proc_macro::Spacing::Joint, + Spacing::Alone => proc_macro::Spacing::Alone, + }; +@@ -202,37 +156,37 @@ fn into_compiler_token(token: TokenTree) + } + TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(), + TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(), + } + } + + impl From for TokenStream { + fn from(token: TokenTree) -> TokenStream { +- if nightly_works() { ++ if inside_proc_macro() { + TokenStream::Compiler(DeferredTokenStream::new(into_compiler_token(token).into())) + } else { + TokenStream::Fallback(token.into()) + } + } + } + +-impl iter::FromIterator for TokenStream { ++impl FromIterator for TokenStream { + fn from_iter>(trees: I) -> Self { +- if nightly_works() { ++ if inside_proc_macro() { + TokenStream::Compiler(DeferredTokenStream::new( + trees.into_iter().map(into_compiler_token).collect(), + )) + } else { + TokenStream::Fallback(trees.into_iter().collect()) + } + } + } + +-impl iter::FromIterator for TokenStream { ++impl FromIterator for TokenStream { + fn from_iter>(streams: I) -> Self { + let mut streams = streams.into_iter(); + match streams.next() { + Some(TokenStream::Compiler(mut first)) => { + first.evaluate_now(); + first.stream.extend(streams.map(|s| match s { + TokenStream::Compiler(s) => s.into_token_stream(), + TokenStream::Fallback(_) => mismatch(), +@@ -247,75 +201,76 @@ impl iter::FromIterator for + TokenStream::Fallback(first) + } + None => TokenStream::new(), + } + } + } + + impl Extend for TokenStream { +- fn extend>(&mut self, streams: I) { ++ fn extend>(&mut self, stream: I) { + match self { + TokenStream::Compiler(tts) => { + // Here is the reason for DeferredTokenStream. +- tts.extra +- .extend(streams.into_iter().map(into_compiler_token)); ++ for token in stream { ++ tts.extra.push(into_compiler_token(token)); ++ } + } +- TokenStream::Fallback(tts) => tts.extend(streams), ++ TokenStream::Fallback(tts) => tts.extend(stream), + } + } + } + + impl Extend for TokenStream { + fn extend>(&mut self, streams: I) { + match self { + TokenStream::Compiler(tts) => { + tts.evaluate_now(); + tts.stream +- .extend(streams.into_iter().map(|stream| stream.unwrap_nightly())); ++ .extend(streams.into_iter().map(TokenStream::unwrap_nightly)); + } + TokenStream::Fallback(tts) => { +- tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable())); ++ tts.extend(streams.into_iter().map(TokenStream::unwrap_stable)); + } + } + } + } + +-impl fmt::Debug for TokenStream { ++impl Debug for TokenStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { +- TokenStream::Compiler(tts) => tts.clone().into_token_stream().fmt(f), +- TokenStream::Fallback(tts) => tts.fmt(f), ++ TokenStream::Compiler(tts) => Debug::fmt(&tts.clone().into_token_stream(), f), ++ TokenStream::Fallback(tts) => Debug::fmt(tts, f), + } + } + } + + impl From for LexError { + fn from(e: proc_macro::LexError) -> LexError { + LexError::Compiler(e) + } + } + + impl From for LexError { + fn from(e: fallback::LexError) -> LexError { + LexError::Fallback(e) + } + } + +-impl fmt::Debug for LexError { ++impl Debug for LexError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { +- LexError::Compiler(e) => e.fmt(f), +- LexError::Fallback(e) => e.fmt(f), ++ LexError::Compiler(e) => Debug::fmt(e, f), ++ LexError::Fallback(e) => Debug::fmt(e, f), + } + } + } + + #[derive(Clone)] +-pub enum TokenTreeIter { ++pub(crate) enum TokenTreeIter { + Compiler(proc_macro::token_stream::IntoIter), + Fallback(fallback::TokenTreeIter), + } + + impl IntoIterator for TokenStream { + type Item = TokenTree; + type IntoIter = TokenTreeIter; + +@@ -356,25 +311,25 @@ impl Iterator for TokenTreeIter { + fn size_hint(&self) -> (usize, Option) { + match self { + TokenTreeIter::Compiler(tts) => tts.size_hint(), + TokenTreeIter::Fallback(tts) => tts.size_hint(), + } + } + } + +-impl fmt::Debug for TokenTreeIter { ++impl Debug for TokenTreeIter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("TokenTreeIter").finish() + } + } + + #[derive(Clone, PartialEq, Eq)] + #[cfg(super_unstable)] +-pub enum SourceFile { ++pub(crate) enum SourceFile { + Compiler(proc_macro::SourceFile), + Fallback(fallback::SourceFile), + } + + #[cfg(super_unstable)] + impl SourceFile { + fn nightly(sf: proc_macro::SourceFile) -> Self { + SourceFile::Compiler(sf) +@@ -392,68 +347,87 @@ impl SourceFile { + match self { + SourceFile::Compiler(a) => a.is_real(), + SourceFile::Fallback(a) => a.is_real(), + } + } + } + + #[cfg(super_unstable)] +-impl fmt::Debug for SourceFile { ++impl Debug for SourceFile { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { +- SourceFile::Compiler(a) => a.fmt(f), +- SourceFile::Fallback(a) => a.fmt(f), ++ SourceFile::Compiler(a) => Debug::fmt(a, f), ++ SourceFile::Fallback(a) => Debug::fmt(a, f), + } + } + } + + #[cfg(any(super_unstable, feature = "span-locations"))] +-pub struct LineColumn { ++pub(crate) struct LineColumn { + pub line: usize, + pub column: usize, + } + + #[derive(Copy, Clone)] +-pub enum Span { ++pub(crate) enum Span { + Compiler(proc_macro::Span), + Fallback(fallback::Span), + } + + impl Span { + pub fn call_site() -> Span { +- if nightly_works() { ++ if inside_proc_macro() { + Span::Compiler(proc_macro::Span::call_site()) + } else { + Span::Fallback(fallback::Span::call_site()) + } + } + ++ #[cfg(hygiene)] ++ pub fn mixed_site() -> Span { ++ if inside_proc_macro() { ++ Span::Compiler(proc_macro::Span::mixed_site()) ++ } else { ++ Span::Fallback(fallback::Span::mixed_site()) ++ } ++ } ++ + #[cfg(super_unstable)] + pub fn def_site() -> Span { +- if nightly_works() { ++ if inside_proc_macro() { + Span::Compiler(proc_macro::Span::def_site()) + } else { + Span::Fallback(fallback::Span::def_site()) + } + } + +- #[cfg(super_unstable)] + pub fn resolved_at(&self, other: Span) -> Span { + match (self, other) { ++ #[cfg(hygiene)] + (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), ++ ++ // Name resolution affects semantics, but location is only cosmetic ++ #[cfg(not(hygiene))] ++ (Span::Compiler(_), Span::Compiler(_)) => other, ++ + (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), + _ => mismatch(), + } + } + +- #[cfg(super_unstable)] + pub fn located_at(&self, other: Span) -> Span { + match (self, other) { ++ #[cfg(hygiene)] + (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), ++ ++ // Name resolution affects semantics, but location is only cosmetic ++ #[cfg(not(hygiene))] ++ (Span::Compiler(_), Span::Compiler(_)) => *self, ++ + (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), + _ => mismatch(), + } + } + + pub fn unwrap(self) -> proc_macro::Span { + match self { + Span::Compiler(s) => s, +@@ -537,36 +511,36 @@ impl From for crate::S + } + + impl From for Span { + fn from(inner: fallback::Span) -> Span { + Span::Fallback(inner) + } + } + +-impl fmt::Debug for Span { ++impl Debug for Span { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { +- Span::Compiler(s) => s.fmt(f), +- Span::Fallback(s) => s.fmt(f), ++ Span::Compiler(s) => Debug::fmt(s, f), ++ Span::Fallback(s) => Debug::fmt(s, f), + } + } + } + +-pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { ++pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { + match span { + Span::Compiler(s) => { + debug.field("span", &s); + } + Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s), + } + } + + #[derive(Clone)] +-pub enum Group { ++pub(crate) enum Group { + Compiler(proc_macro::Group), + Fallback(fallback::Group), + } + + impl Group { + pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { + match stream { + TokenStream::Compiler(tts) => { +@@ -647,36 +621,36 @@ impl Group { + } + + impl From for Group { + fn from(g: fallback::Group) -> Self { + Group::Fallback(g) + } + } + +-impl fmt::Display for Group { ++impl Display for Group { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self { +- Group::Compiler(group) => group.fmt(formatter), +- Group::Fallback(group) => group.fmt(formatter), ++ Group::Compiler(group) => Display::fmt(group, formatter), ++ Group::Fallback(group) => Display::fmt(group, formatter), + } + } + } + +-impl fmt::Debug for Group { ++impl Debug for Group { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self { +- Group::Compiler(group) => group.fmt(formatter), +- Group::Fallback(group) => group.fmt(formatter), ++ Group::Compiler(group) => Debug::fmt(group, formatter), ++ Group::Fallback(group) => Debug::fmt(group, formatter), + } + } + } + + #[derive(Clone)] +-pub enum Ident { ++pub(crate) enum Ident { + Compiler(proc_macro::Ident), + Fallback(fallback::Ident), + } + + impl Ident { + pub fn new(string: &str, span: Span) -> Ident { + match span { + Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)), +@@ -742,56 +716,56 @@ where + let other = other.as_ref(); + match self { + Ident::Compiler(t) => t.to_string() == other, + Ident::Fallback(t) => t == other, + } + } + } + +-impl fmt::Display for Ident { ++impl Display for Ident { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { +- Ident::Compiler(t) => t.fmt(f), +- Ident::Fallback(t) => t.fmt(f), ++ Ident::Compiler(t) => Display::fmt(t, f), ++ Ident::Fallback(t) => Display::fmt(t, f), + } + } + } + +-impl fmt::Debug for Ident { ++impl Debug for Ident { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { +- Ident::Compiler(t) => t.fmt(f), +- Ident::Fallback(t) => t.fmt(f), ++ Ident::Compiler(t) => Debug::fmt(t, f), ++ Ident::Fallback(t) => Debug::fmt(t, f), + } + } + } + + #[derive(Clone)] +-pub enum Literal { ++pub(crate) enum Literal { + Compiler(proc_macro::Literal), + Fallback(fallback::Literal), + } + + macro_rules! suffixed_numbers { + ($($name:ident => $kind:ident,)*) => ($( + pub fn $name(n: $kind) -> Literal { +- if nightly_works() { ++ if inside_proc_macro() { + Literal::Compiler(proc_macro::Literal::$name(n)) + } else { + Literal::Fallback(fallback::Literal::$name(n)) + } + } + )*) + } + + macro_rules! unsuffixed_integers { + ($($name:ident => $kind:ident,)*) => ($( + pub fn $name(n: $kind) -> Literal { +- if nightly_works() { ++ if inside_proc_macro() { + Literal::Compiler(proc_macro::Literal::$name(n)) + } else { + Literal::Fallback(fallback::Literal::$name(n)) + } + } + )*) + } + +@@ -825,49 +799,49 @@ impl Literal { + i16_unsuffixed => i16, + i32_unsuffixed => i32, + i64_unsuffixed => i64, + i128_unsuffixed => i128, + isize_unsuffixed => isize, + } + + pub fn f32_unsuffixed(f: f32) -> Literal { +- if nightly_works() { ++ if inside_proc_macro() { + Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f)) + } else { + Literal::Fallback(fallback::Literal::f32_unsuffixed(f)) + } + } + + pub fn f64_unsuffixed(f: f64) -> Literal { +- if nightly_works() { ++ if inside_proc_macro() { + Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f)) + } else { + Literal::Fallback(fallback::Literal::f64_unsuffixed(f)) + } + } + + pub fn string(t: &str) -> Literal { +- if nightly_works() { ++ if inside_proc_macro() { + Literal::Compiler(proc_macro::Literal::string(t)) + } else { + Literal::Fallback(fallback::Literal::string(t)) + } + } + + pub fn character(t: char) -> Literal { +- if nightly_works() { ++ if inside_proc_macro() { + Literal::Compiler(proc_macro::Literal::character(t)) + } else { + Literal::Fallback(fallback::Literal::character(t)) + } + } + + pub fn byte_string(bytes: &[u8]) -> Literal { +- if nightly_works() { ++ if inside_proc_macro() { + Literal::Compiler(proc_macro::Literal::byte_string(bytes)) + } else { + Literal::Fallback(fallback::Literal::byte_string(bytes)) + } + } + + pub fn span(&self) -> Span { + match self { +@@ -903,25 +877,25 @@ impl Literal { + } + + impl From for Literal { + fn from(s: fallback::Literal) -> Literal { + Literal::Fallback(s) + } + } + +-impl fmt::Display for Literal { ++impl Display for Literal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { +- Literal::Compiler(t) => t.fmt(f), +- Literal::Fallback(t) => t.fmt(f), ++ Literal::Compiler(t) => Display::fmt(t, f), ++ Literal::Fallback(t) => Display::fmt(t, f), + } + } + } + +-impl fmt::Debug for Literal { ++impl Debug for Literal { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { +- Literal::Compiler(t) => t.fmt(f), +- Literal::Fallback(t) => t.fmt(f), ++ Literal::Compiler(t) => Debug::fmt(t, f), ++ Literal::Fallback(t) => Debug::fmt(t, f), + } + } + } +diff --git a/third_party/rust/proc-macro2/tests/comments.rs b/third_party/rust/proc-macro2/tests/comments.rs +new file mode 100644 +--- /dev/null ++++ b/third_party/rust/proc-macro2/tests/comments.rs +@@ -0,0 +1,103 @@ ++use proc_macro2::{Delimiter, Literal, Spacing, TokenStream, TokenTree}; ++ ++// #[doc = "..."] -> "..." ++fn lit_of_outer_doc_comment(tokens: TokenStream) -> Literal { ++ lit_of_doc_comment(tokens, false) ++} ++ ++// #![doc = "..."] -> "..." ++fn lit_of_inner_doc_comment(tokens: TokenStream) -> Literal { ++ lit_of_doc_comment(tokens, true) ++} ++ ++fn lit_of_doc_comment(tokens: TokenStream, inner: bool) -> Literal { ++ let mut iter = tokens.clone().into_iter(); ++ match iter.next().unwrap() { ++ TokenTree::Punct(punct) => { ++ assert_eq!(punct.as_char(), '#'); ++ assert_eq!(punct.spacing(), Spacing::Alone); ++ } ++ _ => panic!("wrong token {:?}", tokens), ++ } ++ if inner { ++ match iter.next().unwrap() { ++ TokenTree::Punct(punct) => { ++ assert_eq!(punct.as_char(), '!'); ++ assert_eq!(punct.spacing(), Spacing::Alone); ++ } ++ _ => panic!("wrong token {:?}", tokens), ++ } ++ } ++ iter = match iter.next().unwrap() { ++ TokenTree::Group(group) => { ++ assert_eq!(group.delimiter(), Delimiter::Bracket); ++ assert!(iter.next().is_none(), "unexpected token {:?}", tokens); ++ group.stream().into_iter() ++ } ++ _ => panic!("wrong token {:?}", tokens), ++ }; ++ match iter.next().unwrap() { ++ TokenTree::Ident(ident) => assert_eq!(ident.to_string(), "doc"), ++ _ => panic!("wrong token {:?}", tokens), ++ } ++ match iter.next().unwrap() { ++ TokenTree::Punct(punct) => { ++ assert_eq!(punct.as_char(), '='); ++ assert_eq!(punct.spacing(), Spacing::Alone); ++ } ++ _ => panic!("wrong token {:?}", tokens), ++ } ++ match iter.next().unwrap() { ++ TokenTree::Literal(literal) => { ++ assert!(iter.next().is_none(), "unexpected token {:?}", tokens); ++ literal ++ } ++ _ => panic!("wrong token {:?}", tokens), ++ } ++} ++ ++#[test] ++fn closed_immediately() { ++ let stream = "/**/".parse::().unwrap(); ++ let tokens = stream.into_iter().collect::>(); ++ assert!(tokens.is_empty(), "not empty -- {:?}", tokens); ++} ++ ++#[test] ++fn incomplete() { ++ assert!("/*/".parse::().is_err()); ++} ++ ++#[test] ++fn lit() { ++ let stream = "/// doc".parse::().unwrap(); ++ let lit = lit_of_outer_doc_comment(stream); ++ assert_eq!(lit.to_string(), "\" doc\""); ++ ++ let stream = "//! doc".parse::().unwrap(); ++ let lit = lit_of_inner_doc_comment(stream); ++ assert_eq!(lit.to_string(), "\" doc\""); ++ ++ let stream = "/** doc */".parse::().unwrap(); ++ let lit = lit_of_outer_doc_comment(stream); ++ assert_eq!(lit.to_string(), "\" doc \""); ++ ++ let stream = "/*! doc */".parse::().unwrap(); ++ let lit = lit_of_inner_doc_comment(stream); ++ assert_eq!(lit.to_string(), "\" doc \""); ++} ++ ++#[test] ++fn carriage_return() { ++ let stream = "///\r\n".parse::().unwrap(); ++ let lit = lit_of_outer_doc_comment(stream); ++ assert_eq!(lit.to_string(), "\"\""); ++ ++ let stream = "/**\r\n*/".parse::().unwrap(); ++ let lit = lit_of_outer_doc_comment(stream); ++ assert_eq!(lit.to_string(), "\"\\r\\n\""); ++ ++ "///\r".parse::().unwrap_err(); ++ "///\r \n".parse::().unwrap_err(); ++ "/**\r \n*/".parse::().unwrap_err(); ++} +diff --git a/third_party/rust/proc-macro2/tests/test.rs b/third_party/rust/proc-macro2/tests/test.rs +--- a/third_party/rust/proc-macro2/tests/test.rs ++++ b/third_party/rust/proc-macro2/tests/test.rs +@@ -1,12 +1,11 @@ ++use proc_macro2::{Ident, Literal, Spacing, Span, TokenStream, TokenTree}; + use std::str::{self, FromStr}; + +-use proc_macro2::{Ident, Literal, Spacing, Span, TokenStream, TokenTree}; +- + #[test] + fn idents() { + assert_eq!( + Ident::new("String", Span::call_site()).to_string(), + "String" + ); + assert_eq!(Ident::new("fn", Span::call_site()).to_string(), "fn"); + assert_eq!(Ident::new("_", Span::call_site()).to_string(), "_"); +@@ -105,16 +104,43 @@ fn literal_suffix() { + assert_eq!(token_count("999u256"), 1); + assert_eq!(token_count("999r#u256"), 3); + assert_eq!(token_count("1."), 1); + assert_eq!(token_count("1.f32"), 3); + assert_eq!(token_count("1.0_0"), 1); + assert_eq!(token_count("1._0"), 3); + assert_eq!(token_count("1._m"), 3); + assert_eq!(token_count("\"\"s"), 1); ++ assert_eq!(token_count("r\"\"r"), 1); ++ assert_eq!(token_count("b\"\"b"), 1); ++ assert_eq!(token_count("br\"\"br"), 1); ++ assert_eq!(token_count("r#\"\"#r"), 1); ++ assert_eq!(token_count("'c'c"), 1); ++ assert_eq!(token_count("b'b'b"), 1); ++} ++ ++#[test] ++fn literal_iter_negative() { ++ let negative_literal = Literal::i32_suffixed(-3); ++ let tokens = TokenStream::from(TokenTree::Literal(negative_literal)); ++ let mut iter = tokens.into_iter(); ++ match iter.next().unwrap() { ++ TokenTree::Punct(punct) => { ++ assert_eq!(punct.as_char(), '-'); ++ assert_eq!(punct.spacing(), Spacing::Alone); ++ } ++ unexpected => panic!("unexpected token {:?}", unexpected), ++ } ++ match iter.next().unwrap() { ++ TokenTree::Literal(literal) => { ++ assert_eq!(literal.to_string(), "3i32"); ++ } ++ unexpected => panic!("unexpected token {:?}", unexpected), ++ } ++ assert!(iter.next().is_none()); + } + + #[test] + fn roundtrip() { + fn roundtrip(p: &str) { + println!("parse: {}", p); + let s = p.parse::().unwrap().to_string(); + println!("first: {}", s); +@@ -161,46 +187,16 @@ fn fail() { + fail("' static"); + fail("r#1"); + fail("r#_"); + } + + #[cfg(span_locations)] + #[test] + fn span_test() { +- use proc_macro2::TokenTree; +- +- fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) { +- let ts = p.parse::().unwrap(); +- check_spans_internal(ts, &mut lines); +- } +- +- fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) { +- for i in ts { +- if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() { +- *lines = rest; +- +- let start = i.span().start(); +- assert_eq!(start.line, sline, "sline did not match for {}", i); +- assert_eq!(start.column, scol, "scol did not match for {}", i); +- +- let end = i.span().end(); +- assert_eq!(end.line, eline, "eline did not match for {}", i); +- assert_eq!(end.column, ecol, "ecol did not match for {}", i); +- +- match i { +- TokenTree::Group(ref g) => { +- check_spans_internal(g.stream().clone(), lines); +- } +- _ => {} +- } +- } +- } +- } +- + check_spans( + "\ + /// This is a document comment + testing 123 + { + testing 234 + }", + &[ +@@ -269,59 +265,17 @@ fn span_join() { + joined1.unwrap().source_file(), + source1[0].span().source_file() + ); + } + + #[test] + fn no_panic() { + let s = str::from_utf8(b"b\'\xc2\x86 \x00\x00\x00^\"").unwrap(); +- assert!(s.parse::().is_err()); +-} +- +-#[test] +-fn tricky_doc_comment() { +- let stream = "/**/".parse::().unwrap(); +- let tokens = stream.into_iter().collect::>(); +- assert!(tokens.is_empty(), "not empty -- {:?}", tokens); +- +- let stream = "/// doc".parse::().unwrap(); +- let tokens = stream.into_iter().collect::>(); +- assert!(tokens.len() == 2, "not length 2 -- {:?}", tokens); +- match tokens[0] { +- proc_macro2::TokenTree::Punct(ref tt) => assert_eq!(tt.as_char(), '#'), +- _ => panic!("wrong token {:?}", tokens[0]), +- } +- let mut tokens = match tokens[1] { +- proc_macro2::TokenTree::Group(ref tt) => { +- assert_eq!(tt.delimiter(), proc_macro2::Delimiter::Bracket); +- tt.stream().into_iter() +- } +- _ => panic!("wrong token {:?}", tokens[0]), +- }; +- +- match tokens.next().unwrap() { +- proc_macro2::TokenTree::Ident(ref tt) => assert_eq!(tt.to_string(), "doc"), +- t => panic!("wrong token {:?}", t), +- } +- match tokens.next().unwrap() { +- proc_macro2::TokenTree::Punct(ref tt) => assert_eq!(tt.as_char(), '='), +- t => panic!("wrong token {:?}", t), +- } +- match tokens.next().unwrap() { +- proc_macro2::TokenTree::Literal(ref tt) => { +- assert_eq!(tt.to_string(), "\" doc\""); +- } +- t => panic!("wrong token {:?}", t), +- } +- assert!(tokens.next().is_none()); +- +- let stream = "//! doc".parse::().unwrap(); +- let tokens = stream.into_iter().collect::>(); +- assert!(tokens.len() == 3, "not length 3 -- {:?}", tokens); ++ assert!(s.parse::().is_err()); + } + + #[test] + fn op_before_comment() { + let mut tts = TokenStream::from_str("~// comment").unwrap().into_iter(); + match tts.next().unwrap() { + TokenTree::Punct(tt) => { + assert_eq!(tt.as_char(), '~'); +@@ -340,30 +294,30 @@ fn raw_identifier() { + } + assert!(tts.next().is_none()); + } + + #[test] + fn test_debug_ident() { + let ident = Ident::new("proc_macro", Span::call_site()); + +- #[cfg(not(procmacro2_semver_exempt))] ++ #[cfg(not(span_locations))] + let expected = "Ident(proc_macro)"; + +- #[cfg(procmacro2_semver_exempt)] +- let expected = "Ident { sym: proc_macro, span: bytes(0..0) }"; ++ #[cfg(span_locations)] ++ let expected = "Ident { sym: proc_macro }"; + + assert_eq!(expected, format!("{:?}", ident)); + } + + #[test] + fn test_debug_tokenstream() { + let tts = TokenStream::from_str("[a + 1]").unwrap(); + +- #[cfg(not(procmacro2_semver_exempt))] ++ #[cfg(not(span_locations))] + let expected = "\ + TokenStream [ + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + sym: a, + }, +@@ -374,17 +328,17 @@ TokenStream [ + Literal { + lit: 1, + }, + ], + }, + ]\ + "; + +- #[cfg(not(procmacro2_semver_exempt))] ++ #[cfg(not(span_locations))] + let expected_before_trailing_commas = "\ + TokenStream [ + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + sym: a + }, +@@ -395,17 +349,17 @@ TokenStream [ + Literal { + lit: 1 + } + ] + } + ]\ + "; + +- #[cfg(procmacro2_semver_exempt)] ++ #[cfg(span_locations)] + let expected = "\ + TokenStream [ + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + sym: a, + span: bytes(2..3), +@@ -420,17 +374,17 @@ TokenStream [ + span: bytes(6..7), + }, + ], + span: bytes(1..8), + }, + ]\ + "; + +- #[cfg(procmacro2_semver_exempt)] ++ #[cfg(span_locations)] + let expected_before_trailing_commas = "\ + TokenStream [ + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + sym: a, + span: bytes(2..3) +@@ -459,8 +413,85 @@ TokenStream [ + } + + #[test] + fn default_tokenstream_is_empty() { + let default_token_stream: TokenStream = Default::default(); + + assert!(default_token_stream.is_empty()); + } ++ ++#[test] ++fn tuple_indexing() { ++ // This behavior may change depending on https://github.com/rust-lang/rust/pull/71322 ++ let mut tokens = "tuple.0.0".parse::().unwrap().into_iter(); ++ assert_eq!("tuple", tokens.next().unwrap().to_string()); ++ assert_eq!(".", tokens.next().unwrap().to_string()); ++ assert_eq!("0.0", tokens.next().unwrap().to_string()); ++ assert!(tokens.next().is_none()); ++} ++ ++#[cfg(span_locations)] ++#[test] ++fn non_ascii_tokens() { ++ check_spans("// abc", &[]); ++ check_spans("// ábc", &[]); ++ check_spans("// abc x", &[]); ++ check_spans("// ábc x", &[]); ++ check_spans("/* abc */ x", &[(1, 10, 1, 11)]); ++ check_spans("/* ábc */ x", &[(1, 10, 1, 11)]); ++ check_spans("/* ab\nc */ x", &[(2, 5, 2, 6)]); ++ check_spans("/* áb\nc */ x", &[(2, 5, 2, 6)]); ++ check_spans("/*** abc */ x", &[(1, 12, 1, 13)]); ++ check_spans("/*** ábc */ x", &[(1, 12, 1, 13)]); ++ check_spans(r#""abc""#, &[(1, 0, 1, 5)]); ++ check_spans(r#""ábc""#, &[(1, 0, 1, 5)]); ++ check_spans(r###"r#"abc"#"###, &[(1, 0, 1, 8)]); ++ check_spans(r###"r#"ábc"#"###, &[(1, 0, 1, 8)]); ++ check_spans("r#\"a\nc\"#", &[(1, 0, 2, 3)]); ++ check_spans("r#\"á\nc\"#", &[(1, 0, 2, 3)]); ++ check_spans("'a'", &[(1, 0, 1, 3)]); ++ check_spans("'á'", &[(1, 0, 1, 3)]); ++ check_spans("//! abc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); ++ check_spans("//! ábc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); ++ check_spans("//! abc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); ++ check_spans("//! ábc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); ++ check_spans("/*! abc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]); ++ check_spans("/*! ábc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]); ++ check_spans("/*! a\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]); ++ check_spans("/*! á\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]); ++ check_spans("abc", &[(1, 0, 1, 3)]); ++ check_spans("ábc", &[(1, 0, 1, 3)]); ++ check_spans("ábć", &[(1, 0, 1, 3)]); ++ check_spans("abc// foo", &[(1, 0, 1, 3)]); ++ check_spans("ábc// foo", &[(1, 0, 1, 3)]); ++ check_spans("ábć// foo", &[(1, 0, 1, 3)]); ++ check_spans("b\"a\\\n c\"", &[(1, 0, 2, 3)]); ++ check_spans("b\"a\\\n\u{00a0}c\"", &[(1, 0, 2, 3)]); ++} ++ ++#[cfg(span_locations)] ++fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) { ++ let ts = p.parse::().unwrap(); ++ check_spans_internal(ts, &mut lines); ++ assert!(lines.is_empty(), "leftover ranges: {:?}", lines); ++} ++ ++#[cfg(span_locations)] ++fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) { ++ for i in ts { ++ if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() { ++ *lines = rest; ++ ++ let start = i.span().start(); ++ assert_eq!(start.line, sline, "sline did not match for {}", i); ++ assert_eq!(start.column, scol, "scol did not match for {}", i); ++ ++ let end = i.span().end(); ++ assert_eq!(end.line, eline, "eline did not match for {}", i); ++ assert_eq!(end.column, ecol, "ecol did not match for {}", i); ++ ++ if let TokenTree::Group(g) = i { ++ check_spans_internal(g.stream().clone(), lines); ++ } ++ } ++ } ++} +diff --git a/third_party/rust/proc-macro2/tests/test_fmt.rs b/third_party/rust/proc-macro2/tests/test_fmt.rs +new file mode 100644 +--- /dev/null ++++ b/third_party/rust/proc-macro2/tests/test_fmt.rs +@@ -0,0 +1,26 @@ ++use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; ++use std::iter::{self, FromIterator}; ++ ++#[test] ++fn test_fmt_group() { ++ let ident = Ident::new("x", Span::call_site()); ++ let inner = TokenStream::from_iter(iter::once(TokenTree::Ident(ident))); ++ let parens_empty = Group::new(Delimiter::Parenthesis, TokenStream::new()); ++ let parens_nonempty = Group::new(Delimiter::Parenthesis, inner.clone()); ++ let brackets_empty = Group::new(Delimiter::Bracket, TokenStream::new()); ++ let brackets_nonempty = Group::new(Delimiter::Bracket, inner.clone()); ++ let braces_empty = Group::new(Delimiter::Brace, TokenStream::new()); ++ let braces_nonempty = Group::new(Delimiter::Brace, inner.clone()); ++ let none_empty = Group::new(Delimiter::None, TokenStream::new()); ++ let none_nonempty = Group::new(Delimiter::None, inner.clone()); ++ ++ // Matches libproc_macro. ++ assert_eq!("()", parens_empty.to_string()); ++ assert_eq!("(x)", parens_nonempty.to_string()); ++ assert_eq!("[]", brackets_empty.to_string()); ++ assert_eq!("[x]", brackets_nonempty.to_string()); ++ assert_eq!("{ }", braces_empty.to_string()); ++ assert_eq!("{ x }", braces_nonempty.to_string()); ++ assert_eq!("", none_empty.to_string()); ++ assert_eq!("x", none_nonempty.to_string()); ++} +diff --git a/third_party/rust/syn/.cargo-checksum.json b/third_party/rust/syn/.cargo-checksum.json +--- a/third_party/rust/syn/.cargo-checksum.json ++++ b/third_party/rust/syn/.cargo-checksum.json +@@ -1,1 +1,1 @@ +-{"files":{"Cargo.toml":"484d29864d333a361652fa4e24e1dcfab9efa47705ffd8c106d802eb03b78da7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"ca605417b6db8c995458f8407afaad6c177aedcc2274004283600f5638fa1b0c","benches/file.rs":"b45211cc4a0296a77aac2b4de16dbc6b5cb66adfb5afac00a77bccea87f43968","benches/rust.rs":"9cc0f62e944f1583d05c43a395a1556731501cf5976ef67a081f4f6387f883ba","build.rs":"7423ab199728d55c7d64c44b7c6729cfd93bd8273366a77707353003e27565d7","src/attr.rs":"cf81add298f0e75c35a9980a59bc3c2fd3fe933635830d1591374eeb2487c225","src/await.rs":"18f0b2ecb319991f891e300011424985e3cf33d166ea9f29f22d575fc8c83a76","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"2a432c11a3da67a21d46c2272bf9ce60a0bb20893b5750027bbd8ca3e843ab35","src/custom_keyword.rs":"589e46ec1be9a04d6de12c0b8cadf87cc1c05606ed46ddea62e9869cbca4a191","src/custom_punctuation.rs":"2ba2e294e15a0fce7ede3686c42b2891797079a724dd1193b66e7d305624c891","src/data.rs":"cc9b250d084e444782d3ff5e63c1ba387cbde8f7f2e977eab9846d920b4b8c3f","src/derive.rs":"c18878f14be5d5ab11fd7dda2d2ff1ff75c9662daf11eed033de62e4d0670a89","src/discouraged.rs":"50e10915695c4d14f64a78e20ecbef90a2cd53a7c26ee3426a2524a8ee5c9cbf","src/error.rs":"2c17a402f83ed5ae4ad96e753216771bef620235c2ff1ccc23f4bbafc7266fe1","src/export.rs":"dcae67456278c0339acfbcbb4737b8d37cfba5a150ae789f31f4be79abf7e726","src/expr.rs":"871d8eeb43cef02ef88de3bea7477b79b4eabc096a0899dde0e5750edf482f49","src/ext.rs":"b97ed549490b9248b5b5df31b3d5b08ba8791e23e6c5d3a1157a0363eb683ff3","src/file.rs":"3cc2bf5c709238d515a557f721f231c8c725b196400de051f945b549299d38a7","src/gen/fold.rs":"10b3ae33d0ce410d6bbe8b93be9d5f9e856c7dc8212133cc46b703f97d548190","src/gen/visit.rs":"e0f5798552d186024696b7bfc7219d4ff53b0e45f735a83e77cbb6b6578c5fa4","src/gen/visit_mut.rs":"9f7dda83907969971dba84d545aaa563b0728e54db97ffab5050fdf43a79c731","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"d845d7a828863123a5187fd0fe59c9dae3636f63bad302bd035792eed3dcb1ba","src/group.rs":"119b62d8481b4b1c327639bed40e114bf1969765250b68186628247fd4144b3b","src/ident.rs":"503156ce51a7ef0420892e8dbf2ecf8fe51f42a84d52cc2c05654e1a83020cbf","src/item.rs":"213f2f58c65ee1aa222f111bc9b1be681f8fb069caed04ca56586839979318d0","src/keyword.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/lib.rs":"24778e9f15e8025e75aca114c712716ada586b471adb3b3b69278f4d39b8a21b","src/lifetime.rs":"905359708f772ec858954badde69ee016d29e6eeba1dd205b268445b1aff6f3a","src/lit.rs":"5bb0bddb94cbd256e50e92dc091a0baa09f1be40a77058b897507f3b17191e5d","src/lookahead.rs":"5cce8b4cb345a85c24a452ea6d78eadb76f01ca0a789cbf5ce35108334904173","src/mac.rs":"6b468244cc07e3f2f10419f833d9e2ed23edbcd6dc34cf21c5947633699db964","src/macros.rs":"0d8c3bab47539aa2d00bec64e92c901ea2c9c0af74c868051c0905b82650f970","src/op.rs":"93cd44770bb110deadf807a01d9a666efe644b6e3010f4b51cae77ee7438cfbb","src/parse.rs":"5017123c249ebc65866af113a0ad671814b9873f47568180e6539a305eb0317d","src/parse_macro_input.rs":"f799aadb7216c2d333b579f48ed2fedfe07b5e96f004b25b569649ffbaa958d2","src/parse_quote.rs":"81575bf60b18b0d8624d7025a5bcc8dcd6633ad70c454dee2a06e4c391700b6c","src/pat.rs":"db0f2263b9813de1f4e3e3e0396fe0080b1e11c8090c6b4fb6fca3cfbe22bc96","src/path.rs":"32e685ac7fd2d4b9989802de8f326a8d47fa710f86ec3e45fd9d3ff8fdfe97ef","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"384e7b317b26f24118eb4b0c39e949ee9f4f3e700a4c80e462342c83b2cc3282","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"adddb6acae14a0fa340df302b932c31e34b259706ce56fd82ab597ec424500e1","src/stmt.rs":"fbccf2b4da7980fe6ea8d99457d291577c0f225b370c1dd97da41abf2a18fcf7","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"761d8d1793560eb2b631c36ddfdbb14ac65178405f095453aa0e75e8816bdbb9","src/tt.rs":"1e32ae216d14d895ff621bf32bc611f138aa00108b0090be2cbaa0affebe8e2a","src/ty.rs":"ce052e0079b65b66bea4e9502d2ff2c90ad4b867904bf7eb892eb60aa3ef219a","tests/clone.sh":"961243d42540d9992090efbbd5478b7aa395671db64a6c28cdadb6edc610ebdf","tests/common/eq.rs":"a42d339808fd32dd4bfd440c254add8c56d5e2cde3a6bf0c88621b618ce5eaa7","tests/common/mod.rs":"20a3300016351fa210a193fbb0db059ef5125fa7909585ded64790004d4977ed","tests/common/parse.rs":"17ba6d1e74aaa3f8096c6d379d803221f12d95cca69927be047d6ddf8367647f","tests/debug/gen.rs":"57bd5cf585e0b86ad00f29f09ff3db3390c4a756d503514a9b28407500dcea3c","tests/debug/mod.rs":"462d6fe34ee75c3ca1207d4db2ff3bdee5b430b9f9ca632e5671d1588d3f76b3","tests/features/error.rs":"e0581a2869cbd237c2bc18a0a85272296e1577bb5f7317a67fa85e28e04eea6f","tests/features/mod.rs":"66a2605ec54ede29208da350f2bed536dfa763b58408d64d3fca3b13de64b64f","tests/macros/mod.rs":"3f2d758c0ba76b93f54b0c1fc22ad50edff8ef42629ba4d47ac7d7f823da8359","tests/repo/mod.rs":"e851a68972c9194a9a8d7b68538b16ed79ae81cba55e1a2ce210d1b759fb1a21","tests/test_asyncness.rs":"b6c46118b036e6807d24eb0e1779244b4fca23dac0d8031e9843b3edec484ce8","tests/test_attribute.rs":"2d8f18a98c989d3f7adaaeb1aeebd4f8413365ace63feecb37cb3f9db9db4d8f","tests/test_derive_input.rs":"477d80f914c54b526f8ff229788dc0e7798d118f6dcfa348f4c99755edb347b9","tests/test_expr.rs":"f35ca80566849a36e6ba6403d9663519eff37e4224360c468fedff8b561a643e","tests/test_generics.rs":"83a5dc07f5c5701c12625399262f7120b66f01a742523f3eda28da2cf2c87eb3","tests/test_grouping.rs":"aadd75215addd9e5a8fa2f9472117d4cb80f1e8b84e07f4c0845675c9014164f","tests/test_ident.rs":"236c239dd66f543f084f44ff747d7bc3962cf11a019a279777fe972f6e17aa4c","tests/test_iterators.rs":"718938da14778dcba06324d36a99d9317c9d45d81a34c6a44c47e1fa38085e9f","tests/test_lit.rs":"7dff2661a5ac586d6ed2fe27501cb8ff62f4cf3f6c91f596bff6057c67ad7857","tests/test_meta.rs":"8444dee084882243b107dfc8a6aac27f9382f9774162d1ac8ed8ec30d60c048e","tests/test_parse_buffer.rs":"b244bb4bc41ff06d21f239e60a3d663fdec5aa4af33f2a354afef36d34f0aefc","tests/test_pat.rs":"41776b878efae9b8e340f21ffe6296e921cf309f618482efd98609c33e32c28b","tests/test_precedence.rs":"71f3ea52cda8b40166bb7416fb98774e6a653542497b521f8e183e283dcf579d","tests/test_round_trip.rs":"e0de37f45fa223b488d25a41beab185eb92abb7bf765a9f13fe5d870ff31f5f1","tests/test_should_parse.rs":"4da4e25ee2baa7e75135c375042a7f958de136c5698dab03f99ff7a774dcd463","tests/test_size.rs":"970150b9d49ef91ab4c8f8c6a59b83f9a68a02acb779f0280733a5efaec6487a","tests/test_token_trees.rs":"a07ea657bf03b9c667c821b2db2af49b176ca737e3e01217a73cca78b7f11380","tests/zzz_stable.rs":"961d4940a926db4ca523d834b060c62de988e6a8e01c9f5efaa7bb4c86745b47"},"package":"66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"} +\ No newline at end of file ++{"files":{"Cargo.toml":"28ddb678a5ccac4423435384c8b7116f804e896eabc5aae9d5c2bc666aaebbb4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"03f3b53cf858536a0883aa5b5882ee61dcd0f1e71c0930c9106fcfa1d6aad2df","benches/file.rs":"b4724fc7c0f48b8f488e2632a1064f6c0bf16ded3969680fc3f4a2369536269b","benches/rust.rs":"ea6291ef2d2a83d94a3312fe179d48259f8ec0b04c961993ddd181d0a4ab740e","build.rs":"aeca2312f05aec658eaa66980a0ef3d578837db107a55702b39419ea0422eb4a","src/attr.rs":"7d79482634d6544eb4a4825405407b53660d0f5f8b929f7e1671e005b9d92038","src/await.rs":"18f0b2ecb319991f891e300011424985e3cf33d166ea9f29f22d575fc8c83a76","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"cf2a4b3bdc247b80c85ff5625a1dfb7a5f517fd835f6e1518a7b924990e4c293","src/custom_keyword.rs":"9627467063e41776315a6a14b2aaea3875592d8e0ebd2dc6df1fc2f12c06f146","src/custom_punctuation.rs":"b00e7bee96eb473507527e39db65e74e71592dc06421d2cfe45ed899c17d4847","src/data.rs":"7aec9a745cd53ec95688afa353f6efb9576e7fc0143757b51d28bc3d900b1d2a","src/derive.rs":"fa71866df6e383673dd3329f455a9f953585b83f9739050be3bf1f8c6d526b96","src/discouraged.rs":"a1f3d85e20dedf50b1b7b4571d970a3a6e9b2de4afde7dd0c986fe240df2ba46","src/error.rs":"c3005b50e3132026250c5356d0d391bf96db8087f0f5f744de98e360d8a20a3e","src/export.rs":"dcae67456278c0339acfbcbb4737b8d37cfba5a150ae789f31f4be79abf7e726","src/expr.rs":"54455fd20041996653ca5379b03cdf3c2fc1b3dd2e1149b5bc6b1dd492545d55","src/ext.rs":"870086d9021e6a6fcefa2f00cd91b55c4b74dcee8f0f6a07e76d96fb44707d61","src/file.rs":"75167ebc77e7870122078eabde1b872c337142d4b0962c20cedffcaaa2a5b7c6","src/gen/clone.rs":"0845c1bf8624c3f235cd247b4eb748e7e16b4c240097cb0ff16751f688c079ae","src/gen/debug.rs":"d24fe37f4ce1dd74f2dc54136e893782d3c4d0908323c036c97599551a56960c","src/gen/eq.rs":"1e6ef09b17ca7f36861ef23ce2a6991b231ed5f087f046469b5f23da40f5b419","src/gen/fold.rs":"3f59e59ed8ad2ab5dd347bfbe41bbc785c2aabd8ae902087a584a6daed597182","src/gen/hash.rs":"e5b2a52587173076777233a9e57e2b3c8e0dd6d6f41d16fa7c9fde68b05c2bfc","src/gen/visit.rs":"23008c170d4dd3975232876a0a654921d9b6af57372cb9fcc133ca740588d666","src/gen/visit_mut.rs":"42886c3ee02ded72d9c3eec006e20431eaee0c6b90ddefc1a36ec7bf50c6a24a","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"d1c175284ca21e777ef0414c28383929b170ccb00aaf7a929eb18d3b05e18da8","src/group.rs":"119b62d8481b4b1c327639bed40e114bf1969765250b68186628247fd4144b3b","src/ident.rs":"503156ce51a7ef0420892e8dbf2ecf8fe51f42a84d52cc2c05654e1a83020cbf","src/item.rs":"c9ad9881e8cda8ee3f157f0c7602fc53d08a7e3288b9afc388c393689eac5aea","src/lib.rs":"558ad13779233b27bebc4b2fc8025eb1c7e57b32130dc1dd911391e27b427500","src/lifetime.rs":"f390fe06692fc51fbf3eb490bb9f795da70e4452f51c5b0df3bbaa899084ddf1","src/lit.rs":"9fab84e38756b092fbb055dcdf01e31d42d916c49e3eaae8c9019043b0ee4301","src/lookahead.rs":"5cce8b4cb345a85c24a452ea6d78eadb76f01ca0a789cbf5ce35108334904173","src/mac.rs":"e5cecea397fd01a44958162781d8d94343fe2a1b9b9754a5666c3d2ab4d7ef64","src/macros.rs":"2ce05b553f14da4ee550bb681cb0733b7186ad94719cd36f96d53e15fd02cf2b","src/op.rs":"449514e146deab0ab020bc6f764544c294dbc780941c9802bf60cf1b2839d550","src/parse.rs":"bde888c98ee259f2a73489a693515ed4875432b0d79486ac83aea19f441992a3","src/parse_macro_input.rs":"653a020f023cac0eccbc1fcc34aa7bf80567b43e5475deab4ad3e487a5363201","src/parse_quote.rs":"642f21e5fa54df4b7c373fb158289ee1005d49e1a49b1d194df5438faee71c46","src/pat.rs":"1473b258162cc822f1ee0c0869f521053ed345a140c39ed83b9b4dfb6f9f2aca","src/path.rs":"f119f0c2af12fabd360eac9a2312e0f6e6c28c633c9671bde6ef0bece7c5ba3c","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"212f5a601d6c2eb8b8fa679be1167b455b595bee964d2775b0101ebb16c3eaa5","src/reserved.rs":"3625eb2a64589a4992ab79a1674e9679f465bea613ab139a671df5337e88cee6","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"7d77714d585e6f42397091ffb3a799fd7b20c05c5442c737683c429ea7d409a5","src/stmt.rs":"3917fbc897f80efe838267833c55650ff8d636cb49a6d1084e28eff65d0e3ccd","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"a1ca6298bf6592cb80cbab1db4eac2fa4e3fa56729bb807bfb0f08ab0f229ca5","src/tt.rs":"1cc9e200624288322f800f32e3d6e2e53da946467bb312dd40a52c02cdcc4730","src/ty.rs":"cb167cbb16240c59a31b44adec175172caaf75ffef9a0bb168584b51bf105795","src/verbatim.rs":"802a97df997432f18cac6e6200ff6ea29fb2474986005e0fcdbc2b65197f87f7","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/.gitignore":"22e782449a3c216db3f7215d5fb8882e316768e40beeec3833aae419ad8941db","tests/common/eq.rs":"4b190a3833bdfd20a4cb1e3dff25a698751dec71d6f30249cf09426e061a4fb1","tests/common/mod.rs":"25ef6d7daa09bad3198a0e9e91b2812425f92db7c585c1e34a03a84d7362ccd8","tests/common/parse.rs":"8b7ba32f4988c30758c108536c4877dc5a039a237bf9b0687220ef2295797bbd","tests/debug/gen.rs":"d6e2abf2a7bb58a7895a60c2f094a98a4f85c9189d02011d0dcef6ef053f26e3","tests/debug/mod.rs":"868763d0ef1609a3ad5e05e9f1bfa0f813e91e7e9a36653414a188bb2fdaa425","tests/macros/mod.rs":"c0eafa4e3845fc08f6efe6021bac37822c0ac325eb7b51194a5f35236f648d92","tests/repo/mod.rs":"9e316b88d57ae213e81950c35e45443078ec90e702798353bc3528cb8a2810b6","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"610444351e3bf99366976bbf1da109c334a70ac9500caef366bcf9b68819829f","tests/test_expr.rs":"0ee83f6f6de950018c043efcc3e85776b4227dae3068309998a8d9709f2fc66c","tests/test_generics.rs":"9d713f90a79d6145efc89fb6f946029ca03486c632219950889da39940152ba0","tests/test_grouping.rs":"46c27baec4daaaf1e891892f0b0515ea8a44619071c7d0cc9192580916f1569f","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"461ed0c8648afffcea3217f52c9a88298182b4d39d73a11803b1281d99c98c25","tests/test_iterators.rs":"53ed6078d37550bd6765d2411e3660be401aef8a31a407350cc064a7d08c7c33","tests/test_lit.rs":"2a46c5f2f2ad1dcbb7e9b0cd11b55861c5ff818c2c4c51351d07e2daa7c74674","tests/test_meta.rs":"1fc98af3279cadc3d8db3c7e8d4d7f9e9dbd4d17548cf6a2f6f4536ed65367f6","tests/test_parse_buffer.rs":"8bbe2d24ca8a3788f72c6908fc96c26d546f11c69687bf8d72727f851d5e2d27","tests/test_parse_stream.rs":"2f449a2c41a3dee6fd14bee24e1666a453cb808eda17332fd91afd127fcdd2a6","tests/test_pat.rs":"2cb331fe404496d51e7cc7e283ae13c519a2265ca82e1c88e113296f860c2cba","tests/test_path.rs":"fcd5591e639fc787acc9763d828a811c8114525c9341282eefda8f331e082a51","tests/test_precedence.rs":"8d03656741b01e577d7501ce24332d1a4febec3e31a043e47c61062b8c527ed2","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"ba01bf4ec04cd2d6f9e4800c343563925ae960c5f16752dc0797fda4451b6cc2","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"5fae772bab66809d6708232f35cfb4a287882486763b0f763feec2ad79fbb68b","tests/test_stmt.rs":"17e4355843ee2982b51faba2721a18966f8c2b9422e16b052a123b8ee8b80752","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"5b7c0bfc4963d41920dd0b39fdea419e34f00409ba86ad4211d6c3c7e8bbe1c0","tests/test_visibility.rs":"3f958e2b3b5908005e756a80eea326a91eac97cc4ab60599bebde8d4b942d65c","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"} +\ No newline at end of file +diff --git a/third_party/rust/syn/Cargo.toml b/third_party/rust/syn/Cargo.toml +--- a/third_party/rust/syn/Cargo.toml ++++ b/third_party/rust/syn/Cargo.toml +@@ -8,79 +8,90 @@ + # If you believe there's an error in this file please file an + # issue against the rust-lang/cargo repository. If you're + # editing this file be aware that the upstream Cargo.toml + # will likely look very different (and much more reasonable) + + [package] + edition = "2018" + name = "syn" +-version = "1.0.5" ++version = "1.0.40" + authors = ["David Tolnay "] + include = ["/benches/**", "/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**"] + description = "Parser for Rust source code" + documentation = "https://docs.rs/syn" + readme = "README.md" + categories = ["development-tools::procedural-macro-helpers"] + license = "MIT OR Apache-2.0" + repository = "https://github.com/dtolnay/syn" + [package.metadata.docs.rs] + all-features = true ++targets = ["x86_64-unknown-linux-gnu"] + + [package.metadata.playground] +-all-features = true +- +-[lib] +-name = "syn" ++features = ["full", "visit", "visit-mut", "fold", "extra-traits"] + + [[bench]] + name = "rust" + harness = false + required-features = ["full", "parsing"] +-edition = "2018" + + [[bench]] + name = "file" + required-features = ["full", "parsing"] +-edition = "2018" + [dependencies.proc-macro2] +-version = "1.0" ++version = "1.0.13" + default-features = false + + [dependencies.quote] + version = "1.0" + optional = true + default-features = false + + [dependencies.unicode-xid] + version = "0.2" ++[dev-dependencies.anyhow] ++version = "1.0" ++ ++[dev-dependencies.flate2] ++version = "1.0" ++ + [dev-dependencies.insta] +-version = "0.9" ++version = "0.16" + + [dev-dependencies.rayon] + version = "1.0" + + [dev-dependencies.ref-cast] +-version = "0.2" ++version = "1.0" + + [dev-dependencies.regex] + version = "1.0" + ++[dev-dependencies.reqwest] ++version = "0.10" ++features = ["blocking"] ++ ++[dev-dependencies.syn-test-suite] ++version = "0" ++ ++[dev-dependencies.tar] ++version = "0.4" ++ + [dev-dependencies.termcolor] + version = "1.0" + + [dev-dependencies.walkdir] + version = "2.1" + + [features] + clone-impls = [] + default = ["derive", "parsing", "printing", "clone-impls", "proc-macro"] + derive = [] + extra-traits = [] + fold = [] + full = [] + parsing = [] + printing = ["quote"] + proc-macro = ["proc-macro2/proc-macro", "quote/proc-macro"] ++test = ["syn-test-suite/all-features"] + visit = [] + visit-mut = [] +-[badges.travis-ci] +-repository = "dtolnay/syn" +diff --git a/third_party/rust/syn/README.md b/third_party/rust/syn/README.md +--- a/third_party/rust/syn/README.md ++++ b/third_party/rust/syn/README.md +@@ -1,15 +1,15 @@ + Parser for Rust source code + =========================== + +-[![Build Status](https://api.travis-ci.org/dtolnay/syn.svg?branch=master)](https://travis-ci.org/dtolnay/syn) +-[![Latest Version](https://img.shields.io/crates/v/syn.svg)](https://crates.io/crates/syn) +-[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/syn/1.0/syn/) +-[![Rustc Version 1.31+](https://img.shields.io/badge/rustc-1.31+-lightgray.svg)](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html) ++[github](https://github.com/dtolnay/syn) ++[crates.io](https://crates.io/crates/syn) ++[docs.rs](https://docs.rs/syn) ++[build status](https://github.com/dtolnay/syn/actions?query=branch%3Amaster) + + Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree + of Rust source code. + + Currently this library is geared toward use in Rust procedural macros, but + contains some APIs that may be useful more generally. + + - **Data structures** — Syn provides a complete syntax tree that can represent +@@ -41,20 +41,16 @@ contains some APIs that may be useful mo + + [`syn::File`]: https://docs.rs/syn/1.0/syn/struct.File.html + [`syn::Item`]: https://docs.rs/syn/1.0/syn/enum.Item.html + [`syn::Expr`]: https://docs.rs/syn/1.0/syn/enum.Expr.html + [`syn::Type`]: https://docs.rs/syn/1.0/syn/enum.Type.html + [`syn::DeriveInput`]: https://docs.rs/syn/1.0/syn/struct.DeriveInput.html + [parser functions]: https://docs.rs/syn/1.0/syn/parse/index.html + +-If you get stuck with anything involving procedural macros in Rust I am happy to +-provide help even if the issue is not related to Syn. Please file a ticket in +-this repo. +- + *Version requirement: Syn supports rustc 1.31 and up.* + + [*Release notes*](https://github.com/dtolnay/syn/releases) + +
+ + ## Resources + +@@ -83,18 +79,16 @@ tokens back to the compiler to compile i + syn = "1.0" + quote = "1.0" + + [lib] + proc-macro = true + ``` + + ```rust +-extern crate proc_macro; +- + use proc_macro::TokenStream; + use quote::quote; + use syn::{parse_macro_input, DeriveInput}; + + #[proc_macro_derive(MyMacro)] + pub fn my_macro(input: TokenStream) -> TokenStream { + // Parse the input tokens into a syntax tree + let input = parse_macro_input!(input as DeriveInput); +@@ -266,17 +260,17 @@ incompatible ecosystems for proc macros + + In general all of your code should be written against proc-macro2 rather than + proc-macro. The one exception is in the signatures of procedural macro entry + points, which are required by the language to use `proc_macro::TokenStream`. + + The proc-macro2 crate will automatically detect and use the compiler's data + structures when a procedural macro is active. + +-[proc-macro2]: https://docs.rs/proc-macro2/1.0.0/proc_macro2/ ++[proc-macro2]: https://docs.rs/proc-macro2/1.0/proc_macro2/ + +
+ + #### License + + + Licensed under either of Apache License, Version + 2.0 or MIT license at your option. +diff --git a/third_party/rust/syn/benches/file.rs b/third_party/rust/syn/benches/file.rs +--- a/third_party/rust/syn/benches/file.rs ++++ b/third_party/rust/syn/benches/file.rs +@@ -1,14 +1,21 @@ + // $ cargo bench --features full --bench file + + #![feature(rustc_private, test)] ++#![recursion_limit = "1024"] + + extern crate test; + ++#[macro_use] ++#[path = "../tests/macros/mod.rs"] ++mod macros; ++ ++#[path = "../tests/common/mod.rs"] ++mod common; + #[path = "../tests/repo/mod.rs"] + pub mod repo; + + use proc_macro2::TokenStream; + use std::fs; + use std::str::FromStr; + use test::Bencher; + +diff --git a/third_party/rust/syn/benches/rust.rs b/third_party/rust/syn/benches/rust.rs +--- a/third_party/rust/syn/benches/rust.rs ++++ b/third_party/rust/syn/benches/rust.rs +@@ -1,15 +1,22 @@ + // $ cargo bench --features full --bench rust + // + // Syn only, useful for profiling: + // $ RUSTFLAGS='--cfg syn_only' cargo build --release --features full --bench rust + + #![cfg_attr(not(syn_only), feature(rustc_private))] ++#![recursion_limit = "1024"] + ++#[macro_use] ++#[path = "../tests/macros/mod.rs"] ++mod macros; ++ ++#[path = "../tests/common/mod.rs"] ++mod common; + #[path = "../tests/repo/mod.rs"] + mod repo; + + use std::fs; + use std::time::{Duration, Instant}; + + #[cfg(not(syn_only))] + mod tokenstream_parse { +@@ -23,41 +30,45 @@ mod tokenstream_parse { + + mod syn_parse { + pub fn bench(content: &str) -> Result<(), ()> { + syn::parse_file(content).map(drop).map_err(drop) + } + } + + #[cfg(not(syn_only))] +-mod libsyntax_parse { ++mod librustc_parse { + extern crate rustc_data_structures; +- extern crate syntax; +- extern crate syntax_pos; ++ extern crate rustc_errors; ++ extern crate rustc_parse; ++ extern crate rustc_session; ++ extern crate rustc_span; + + use rustc_data_structures::sync::Lrc; +- use syntax::edition::Edition; +- use syntax::errors::{emitter::Emitter, DiagnosticBuilder, Handler}; +- use syntax::parse::ParseSess; +- use syntax::source_map::{FilePathMapping, SourceMap}; +- use syntax_pos::FileName; ++ use rustc_errors::{emitter::Emitter, Diagnostic, Handler}; ++ use rustc_session::parse::ParseSess; ++ use rustc_span::source_map::{FilePathMapping, SourceMap}; ++ use rustc_span::{edition::Edition, FileName}; + + pub fn bench(content: &str) -> Result<(), ()> { + struct SilentEmitter; + + impl Emitter for SilentEmitter { +- fn emit_diagnostic(&mut self, _db: &DiagnosticBuilder) {} ++ fn emit_diagnostic(&mut self, _diag: &Diagnostic) {} ++ fn source_map(&self) -> Option<&Lrc> { ++ None ++ } + } + +- syntax::with_globals(Edition::Edition2018, || { ++ rustc_span::with_session_globals(Edition::Edition2018, || { + let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let emitter = Box::new(SilentEmitter); + let handler = Handler::with_emitter(false, None, emitter); + let sess = ParseSess::with_span_handler(handler, cm); +- if let Err(mut diagnostic) = syntax::parse::parse_crate_from_source_str( ++ if let Err(mut diagnostic) = rustc_parse::parse_crate_from_source_str( + FileName::Custom("bench".to_owned()), + content.to_owned(), + &sess, + ) { + diagnostic.cancel(); + return Err(()); + }; + Ok(()) +@@ -99,21 +110,21 @@ fn exec(mut codepath: impl FnMut(&str) - + assert_eq!(success, total); + begin.elapsed() + } + + fn main() { + repo::clone_rust(); + + macro_rules! testcases { +- ($($(#[$cfg:meta])* $name:path,)*) => { ++ ($($(#[$cfg:meta])* $name:ident,)*) => { + vec![ + $( + $(#[$cfg])* +- (stringify!($name), $name as fn(&str) -> Result<(), ()>), ++ (stringify!($name), $name::bench as fn(&str) -> Result<(), ()>), + )* + ] + }; + } + + #[cfg(not(syn_only))] + { + let mut lines = 0; +@@ -123,22 +134,22 @@ fn main() { + files += 1; + Ok(()) + }); + eprintln!("\n{} lines in {} files", lines, files); + } + + for (name, f) in testcases!( + #[cfg(not(syn_only))] +- read_from_disk::bench, ++ read_from_disk, + #[cfg(not(syn_only))] +- tokenstream_parse::bench, +- syn_parse::bench, ++ tokenstream_parse, ++ syn_parse, + #[cfg(not(syn_only))] +- libsyntax_parse::bench, ++ librustc_parse, + ) { + eprint!("{:20}", format!("{}:", name)); + let elapsed = exec(f); + eprintln!( + "elapsed={}.{:03}s", + elapsed.as_secs(), + elapsed.subsec_millis(), + ); +diff --git a/third_party/rust/syn/build.rs b/third_party/rust/syn/build.rs +--- a/third_party/rust/syn/build.rs ++++ b/third_party/rust/syn/build.rs +@@ -1,11 +1,11 @@ + use std::env; + use std::process::Command; +-use std::str::{self, FromStr}; ++use std::str; + + // The rustc-cfg strings below are *not* public API. Please let us know by + // opening a GitHub issue if your build environment requires some way to enable + // these cfgs other than by executing our build script. + fn main() { + let compiler = match rustc_version() { + Some(compiler) => compiler, + None => return, +@@ -21,43 +21,19 @@ fn main() { + } + + struct Compiler { + minor: u32, + nightly: bool, + } + + fn rustc_version() -> Option { +- let rustc = match env::var_os("RUSTC") { +- Some(rustc) => rustc, +- None => return None, +- }; +- +- let output = match Command::new(rustc).arg("--version").output() { +- Ok(output) => output, +- Err(_) => return None, +- }; +- +- let version = match str::from_utf8(&output.stdout) { +- Ok(version) => version, +- Err(_) => return None, +- }; +- ++ let rustc = env::var_os("RUSTC")?; ++ let output = Command::new(rustc).arg("--version").output().ok()?; ++ let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } +- +- let next = match pieces.next() { +- Some(next) => next, +- None => return None, +- }; +- +- let minor = match u32::from_str(next) { +- Ok(minor) => minor, +- Err(_) => return None, +- }; +- +- Some(Compiler { +- minor: minor, +- nightly: version.contains("nightly"), +- }) ++ let minor = pieces.next()?.parse().ok()?; ++ let nightly = version.contains("nightly"); ++ Some(Compiler { minor, nightly }) + } +diff --git a/third_party/rust/syn/src/attr.rs b/third_party/rust/syn/src/attr.rs +--- a/third_party/rust/syn/src/attr.rs ++++ b/third_party/rust/syn/src/attr.rs +@@ -4,25 +4,21 @@ use crate::punctuated::Punctuated; + use std::iter; + + use proc_macro2::TokenStream; + + #[cfg(feature = "parsing")] + use crate::parse::{Parse, ParseBuffer, ParseStream, Parser, Result}; + #[cfg(feature = "parsing")] + use crate::punctuated::Pair; +-#[cfg(feature = "extra-traits")] +-use crate::tt::TokenStreamHelper; +-#[cfg(feature = "extra-traits")] +-use std::hash::{Hash, Hasher}; + + ast_struct! { + /// An attribute like `#[repr(transparent)]`. + /// +- /// *This type is available if Syn is built with the `"derive"` or `"full"` ++ /// *This type is available only if Syn is built with the `"derive"` or `"full"` + /// feature.* + /// + ///
+ /// + /// # Syntax + /// + /// Rust has six types of attributes. + /// +@@ -106,58 +102,69 @@ ast_struct! { + /// If the attribute you are parsing is expected to conform to the + /// conventional structured form of attribute, use [`parse_meta()`] to + /// obtain that structured representation. If the attribute follows some + /// other grammar of its own, use [`parse_args()`] to parse that into the + /// expected data structure. + /// + /// [`parse_meta()`]: Attribute::parse_meta + /// [`parse_args()`]: Attribute::parse_args +- pub struct Attribute #manual_extra_traits { ++ /// ++ ///


++ /// ++ /// # Doc comments ++ /// ++ /// The compiler transforms doc comments, such as `/// comment` and `/*! ++ /// comment */`, into attributes before macros are expanded. Each comment is ++ /// expanded into an attribute of the form `#[doc = r"comment"]`. ++ /// ++ /// As an example, the following `mod` items are expanded identically: ++ /// ++ /// ``` ++ /// # use syn::{ItemMod, parse_quote}; ++ /// let doc: ItemMod = parse_quote! { ++ /// /// Single line doc comments ++ /// /// We write so many! ++ /// /** ++ /// * Multi-line comments... ++ /// * May span many lines ++ /// */ ++ /// mod example { ++ /// //! Of course, they can be inner too ++ /// /*! And fit in a single line */ ++ /// } ++ /// }; ++ /// let attr: ItemMod = parse_quote! { ++ /// #[doc = r" Single line doc comments"] ++ /// #[doc = r" We write so many!"] ++ /// #[doc = r" ++ /// * Multi-line comments... ++ /// * May span many lines ++ /// "] ++ /// mod example { ++ /// #![doc = r" Of course, they can be inner too"] ++ /// #![doc = r" And fit in a single line "] ++ /// } ++ /// }; ++ /// assert_eq!(doc, attr); ++ /// ``` ++ pub struct Attribute { + pub pound_token: Token![#], + pub style: AttrStyle, + pub bracket_token: token::Bracket, + pub path: Path, + pub tokens: TokenStream, + } + } + +-#[cfg(feature = "extra-traits")] +-impl Eq for Attribute {} +- +-#[cfg(feature = "extra-traits")] +-impl PartialEq for Attribute { +- fn eq(&self, other: &Self) -> bool { +- self.style == other.style +- && self.pound_token == other.pound_token +- && self.bracket_token == other.bracket_token +- && self.path == other.path +- && TokenStreamHelper(&self.tokens) == TokenStreamHelper(&other.tokens) +- } +-} +- +-#[cfg(feature = "extra-traits")] +-impl Hash for Attribute { +- fn hash(&self, state: &mut H) +- where +- H: Hasher, +- { +- self.style.hash(state); +- self.pound_token.hash(state); +- self.bracket_token.hash(state); +- self.path.hash(state); +- TokenStreamHelper(&self.tokens).hash(state); +- } +-} +- + impl Attribute { + /// Parses the content of the attribute, consisting of the path and tokens, + /// as a [`Meta`] if possible. + /// +- /// *This function is available if Syn is built with the `"parsing"` ++ /// *This function is available only if Syn is built with the `"parsing"` + /// feature.* + #[cfg(feature = "parsing")] + pub fn parse_meta(&self) -> Result { + fn clone_ident_segment(segment: &PathSegment) -> PathSegment { + PathSegment { + ident: segment.ident.clone(), + arguments: PathArguments::None, + } +@@ -194,91 +201,95 @@ impl Attribute { + /// parser; and + /// - the error message has a more useful span when `tokens` is empty. + /// + /// ```text + /// #[my_attr(value < 5)] + /// ^^^^^^^^^ what gets parsed + /// ``` + /// +- /// *This function is available if Syn is built with the `"parsing"` ++ /// *This function is available only if Syn is built with the `"parsing"` + /// feature.* + #[cfg(feature = "parsing")] + pub fn parse_args(&self) -> Result { + self.parse_args_with(T::parse) + } + + /// Parse the arguments to the attribute using the given parser. + /// +- /// *This function is available if Syn is built with the `"parsing"` ++ /// *This function is available only if Syn is built with the `"parsing"` + /// feature.* + #[cfg(feature = "parsing")] + pub fn parse_args_with(&self, parser: F) -> Result { + let parser = |input: ParseStream| { + let args = enter_args(self, input)?; + parse::parse_stream(parser, &args) + }; + parser.parse2(self.tokens.clone()) + } + + /// Parses zero or more outer attributes from the stream. + /// +- /// *This function is available if Syn is built with the `"parsing"` ++ /// *This function is available only if Syn is built with the `"parsing"` + /// feature.* + #[cfg(feature = "parsing")] + pub fn parse_outer(input: ParseStream) -> Result> { + let mut attrs = Vec::new(); + while input.peek(Token![#]) { + attrs.push(input.call(parsing::single_parse_outer)?); + } + Ok(attrs) + } + + /// Parses zero or more inner attributes from the stream. + /// +- /// *This function is available if Syn is built with the `"parsing"` ++ /// *This function is available only if Syn is built with the `"parsing"` + /// feature.* + #[cfg(feature = "parsing")] + pub fn parse_inner(input: ParseStream) -> Result> { + let mut attrs = Vec::new(); + while input.peek(Token![#]) && input.peek2(Token![!]) { + attrs.push(input.call(parsing::single_parse_inner)?); + } + Ok(attrs) + } + } + + #[cfg(feature = "parsing")] +-fn error_expected_args(attr: &Attribute) -> Error { ++fn expected_parentheses(attr: &Attribute) -> String { + let style = match attr.style { + AttrStyle::Outer => "#", + AttrStyle::Inner(_) => "#!", + }; + + let mut path = String::new(); + for segment in &attr.path.segments { + if !path.is_empty() || attr.path.leading_colon.is_some() { + path += "::"; + } + path += &segment.ident.to_string(); + } + +- let msg = format!("expected attribute arguments: {}[{}(...)]", style, path); +- +- #[cfg(feature = "printing")] +- return Error::new_spanned(attr, msg); +- +- #[cfg(not(feature = "printing"))] +- return Error::new(attr.bracket_token.span, msg); ++ format!("{}[{}(...)]", style, path) + } + + #[cfg(feature = "parsing")] + fn enter_args<'a>(attr: &Attribute, input: ParseStream<'a>) -> Result> { + if input.is_empty() { +- return Err(error_expected_args(attr)); ++ let expected = expected_parentheses(attr); ++ let msg = format!("expected attribute arguments in parentheses: {}", expected); ++ return Err(crate::error::new2( ++ attr.pound_token.span, ++ attr.bracket_token.span, ++ msg, ++ )); ++ } else if input.peek(Token![=]) { ++ let expected = expected_parentheses(attr); ++ let msg = format!("expected parentheses: {}", expected); ++ return Err(input.error(msg)); + }; + + let content; + if input.peek(token::Paren) { + parenthesized!(content in input); + } else if input.peek(token::Bracket) { + bracketed!(content in input); + } else if input.peek(token::Brace) { +@@ -293,41 +304,40 @@ fn enter_args<'a>(attr: &Attribute, inpu + Err(input.error("unexpected token in attribute arguments")) + } + } + + ast_enum! { + /// Distinguishes between attributes that decorate an item and attributes + /// that are contained within an item. + /// +- /// *This type is available if Syn is built with the `"derive"` or `"full"` ++ /// *This type is available only if Syn is built with the `"derive"` or `"full"` + /// feature.* + /// + /// # Outer attributes + /// + /// - `#[repr(transparent)]` + /// - `/// # Example` + /// - `/** Please file an issue */` + /// + /// # Inner attributes + /// + /// - `#![feature(proc_macro)]` + /// - `//! # Example` + /// - `/*! Please file an issue */` +- #[cfg_attr(feature = "clone-impls", derive(Copy))] + pub enum AttrStyle { + Outer, + Inner(Token![!]), + } + } + + ast_enum_of_structs! { + /// Content of a compile-time structured attribute. + /// +- /// *This type is available if Syn is built with the `"derive"` or `"full"` ++ /// *This type is available only if Syn is built with the `"derive"` or `"full"` + /// feature.* + /// + /// ## Path + /// + /// A meta path is like the `test` in `#[test]`. + /// + /// ## List + /// +@@ -355,29 +365,29 @@ ast_enum_of_structs! { + /// A name-value pair within an attribute, like `feature = "nightly"`. + NameValue(MetaNameValue), + } + } + + ast_struct! { + /// A structured list within an attribute, like `derive(Copy, Clone)`. + /// +- /// *This type is available if Syn is built with the `"derive"` or ++ /// *This type is available only if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct MetaList { + pub path: Path, + pub paren_token: token::Paren, + pub nested: Punctuated, + } + } + + ast_struct! { + /// A name-value pair within an attribute, like `feature = "nightly"`. + /// +- /// *This type is available if Syn is built with the `"derive"` or ++ /// *This type is available only if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct MetaNameValue { + pub path: Path, + pub eq_token: Token![=], + pub lit: Lit, + } + } + +@@ -393,17 +403,17 @@ impl Meta { + Meta::NameValue(meta) => &meta.path, + } + } + } + + ast_enum_of_structs! { + /// Element of a compile-time attribute list. + /// +- /// *This type is available if Syn is built with the `"derive"` or `"full"` ++ /// *This type is available only if Syn is built with the `"derive"` or `"full"` + /// feature.* + pub enum NestedMeta { + /// A structured meta item, like the `Copy` in `#[derive(Copy)]` which + /// would be a nested `Meta::Path`. + Meta(Meta), + + /// A Rust literal, like the `"new_name"` in `#[rename("new_name")]`. + Lit(Lit), +@@ -424,18 +434,18 @@ ast_enum_of_structs! { + /// /* ... */ + /// } + /// ``` + /// + /// The implementation of this macro would want to parse its attribute arguments + /// as type `AttributeArgs`. + /// + /// ``` +-/// extern crate proc_macro; +-/// ++/// # extern crate proc_macro; ++/// # + /// use proc_macro::TokenStream; + /// use syn::{parse_macro_input, AttributeArgs, ItemFn}; + /// + /// # const IGNORE: &str = stringify! { + /// #[proc_macro_attribute] + /// # }; + /// pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream { + /// let args = parse_macro_input!(args as AttributeArgs); +@@ -459,27 +469,27 @@ where + T: IntoIterator, + { + type Ret = iter::Filter bool>; + + fn outer(self) -> Self::Ret { + fn is_outer(attr: &&Attribute) -> bool { + match attr.style { + AttrStyle::Outer => true, +- _ => false, ++ AttrStyle::Inner(_) => false, + } + } + self.into_iter().filter(is_outer) + } + + fn inner(self) -> Self::Ret { + fn is_inner(attr: &&Attribute) -> bool { + match attr.style { + AttrStyle::Inner(_) => true, +- _ => false, ++ AttrStyle::Outer => false, + } + } + self.into_iter().filter(is_inner) + } + } + + #[cfg(feature = "parsing")] + pub mod parsing { +diff --git a/third_party/rust/syn/src/buffer.rs b/third_party/rust/syn/src/buffer.rs +--- a/third_party/rust/syn/src/buffer.rs ++++ b/third_party/rust/syn/src/buffer.rs +@@ -1,12 +1,12 @@ + //! A stably addressed token buffer supporting efficient traversal based on a + //! cheaply copyable cursor. + //! +-//! *This module is available if Syn is built with the `"parsing"` feature.* ++//! *This module is available only if Syn is built with the `"parsing"` feature.* + + // This module is heavily commented as it contains most of the unsafe code in + // Syn, and caution should be used when editing it. The public-facing interface + // is 100% safe but the implementation is fragile internally. + + #[cfg(all( + not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))), + feature = "proc-macro" +@@ -31,17 +31,17 @@ enum Entry { + // token tree, or null if this is the outermost level. + End(*const Entry), + } + + /// A buffer that can be efficiently traversed multiple times, unlike + /// `TokenStream` which requires a deep copy in order to traverse more than + /// once. + /// +-/// *This type is available if Syn is built with the `"parsing"` feature.* ++/// *This type is available only if Syn is built with the `"parsing"` feature.* + pub struct TokenBuffer { + // NOTE: Do not derive clone on this - there are raw pointers inside which + // will be messed up. Moving the `TokenBuffer` itself is safe as the actual + // backing slices won't be moved. + data: Box<[Entry]>, + } + + impl TokenBuffer { +@@ -93,17 +93,17 @@ impl TokenBuffer { + } + + TokenBuffer { data: entries } + } + + /// Creates a `TokenBuffer` containing all the tokens from the input + /// `TokenStream`. + /// +- /// *This method is available if Syn is built with both the `"parsing"` and ++ /// *This method is available only if Syn is built with both the `"parsing"` and + /// `"proc-macro"` features.* + #[cfg(all( + not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))), + feature = "proc-macro" + ))] + pub fn new(stream: pm::TokenStream) -> TokenBuffer { + Self::new2(stream.into()) + } +@@ -128,18 +128,17 @@ impl TokenBuffer { + /// and copied around. + /// + /// An empty `Cursor` can be created directly, or one may create a `TokenBuffer` + /// object and get a cursor to its first token with `begin()`. + /// + /// Two cursors are equal if they have the same location in the same input + /// stream, and have the same scope. + /// +-/// *This type is available if Syn is built with the `"parsing"` feature.* +-#[derive(Copy, Clone, Eq, PartialEq)] ++/// *This type is available only if Syn is built with the `"parsing"` feature.* + pub struct Cursor<'a> { + // The current entry which the `Cursor` is pointing at. + ptr: *const Entry, + // This is the only `Entry::End(..)` object which this cursor is allowed to + // point at. All other `End` objects are skipped over in `Cursor::create`. + scope: *const Entry, + // Cursor is covariant in 'a. This field ensures that our pointers are still + // valid. +@@ -196,37 +195,38 @@ impl<'a> Cursor<'a> { + + /// Bump the cursor to point at the next token after the current one. This + /// is undefined behavior if the cursor is currently looking at an + /// `Entry::End`. + unsafe fn bump(self) -> Cursor<'a> { + Cursor::create(self.ptr.offset(1), self.scope) + } + +- /// If the cursor is looking at a `None`-delimited group, move it to look at +- /// the first token inside instead. If the group is empty, this will move ++ /// While the cursor is looking at a `None`-delimited group, move it to look ++ /// at the first token inside instead. If the group is empty, this will move + /// the cursor past the `None`-delimited group. + /// + /// WARNING: This mutates its argument. + fn ignore_none(&mut self) { +- if let Entry::Group(group, buf) = self.entry() { ++ while let Entry::Group(group, buf) = self.entry() { + if group.delimiter() == Delimiter::None { + // NOTE: We call `Cursor::create` here to make sure that + // situations where we should immediately exit the span after + // entering it are handled correctly. + unsafe { + *self = Cursor::create(&buf.data[0], self.scope); + } ++ } else { ++ break; + } + } + } + + /// Checks whether the cursor is currently pointing at the end of its valid + /// scope. +- #[inline] + pub fn eof(self) -> bool { + // We're at eof if we're at the end of our scope. + self.ptr == self.scope + } + + /// If the cursor is pointing at a `Group` with the given delimiter, returns + /// a cursor into that group and one pointing to the next `TokenTree`. + pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> { +@@ -337,16 +337,54 @@ impl<'a> Cursor<'a> { + match self.entry() { + Entry::Group(group, _) => group.span(), + Entry::Literal(l) => l.span(), + Entry::Ident(t) => t.span(), + Entry::Punct(o) => o.span(), + Entry::End(..) => Span::call_site(), + } + } ++ ++ /// Skip over the next token without cloning it. Returns `None` if this ++ /// cursor points to eof. ++ /// ++ /// This method treats `'lifetimes` as a single token. ++ pub(crate) fn skip(self) -> Option> { ++ match self.entry() { ++ Entry::End(..) => None, ++ ++ // Treat lifetimes as a single tt for the purposes of 'skip'. ++ Entry::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => { ++ let next = unsafe { self.bump() }; ++ match next.entry() { ++ Entry::Ident(_) => Some(unsafe { next.bump() }), ++ _ => Some(next), ++ } ++ } ++ _ => Some(unsafe { self.bump() }), ++ } ++ } ++} ++ ++impl<'a> Copy for Cursor<'a> {} ++ ++impl<'a> Clone for Cursor<'a> { ++ fn clone(&self) -> Self { ++ *self ++ } ++} ++ ++impl<'a> Eq for Cursor<'a> {} ++ ++impl<'a> PartialEq for Cursor<'a> { ++ fn eq(&self, other: &Self) -> bool { ++ let Cursor { ptr, scope, marker } = self; ++ let _ = marker; ++ *ptr == other.ptr && *scope == other.scope ++ } + } + + pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool { + a.scope == b.scope + } + + pub(crate) fn open_span_of_group(cursor: Cursor) -> Span { + match cursor.entry() { +diff --git a/third_party/rust/syn/src/custom_keyword.rs b/third_party/rust/syn/src/custom_keyword.rs +--- a/third_party/rust/syn/src/custom_keyword.rs ++++ b/third_party/rust/syn/src/custom_keyword.rs +@@ -81,46 +81,46 @@ + /// value: input.parse()?, + /// }) + /// } else { + /// Err(lookahead.error()) + /// } + /// } + /// } + /// ``` +-#[macro_export(local_inner_macros)] ++#[macro_export] + macro_rules! custom_keyword { + ($ident:ident) => { + #[allow(non_camel_case_types)] + pub struct $ident { + pub span: $crate::export::Span, + } + + #[doc(hidden)] +- #[allow(non_snake_case)] ++ #[allow(dead_code, non_snake_case)] + pub fn $ident<__S: $crate::export::IntoSpans<[$crate::export::Span; 1]>>( + span: __S, + ) -> $ident { + $ident { + span: $crate::export::IntoSpans::into_spans(span)[0], + } + } + + impl $crate::export::Default for $ident { + fn default() -> Self { + $ident { + span: $crate::export::Span::call_site(), + } + } + } + +- impl_parse_for_custom_keyword!($ident); +- impl_to_tokens_for_custom_keyword!($ident); +- impl_clone_for_custom_keyword!($ident); +- impl_extra_traits_for_custom_keyword!($ident); ++ $crate::impl_parse_for_custom_keyword!($ident); ++ $crate::impl_to_tokens_for_custom_keyword!($ident); ++ $crate::impl_clone_for_custom_keyword!($ident); ++ $crate::impl_extra_traits_for_custom_keyword!($ident); + }; + } + + // Not public API. + #[cfg(feature = "parsing")] + #[doc(hidden)] + #[macro_export] + macro_rules! impl_parse_for_custom_keyword { +diff --git a/third_party/rust/syn/src/custom_punctuation.rs b/third_party/rust/syn/src/custom_punctuation.rs +--- a/third_party/rust/syn/src/custom_punctuation.rs ++++ b/third_party/rust/syn/src/custom_punctuation.rs +@@ -69,67 +69,67 @@ + /// Ok(tokens) + /// } + /// + /// fn main() { + /// let input = r#" a::b c::d::e "#; + /// let _: PathSegments = syn::parse_str(input).unwrap(); + /// } + /// ``` +-#[macro_export(local_inner_macros)] ++#[macro_export] + macro_rules! custom_punctuation { + ($ident:ident, $($tt:tt)+) => { + pub struct $ident { +- pub spans: custom_punctuation_repr!($($tt)+), ++ pub spans: $crate::custom_punctuation_repr!($($tt)+), + } + + #[doc(hidden)] +- #[allow(non_snake_case)] +- pub fn $ident<__S: $crate::export::IntoSpans>( ++ #[allow(dead_code, non_snake_case)] ++ pub fn $ident<__S: $crate::export::IntoSpans<$crate::custom_punctuation_repr!($($tt)+)>>( + spans: __S, + ) -> $ident { +- let _validate_len = 0 $(+ custom_punctuation_len!(strict, $tt))*; ++ let _validate_len = 0 $(+ $crate::custom_punctuation_len!(strict, $tt))*; + $ident { + spans: $crate::export::IntoSpans::into_spans(spans) + } + } + + impl $crate::export::Default for $ident { + fn default() -> Self { + $ident($crate::export::Span::call_site()) + } + } + +- impl_parse_for_custom_punctuation!($ident, $($tt)+); +- impl_to_tokens_for_custom_punctuation!($ident, $($tt)+); +- impl_clone_for_custom_punctuation!($ident, $($tt)+); +- impl_extra_traits_for_custom_punctuation!($ident, $($tt)+); ++ $crate::impl_parse_for_custom_punctuation!($ident, $($tt)+); ++ $crate::impl_to_tokens_for_custom_punctuation!($ident, $($tt)+); ++ $crate::impl_clone_for_custom_punctuation!($ident, $($tt)+); ++ $crate::impl_extra_traits_for_custom_punctuation!($ident, $($tt)+); + }; + } + + // Not public API. + #[cfg(feature = "parsing")] + #[doc(hidden)] +-#[macro_export(local_inner_macros)] ++#[macro_export] + macro_rules! impl_parse_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => { + impl $crate::token::CustomToken for $ident { + fn peek(cursor: $crate::buffer::Cursor) -> bool { +- $crate::token::parsing::peek_punct(cursor, stringify_punct!($($tt)+)) ++ $crate::token::parsing::peek_punct(cursor, $crate::stringify_punct!($($tt)+)) + } + + fn display() -> &'static $crate::export::str { +- custom_punctuation_concat!("`", stringify_punct!($($tt)+), "`") ++ concat!("`", $crate::stringify_punct!($($tt)+), "`") + } + } + + impl $crate::parse::Parse for $ident { + fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> { +- let spans: custom_punctuation_repr!($($tt)+) = +- $crate::token::parsing::punct(input, stringify_punct!($($tt)+))?; ++ let spans: $crate::custom_punctuation_repr!($($tt)+) = ++ $crate::token::parsing::punct(input, $crate::stringify_punct!($($tt)+))?; + Ok($ident(spans)) + } + } + }; + } + + // Not public API. + #[cfg(not(feature = "parsing"))] +@@ -137,22 +137,22 @@ macro_rules! impl_parse_for_custom_punct + #[macro_export] + macro_rules! impl_parse_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => {}; + } + + // Not public API. + #[cfg(feature = "printing")] + #[doc(hidden)] +-#[macro_export(local_inner_macros)] ++#[macro_export] + macro_rules! impl_to_tokens_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => { + impl $crate::export::ToTokens for $ident { + fn to_tokens(&self, tokens: &mut $crate::export::TokenStream2) { +- $crate::token::printing::punct(stringify_punct!($($tt)+), &self.spans, tokens) ++ $crate::token::printing::punct($crate::stringify_punct!($($tt)+), &self.spans, tokens) + } + } + }; + } + + // Not public API. + #[cfg(not(feature = "printing"))] + #[doc(hidden)] +@@ -216,26 +216,26 @@ macro_rules! impl_extra_traits_for_custo + #[doc(hidden)] + #[macro_export] + macro_rules! impl_extra_traits_for_custom_punctuation { + ($ident:ident, $($tt:tt)+) => {}; + } + + // Not public API. + #[doc(hidden)] +-#[macro_export(local_inner_macros)] ++#[macro_export] + macro_rules! custom_punctuation_repr { + ($($tt:tt)+) => { +- [$crate::export::Span; 0 $(+ custom_punctuation_len!(lenient, $tt))+] ++ [$crate::export::Span; 0 $(+ $crate::custom_punctuation_len!(lenient, $tt))+] + }; + } + + // Not public API. + #[doc(hidden)] +-#[macro_export(local_inner_macros)] ++#[macro_export] + #[rustfmt::skip] + macro_rules! custom_punctuation_len { + ($mode:ident, +) => { 1 }; + ($mode:ident, +=) => { 2 }; + ($mode:ident, &) => { 1 }; + ($mode:ident, &&) => { 2 }; + ($mode:ident, &=) => { 2 }; + ($mode:ident, @) => { 1 }; +@@ -274,17 +274,17 @@ macro_rules! custom_punctuation_len { + ($mode:ident, <<=) => { 3 }; + ($mode:ident, >>) => { 2 }; + ($mode:ident, >>=) => { 3 }; + ($mode:ident, *) => { 1 }; + ($mode:ident, -) => { 1 }; + ($mode:ident, -=) => { 2 }; + ($mode:ident, ~) => { 1 }; + (lenient, $tt:tt) => { 0 }; +- (strict, $tt:tt) => {{ custom_punctuation_unexpected!($tt); 0 }}; ++ (strict, $tt:tt) => {{ $crate::custom_punctuation_unexpected!($tt); 0 }}; + } + + // Not public API. + #[doc(hidden)] + #[macro_export] + macro_rules! custom_punctuation_unexpected { + () => {}; + } +@@ -292,18 +292,8 @@ macro_rules! custom_punctuation_unexpect + // Not public API. + #[doc(hidden)] + #[macro_export] + macro_rules! stringify_punct { + ($($tt:tt)+) => { + concat!($(stringify!($tt)),+) + }; + } +- +-// Not public API. +-// Without this, local_inner_macros breaks when looking for concat! +-#[doc(hidden)] +-#[macro_export] +-macro_rules! custom_punctuation_concat { +- ($($tt:tt)*) => { +- concat!($($tt)*) +- }; +-} +diff --git a/third_party/rust/syn/src/data.rs b/third_party/rust/syn/src/data.rs +--- a/third_party/rust/syn/src/data.rs ++++ b/third_party/rust/syn/src/data.rs +@@ -1,15 +1,15 @@ + use super::*; + use crate::punctuated::Punctuated; + + ast_struct! { + /// An enum variant. + /// +- /// *This type is available if Syn is built with the `"derive"` or `"full"` ++ /// *This type is available only if Syn is built with the `"derive"` or `"full"` + /// feature.* + pub struct Variant { + /// Attributes tagged on the variant. + pub attrs: Vec, + + /// Name of the variant. + pub ident: Ident, + +@@ -19,17 +19,17 @@ ast_struct! { + /// Explicit discriminant: `Variant = 1` + pub discriminant: Option<(Token![=], Expr)>, + } + } + + ast_enum_of_structs! { + /// Data stored within an enum variant or struct. + /// +- /// *This type is available if Syn is built with the `"derive"` or `"full"` ++ /// *This type is available only if Syn is built with the `"derive"` or `"full"` + /// feature.* + /// + /// # Syntax tree enum + /// + /// This type is a [syntax tree enum]. + /// + /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums + // +@@ -47,28 +47,28 @@ ast_enum_of_structs! { + Unit, + } + } + + ast_struct! { + /// Named fields of a struct or struct variant such as `Point { x: f64, + /// y: f64 }`. + /// +- /// *This type is available if Syn is built with the `"derive"` or ++ /// *This type is available only if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct FieldsNamed { + pub brace_token: token::Brace, + pub named: Punctuated, + } + } + + ast_struct! { + /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`. + /// +- /// *This type is available if Syn is built with the `"derive"` or ++ /// *This type is available only if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct FieldsUnnamed { + pub paren_token: token::Paren, + pub unnamed: Punctuated, + } + } + + impl Fields { +@@ -88,16 +88,34 @@ impl Fields { + /// struct or variant's fields uniformly. + pub fn iter_mut(&mut self) -> punctuated::IterMut { + match self { + Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(), + Fields::Named(f) => f.named.iter_mut(), + Fields::Unnamed(f) => f.unnamed.iter_mut(), + } + } ++ ++ /// Returns the number of fields. ++ pub fn len(&self) -> usize { ++ match self { ++ Fields::Unit => 0, ++ Fields::Named(f) => f.named.len(), ++ Fields::Unnamed(f) => f.unnamed.len(), ++ } ++ } ++ ++ /// Returns `true` if there are zero fields. ++ pub fn is_empty(&self) -> bool { ++ match self { ++ Fields::Unit => true, ++ Fields::Named(f) => f.named.is_empty(), ++ Fields::Unnamed(f) => f.unnamed.is_empty(), ++ } ++ } + } + + impl IntoIterator for Fields { + type Item = Field; + type IntoIter = punctuated::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + match self { +@@ -124,17 +142,17 @@ impl<'a> IntoIterator for &'a mut Fields + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } + } + + ast_struct! { + /// A field of a struct or enum variant. + /// +- /// *This type is available if Syn is built with the `"derive"` or `"full"` ++ /// *This type is available only if Syn is built with the `"derive"` or `"full"` + /// feature.* + pub struct Field { + /// Attributes tagged on the field. + pub attrs: Vec, + + /// Visibility of the field. + pub vis: Visibility, + +@@ -149,17 +167,17 @@ ast_struct! { + pub ty: Type, + } + } + + ast_enum_of_structs! { + /// The visibility level of an item: inherited or `pub` or + /// `pub(restricted)`. + /// +- /// *This type is available if Syn is built with the `"derive"` or `"full"` ++ /// *This type is available only if Syn is built with the `"derive"` or `"full"` + /// feature.* + /// + /// # Syntax tree enum + /// + /// This type is a [syntax tree enum]. + /// + /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums + // +@@ -179,58 +197,61 @@ ast_enum_of_structs! { + /// An inherited visibility, which usually means private. + Inherited, + } + } + + ast_struct! { + /// A public visibility level: `pub`. + /// +- /// *This type is available if Syn is built with the `"derive"` or ++ /// *This type is available only if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct VisPublic { + pub pub_token: Token![pub], + } + } + + ast_struct! { + /// A crate-level visibility: `crate`. + /// +- /// *This type is available if Syn is built with the `"derive"` or ++ /// *This type is available only if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct VisCrate { + pub crate_token: Token![crate], + } + } + + ast_struct! { + /// A visibility level restricted to some path: `pub(self)` or + /// `pub(super)` or `pub(crate)` or `pub(in some::module)`. + /// +- /// *This type is available if Syn is built with the `"derive"` or ++ /// *This type is available only if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct VisRestricted { + pub pub_token: Token![pub], + pub paren_token: token::Paren, + pub in_token: Option, + pub path: Box, + } + } + + #[cfg(feature = "parsing")] + pub mod parsing { + use super::*; + + use crate::ext::IdentExt; ++ use crate::parse::discouraged::Speculative; + use crate::parse::{Parse, ParseStream, Result}; + + impl Parse for Variant { + fn parse(input: ParseStream) -> Result { ++ let attrs = input.call(Attribute::parse_outer)?; ++ let _visibility: Visibility = input.parse()?; + Ok(Variant { +- attrs: input.call(Attribute::parse_outer)?, ++ attrs, + ident: input.parse()?, + fields: { + if input.peek(token::Brace) { + Fields::Named(input.parse()?) + } else if input.peek(token::Paren) { + Fields::Unnamed(input.parse()?) + } else { + Fields::Unit +@@ -290,68 +311,99 @@ pub mod parsing { + colon_token: None, + ty: input.parse()?, + }) + } + } + + impl Parse for Visibility { + fn parse(input: ParseStream) -> Result { ++ // Recognize an empty None-delimited group, as produced by a $:vis ++ // matcher that matched no tokens. ++ if input.peek(token::Group) { ++ let ahead = input.fork(); ++ let group = crate::group::parse_group(&ahead)?; ++ if group.content.is_empty() { ++ input.advance_to(&ahead); ++ return Ok(Visibility::Inherited); ++ } ++ } ++ + if input.peek(Token![pub]) { + Self::parse_pub(input) + } else if input.peek(Token![crate]) { + Self::parse_crate(input) + } else { + Ok(Visibility::Inherited) + } + } + } + + impl Visibility { + fn parse_pub(input: ParseStream) -> Result { + let pub_token = input.parse::()?; + + if input.peek(token::Paren) { +- // TODO: optimize using advance_to + let ahead = input.fork(); +- let mut content; +- parenthesized!(content in ahead); + ++ let content; ++ let paren_token = parenthesized!(content in ahead); + if content.peek(Token![crate]) + || content.peek(Token![self]) + || content.peek(Token![super]) + { ++ let path = content.call(Ident::parse_any)?; ++ ++ // Ensure there are no additional tokens within `content`. ++ // Without explicitly checking, we may misinterpret a tuple ++ // field as a restricted visibility, causing a parse error. ++ // e.g. `pub (crate::A, crate::B)` (Issue #720). ++ if content.is_empty() { ++ input.advance_to(&ahead); ++ return Ok(Visibility::Restricted(VisRestricted { ++ pub_token, ++ paren_token, ++ in_token: None, ++ path: Box::new(Path::from(path)), ++ })); ++ } ++ } else if content.peek(Token![in]) { ++ let in_token: Token![in] = content.parse()?; ++ let path = content.call(Path::parse_mod_style)?; ++ ++ input.advance_to(&ahead); + return Ok(Visibility::Restricted(VisRestricted { + pub_token, +- paren_token: parenthesized!(content in input), +- in_token: None, +- path: Box::new(Path::from(content.call(Ident::parse_any)?)), +- })); +- } else if content.peek(Token![in]) { +- return Ok(Visibility::Restricted(VisRestricted { +- pub_token, +- paren_token: parenthesized!(content in input), +- in_token: Some(content.parse()?), +- path: Box::new(content.call(Path::parse_mod_style)?), ++ paren_token, ++ in_token: Some(in_token), ++ path: Box::new(path), + })); + } + } + + Ok(Visibility::Public(VisPublic { pub_token })) + } + + fn parse_crate(input: ParseStream) -> Result { + if input.peek2(Token![::]) { + Ok(Visibility::Inherited) + } else { + Ok(Visibility::Crate(VisCrate { + crate_token: input.parse()?, + })) + } + } ++ ++ #[cfg(feature = "full")] ++ pub(crate) fn is_some(&self) -> bool { ++ match self { ++ Visibility::Inherited => false, ++ _ => true, ++ } ++ } + } + } + + #[cfg(feature = "printing")] + mod printing { + use super::*; + + use proc_macro2::TokenStream; +diff --git a/third_party/rust/syn/src/derive.rs b/third_party/rust/syn/src/derive.rs +--- a/third_party/rust/syn/src/derive.rs ++++ b/third_party/rust/syn/src/derive.rs +@@ -1,15 +1,15 @@ + use super::*; + use crate::punctuated::Punctuated; + + ast_struct! { + /// Data structure sent to a `proc_macro_derive` macro. + /// +- /// *This type is available if Syn is built with the `"derive"` feature.* ++ /// *This type is available only if Syn is built with the `"derive"` feature.* + pub struct DeriveInput { + /// Attributes tagged on the whole struct or enum. + pub attrs: Vec, + + /// Visibility of the struct or enum. + pub vis: Visibility, + + /// Name of the struct or enum. +@@ -21,17 +21,17 @@ ast_struct! { + /// Data within the struct or enum. + pub data: Data, + } + } + + ast_enum_of_structs! { + /// The storage of a struct, enum or union data structure. + /// +- /// *This type is available if Syn is built with the `"derive"` feature.* ++ /// *This type is available only if Syn is built with the `"derive"` feature.* + /// + /// # Syntax tree enum + /// + /// This type is a [syntax tree enum]. + /// + /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums + // + // TODO: change syntax-tree-enum link to an intra rustdoc link, currently +@@ -48,41 +48,41 @@ ast_enum_of_structs! { + } + + do_not_generate_to_tokens + } + + ast_struct! { + /// A struct input to a `proc_macro_derive` macro. + /// +- /// *This type is available if Syn is built with the `"derive"` ++ /// *This type is available only if Syn is built with the `"derive"` + /// feature.* + pub struct DataStruct { + pub struct_token: Token![struct], + pub fields: Fields, + pub semi_token: Option, + } + } + + ast_struct! { + /// An enum input to a `proc_macro_derive` macro. + /// +- /// *This type is available if Syn is built with the `"derive"` ++ /// *This type is available only if Syn is built with the `"derive"` + /// feature.* + pub struct DataEnum { + pub enum_token: Token![enum], + pub brace_token: token::Brace, + pub variants: Punctuated, + } + } + + ast_struct! { + /// An untagged union input to a `proc_macro_derive` macro. + /// +- /// *This type is available if Syn is built with the `"derive"` ++ /// *This type is available only if Syn is built with the `"derive"` + /// feature.* + pub struct DataUnion { + pub union_token: Token![union], + pub fields: FieldsNamed, + } + } + + #[cfg(feature = "parsing")] +diff --git a/third_party/rust/syn/src/discouraged.rs b/third_party/rust/syn/src/discouraged.rs +--- a/third_party/rust/syn/src/discouraged.rs ++++ b/third_party/rust/syn/src/discouraged.rs +@@ -11,17 +11,17 @@ pub trait Speculative { + /// stream to the fork to "commit" the parsing from the fork to the main + /// stream. + /// + /// If you can avoid doing this, you should, as it limits the ability to + /// generate useful errors. That said, it is often the only way to parse + /// syntax of the form `A* B*` for arbitrary syntax `A` and `B`. The problem + /// is that when the fork fails to parse an `A`, it's impossible to tell + /// whether that was because of a syntax error and the user meant to provide +- /// an `A`, or that the `A`s are finished and its time to start parsing ++ /// an `A`, or that the `A`s are finished and it's time to start parsing + /// `B`s. Use with care. + /// + /// Also note that if `A` is a subset of `B`, `A* B*` can be parsed by + /// parsing `B*` and removing the leading members of `A` from the + /// repetition, bypassing the need to involve the downsides associated with + /// speculative parsing. + /// + /// [`ParseStream::fork`]: ParseBuffer::fork +@@ -67,17 +67,16 @@ pub trait Speculative { + /// # } + /// + /// impl Parse for PathSegment { + /// fn parse(input: ParseStream) -> Result { + /// if input.peek(Token![super]) + /// || input.peek(Token![self]) + /// || input.peek(Token![Self]) + /// || input.peek(Token![crate]) +- /// || input.peek(Token![extern]) + /// { + /// let ident = input.call(Ident::parse_any)?; + /// return Ok(PathSegment::from(ident)); + /// } + /// + /// let ident = input.parse()?; + /// if input.peek(Token![::]) && input.peek3(Token![<]) { + /// return Ok(PathSegment { +@@ -159,13 +158,37 @@ pub trait Speculative { + } + + impl<'a> Speculative for ParseBuffer<'a> { + fn advance_to(&self, fork: &Self) { + if !crate::buffer::same_scope(self.cursor(), fork.cursor()) { + panic!("Fork was not derived from the advancing parse stream"); + } + ++ let (self_unexp, self_sp) = inner_unexpected(self); ++ let (fork_unexp, fork_sp) = inner_unexpected(fork); ++ if !Rc::ptr_eq(&self_unexp, &fork_unexp) { ++ match (fork_sp, self_sp) { ++ // Unexpected set on the fork, but not on `self`, copy it over. ++ (Some(span), None) => { ++ self_unexp.set(Unexpected::Some(span)); ++ } ++ // Unexpected unset. Use chain to propagate errors from fork. ++ (None, None) => { ++ fork_unexp.set(Unexpected::Chain(self_unexp)); ++ ++ // Ensure toplevel 'unexpected' tokens from the fork don't ++ // bubble up the chain by replacing the root `unexpected` ++ // pointer, only 'unexpected' tokens from existing group ++ // parsers should bubble. ++ fork.unexpected ++ .set(Some(Rc::new(Cell::new(Unexpected::None)))); ++ } ++ // Unexpected has been set on `self`. No changes needed. ++ (_, Some(_)) => {} ++ } ++ } ++ + // See comment on `cell` in the struct definition. + self.cell + .set(unsafe { mem::transmute::>(fork.cursor()) }) + } + } +diff --git a/third_party/rust/syn/src/error.rs b/third_party/rust/syn/src/error.rs +--- a/third_party/rust/syn/src/error.rs ++++ b/third_party/rust/syn/src/error.rs +@@ -1,9 +1,8 @@ +-use std; + use std::fmt::{self, Debug, Display}; + use std::iter::FromIterator; + use std::slice; + use std::vec; + + use proc_macro2::{ + Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, + }; +@@ -27,18 +26,18 @@ pub type Result = std::result::Result + /// message than simply panicking the macro. + /// + /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html + /// + /// When parsing macro input, the [`parse_macro_input!`] macro handles the + /// conversion to `compile_error!` automatically. + /// + /// ``` +-/// extern crate proc_macro; +-/// ++/// # extern crate proc_macro; ++/// # + /// use proc_macro::TokenStream; + /// use syn::{parse_macro_input, AttributeArgs, ItemFn}; + /// + /// # const IGNORE: &str = stringify! { + /// #[proc_macro_attribute] + /// # }; + /// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream { + /// let args = parse_macro_input!(args as AttributeArgs); +@@ -77,17 +76,16 @@ pub type Result = std::result::Result + /// # use proc_macro2::TokenStream; + /// # use syn::{DeriveInput, Result}; + /// # + /// # pub fn my_derive(input: DeriveInput) -> Result { + /// # unimplemented!() + /// # } + /// # } + /// ``` +-#[derive(Clone)] + pub struct Error { + messages: Vec, + } + + struct ErrorMessage { + // Span is implemented as an index into a thread-local interner to keep the + // size small. It is not safe to access from a different thread. We want + // errors to be Send and Sync to play nicely with the Failure crate, so pin +@@ -245,16 +243,27 @@ pub fn new_at(scope: Span, c + if cursor.eof() { + Error::new(scope, format!("unexpected end of input, {}", message)) + } else { + let span = crate::buffer::open_span_of_group(cursor); + Error::new(span, message) + } + } + ++#[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))] ++pub fn new2(start: Span, end: Span, message: T) -> Error { ++ Error { ++ messages: vec![ErrorMessage { ++ start_span: ThreadBound::new(start), ++ end_span: ThreadBound::new(end), ++ message: message.to_string(), ++ }], ++ } ++} ++ + impl Debug for Error { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.messages.len() == 1 { + formatter + .debug_tuple("Error") + .field(&self.messages[0]) + .finish() + } else { +@@ -273,16 +282,24 @@ impl Debug for ErrorMessage { + } + + impl Display for Error { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(&self.messages[0].message) + } + } + ++impl Clone for Error { ++ fn clone(&self) -> Self { ++ Error { ++ messages: self.messages.clone(), ++ } ++ } ++} ++ + impl Clone for ErrorMessage { + fn clone(&self) -> Self { + let start = self + .start_span + .get() + .cloned() + .unwrap_or_else(Span::call_site); + let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site); +@@ -350,8 +367,16 @@ impl<'a> Iterator for Iter<'a> { + type Item = Error; + + fn next(&mut self) -> Option { + Some(Error { + messages: vec![self.messages.next()?.clone()], + }) + } + } ++ ++impl Extend for Error { ++ fn extend>(&mut self, iter: T) { ++ for err in iter { ++ self.combine(err); ++ } ++ } ++} +diff --git a/third_party/rust/syn/src/expr.rs b/third_party/rust/syn/src/expr.rs +--- a/third_party/rust/syn/src/expr.rs ++++ b/third_party/rust/syn/src/expr.rs +@@ -1,23 +1,26 @@ + use super::*; + use crate::punctuated::Punctuated; +-#[cfg(feature = "extra-traits")] +-use crate::tt::TokenStreamHelper; ++#[cfg(feature = "full")] ++use crate::reserved::Reserved; + use proc_macro2::{Span, TokenStream}; +-#[cfg(feature = "extra-traits")] ++#[cfg(feature = "printing")] ++use quote::IdentFragment; ++#[cfg(feature = "printing")] ++use std::fmt::{self, Display}; + use std::hash::{Hash, Hasher}; +-#[cfg(all(feature = "parsing", feature = "full"))] ++#[cfg(feature = "parsing")] + use std::mem; + + ast_enum_of_structs! { + /// A Rust expression. + /// +- /// *This type is available if Syn is built with the `"derive"` or `"full"` +- /// feature.* ++ /// *This type is available only if Syn is built with the `"derive"` or `"full"` ++ /// feature, but most of the variants are not available unless "full" is enabled.* + /// + /// # Syntax tree enums + /// + /// This type is a syntax tree enum. In Syn this and other syntax tree enums + /// are designed to be traversed using the following rebinding idiom. + /// + /// ``` + /// # use syn::Expr; +@@ -78,17 +81,17 @@ ast_enum_of_structs! { + /// if let Expr::Tuple(base) = *discriminant.base { + /// # } + /// # } + /// ``` + /// + /// A sign that you may not be choosing the right variable names is if you + /// see names getting repeated in your code, like accessing + /// `receiver.receiver` or `pat.pat` or `cond.cond`. +- pub enum Expr #manual_extra_traits { ++ pub enum Expr { + /// A slice literal expression: `[a, b, c, d]`. + Array(ExprArray), + + /// An assignment expression: `a = compute()`. + Assign(ExprAssign), + + /// A compound assignment expression: `counter += 1`. + AssignOp(ExprAssignOp), +@@ -223,191 +226,191 @@ ast_enum_of_structs! { + #[doc(hidden)] + __Nonexhaustive, + } + } + + ast_struct! { + /// A slice literal expression: `[a, b, c, d]`. + /// +- /// *This type is available if Syn is built with the `"full"` feature.* ++ /// *This type is available only if Syn is built with the `"full"` feature.* + pub struct ExprArray #full { + pub attrs: Vec, + pub bracket_token: token::Bracket, + pub elems: Punctuated, + } + } + + ast_struct! { + /// An assignment expression: `a = compute()`. + /// +- /// *This type is available if Syn is built with the `"full"` feature.* ++ /// *This type is available only if Syn is built with the `"full"` feature.* + pub struct ExprAssign #full { + pub attrs: Vec, + pub left: Box, + pub eq_token: Token![=], + pub right: Box, + } + } + + ast_struct! { + /// A compound assignment expression: `counter += 1`. + /// +- /// *This type is available if Syn is built with the `"full"` feature.* ++ /// *This type is available only if Syn is built with the `"full"` feature.* + pub struct ExprAssignOp #full { + pub attrs: Vec, + pub left: Box, + pub op: BinOp, + pub right: Box, + } + } + + ast_struct! { + /// An async block: `async { ... }`. + /// +- /// *This type is available if Syn is built with the `"full"` feature.* ++ /// *This type is available only if Syn is built with the `"full"` feature.* + pub struct ExprAsync #full { + pub attrs: Vec, + pub async_token: Token![async], + pub capture: Option, + pub block: Block, + } + } + + ast_struct! { + /// An await expression: `fut.await`. + /// +- /// *This type is available if Syn is built with the `"full"` feature.* ++ /// *This type is available only if Syn is built with the `"full"` feature.* + pub struct ExprAwait #full { + pub attrs: Vec, + pub base: Box, + pub dot_token: Token![.], + pub await_token: token::Await, + } + } + + ast_struct! { + /// A binary operation: `a + b`, `a * b`. + /// +- /// *This type is available if Syn is built with the `"derive"` or ++ /// *This type is available only if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct ExprBinary { + pub attrs: Vec, + pub left: Box, + pub op: BinOp, + pub right: Box, + } + } + + ast_struct! { + /// A blocked scope: `{ ... }`. + /// +- /// *This type is available if Syn is built with the `"full"` feature.* ++ /// *This type is available only if Syn is built with the `"full"` feature.* + pub struct ExprBlock #full { + pub attrs: Vec, + pub label: Option