Bug 1364355 - Implement UpdateOpaqueRegion() by gdk_window_set_opaque_region(), r?karlt draft
authorMartin Stransky <stransky@redhat.com>
Fri, 26 May 2017 21:27:32 +0200
changeset 587569 a841190f85d70524cab3fd0f22af86cb7371bc66
parent 587568 7ff2962c5fd3683a4155f8087f4ffc3a72f9e5ff
child 631312 d3489e35dbbfcc847d1e60c28ed13406c95490e8
push id61752
push userstransky@redhat.com
push dateThu, 01 Jun 2017 09:31:19 +0000
reviewerskarlt
bugs1364355
milestone55.0a1
Bug 1364355 - Implement UpdateOpaqueRegion() by gdk_window_set_opaque_region(), r?karlt MozReview-Commit-ID: 50N99ZlvFUh
widget/gtk/mozgtk/mozgtk.c
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
--- a/widget/gtk/mozgtk/mozgtk.c
+++ b/widget/gtk/mozgtk/mozgtk.c
@@ -512,16 +512,17 @@ STUB(gtk_window_unmaximize)
 STUB(gdk_device_get_source)
 STUB(gdk_device_manager_get_client_pointer)
 STUB(gdk_disable_multidevice)
 STUB(gdk_device_manager_list_devices)
 STUB(gdk_display_get_device_manager)
 STUB(gdk_error_trap_pop_ignored)
 STUB(gdk_event_get_source_device)
 STUB(gdk_window_get_type)
+STUB(gdk_window_get_window_type)
 STUB(gdk_x11_window_get_xid)
 STUB(gdk_x11_display_get_type)
 STUB(gtk_box_new)
 STUB(gtk_cairo_should_draw_window)
 STUB(gtk_cairo_transform_to_window)
 STUB(gtk_combo_box_text_append)
 STUB(gtk_drag_set_icon_surface)
 STUB(gtk_get_major_version)
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -4365,16 +4365,43 @@ nsWindow::GetTransparencyMode()
         }
 
         return topWindow->GetTransparencyMode();
     }
 
     return mIsTransparent ? eTransparencyTransparent : eTransparencyOpaque;
 }
 
+#if (MOZ_WIDGET_GTK >= 3)
+void nsWindow::UpdateOpaqueRegion(const LayoutDeviceIntRegion& aOpaqueRegion)
+{
+    // Available as of GTK 3.10+
+    static auto sGdkWindowSetOpaqueRegion =
+        (void (*)(GdkWindow*, cairo_region_t*))
+            dlsym(RTLD_DEFAULT, "gdk_window_set_opaque_region");
+
+    if (sGdkWindowSetOpaqueRegion && mGdkWindow &&
+        gdk_window_get_window_type(mGdkWindow) == GDK_WINDOW_TOPLEVEL) {
+        if (aOpaqueRegion.IsEmpty()) {
+            (*sGdkWindowSetOpaqueRegion)(mGdkWindow, nullptr);
+        } else {
+            cairo_region_t *region = cairo_region_create();
+            for (auto iter = aOpaqueRegion.RectIter(); !iter.Done();
+                 iter.Next()) {
+                const LayoutDeviceIntRect &r = iter.Get();
+                cairo_rectangle_int_t rect = { r.x, r.y, r.width, r.height };
+                cairo_region_union_rectangle(region, &rect);
+            }
+            (*sGdkWindowSetOpaqueRegion)(mGdkWindow, region);
+            cairo_region_destroy(region);
+        }
+    }
+}
+#endif
+
 nsresult
 nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
 {
     // If this is a remotely updated widget we receive clipping, position, and
     // size information from a source other than our owner. Don't let our parent
     // update this information.
     if (mWindowType == eWindowType_plugin_ipc_chrome) {
       return NS_OK;
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -303,16 +303,19 @@ public:
 
     // These methods are for toplevel windows only.
     void               ResizeTransparencyBitmap();
     void               ApplyTransparencyBitmap();
     void               ClearTransparencyBitmap();
 
    virtual void        SetTransparencyMode(nsTransparencyMode aMode) override;
    virtual nsTransparencyMode GetTransparencyMode() override;
+#if (MOZ_WIDGET_GTK >= 3)
+   virtual void        UpdateOpaqueRegion(const LayoutDeviceIntRegion& aOpaqueRegion) override;
+#endif
    virtual nsresult    ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override;
    nsresult            UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
                                                             uint8_t* aAlphas, int32_t aStride);
 
 #if (MOZ_WIDGET_GTK == 2)
     static already_AddRefed<DrawTarget> GetDrawTargetForGdkDrawable(GdkDrawable* aDrawable,
                                                                     const mozilla::gfx::IntSize& aSize);
 #endif