summaryrefslogtreecommitdiffstats
path: root/widget/gtk/GtkCompositorWidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--widget/gtk/GtkCompositorWidget.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/widget/gtk/GtkCompositorWidget.cpp b/widget/gtk/GtkCompositorWidget.cpp
new file mode 100644
index 0000000000..2c29d5de03
--- /dev/null
+++ b/widget/gtk/GtkCompositorWidget.cpp
@@ -0,0 +1,246 @@
+/* -*- Mode: C++; tab-width: 2; 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 "GtkCompositorWidget.h"
+
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/layers/CompositorThread.h"
+#include "mozilla/widget/InProcessCompositorWidget.h"
+#include "mozilla/widget/PlatformWidgetTypes.h"
+#include "nsWindow.h"
+
+#ifdef MOZ_X11
+# include "mozilla/X11Util.h"
+#endif
+
+#ifdef MOZ_WAYLAND
+# include "mozilla/layers/NativeLayerWayland.h"
+#endif
+
+#ifdef MOZ_LOGGING
+# undef LOG
+# define LOG(str, ...) \
+ MOZ_LOG(IsPopup() ? gWidgetPopupLog : gWidgetLog, \
+ mozilla::LogLevel::Debug, \
+ ("[%p]: " str, mWidget.get(), ##__VA_ARGS__))
+#endif /* MOZ_LOGGING */
+
+namespace mozilla {
+namespace widget {
+
+GtkCompositorWidget::GtkCompositorWidget(
+ const GtkCompositorWidgetInitData& aInitData,
+ const layers::CompositorOptions& aOptions, RefPtr<nsWindow> aWindow)
+ : CompositorWidget(aOptions),
+ mWidget(std::move(aWindow)),
+ mClientSize(LayoutDeviceIntSize(aInitData.InitialClientSize()),
+ "GtkCompositorWidget::mClientSize") {
+#if defined(MOZ_X11)
+ if (GdkIsX11Display()) {
+ mXWindow = (Window)aInitData.XWindow();
+ ConfigureX11Backend(mXWindow, aInitData.Shaped());
+ LOG("GtkCompositorWidget::GtkCompositorWidget() [%p] mXWindow %p "
+ "mIsRenderingSuspended %d\n",
+ (void*)mWidget.get(), (void*)mXWindow, !!mIsRenderingSuspended);
+ }
+#endif
+#if defined(MOZ_WAYLAND)
+ if (GdkIsWaylandDisplay()) {
+ ConfigureWaylandBackend();
+ LOG("GtkCompositorWidget::GtkCompositorWidget() [%p] mWidget %p "
+ "mIsRenderingSuspended %d\n",
+ (void*)mWidget.get(), (void*)mWidget, !!mIsRenderingSuspended);
+ }
+#endif
+}
+
+GtkCompositorWidget::~GtkCompositorWidget() {
+ LOG("GtkCompositorWidget::~GtkCompositorWidget [%p]\n", (void*)mWidget.get());
+ DisableRendering();
+ RefPtr<nsIWidget> widget = mWidget.forget();
+ NS_ReleaseOnMainThread("GtkCompositorWidget::mWidget", widget.forget());
+}
+
+already_AddRefed<gfx::DrawTarget> GtkCompositorWidget::StartRemoteDrawing() {
+ return nullptr;
+}
+void GtkCompositorWidget::EndRemoteDrawing() {}
+
+already_AddRefed<gfx::DrawTarget>
+GtkCompositorWidget::StartRemoteDrawingInRegion(
+ const LayoutDeviceIntRegion& aInvalidRegion,
+ layers::BufferMode* aBufferMode) {
+ return mProvider.StartRemoteDrawingInRegion(aInvalidRegion, aBufferMode);
+}
+
+void GtkCompositorWidget::EndRemoteDrawingInRegion(
+ gfx::DrawTarget* aDrawTarget, const LayoutDeviceIntRegion& aInvalidRegion) {
+ mProvider.EndRemoteDrawingInRegion(aDrawTarget, aInvalidRegion);
+}
+
+nsIWidget* GtkCompositorWidget::RealWidget() { return mWidget; }
+
+void GtkCompositorWidget::NotifyClientSizeChanged(
+ const LayoutDeviceIntSize& aClientSize) {
+ LOG("GtkCompositorWidget::NotifyClientSizeChanged() to %d x %d",
+ aClientSize.width, aClientSize.height);
+
+ auto size = mClientSize.Lock();
+ *size = aClientSize;
+}
+
+LayoutDeviceIntSize GtkCompositorWidget::GetClientSize() {
+ auto size = mClientSize.Lock();
+ return *size;
+}
+
+void GtkCompositorWidget::RemoteLayoutSizeUpdated(
+ const LayoutDeviceRect& aSize) {
+ if (!mWidget || !mWidget->IsWaitingForCompositorResume()) {
+ return;
+ }
+
+ LOG("GtkCompositorWidget::RemoteLayoutSizeUpdated() %d x %d",
+ (int)aSize.width, (int)aSize.height);
+
+ // We're waiting for layout to match widget size.
+ auto clientSize = mClientSize.Lock();
+ if (clientSize->width != (int)aSize.width ||
+ clientSize->height != (int)aSize.height) {
+ LOG("quit, client size doesn't match (%d x %d)", clientSize->width,
+ clientSize->height);
+ return;
+ }
+
+ mWidget->ResumeCompositorFromCompositorThread();
+}
+
+EGLNativeWindowType GtkCompositorWidget::GetEGLNativeWindow() {
+ EGLNativeWindowType window = nullptr;
+ if (mWidget) {
+ window = (EGLNativeWindowType)mWidget->GetNativeData(NS_NATIVE_EGL_WINDOW);
+ }
+#if defined(MOZ_X11)
+ if (mXWindow) {
+ window = (EGLNativeWindowType)mXWindow;
+ }
+#endif
+ LOG("GtkCompositorWidget::GetEGLNativeWindow [%p] window %p\n", mWidget.get(),
+ window);
+ return window;
+}
+
+#if defined(MOZ_WAYLAND)
+void GtkCompositorWidget::SetEGLNativeWindowSize(
+ const LayoutDeviceIntSize& aEGLWindowSize) {
+ if (mWidget) {
+ mWidget->SetEGLNativeWindowSize(aEGLWindowSize);
+ }
+}
+#endif
+
+LayoutDeviceIntRegion GtkCompositorWidget::GetTransparentRegion() {
+ // We need to clear target buffer alpha values of popup windows as
+ // SW-WR paints with alpha blending (see Bug 1674473).
+ if (!mWidget || mWidget->IsPopup()) {
+ return LayoutDeviceIntRect(LayoutDeviceIntPoint(0, 0), GetClientSize());
+ }
+
+ // Clear background of titlebar area to render titlebar
+ // transparent corners correctly.
+ return mWidget->GetTitlebarRect();
+}
+
+#ifdef MOZ_WAYLAND
+RefPtr<mozilla::layers::NativeLayerRoot>
+GtkCompositorWidget::GetNativeLayerRoot() {
+ if (gfx::gfxVars::UseWebRenderCompositor()) {
+ if (!mNativeLayerRoot) {
+ MOZ_ASSERT(mWidget && mWidget->GetMozContainer());
+ mNativeLayerRoot = NativeLayerRootWayland::CreateForMozContainer(
+ mWidget->GetMozContainer());
+ }
+ return mNativeLayerRoot;
+ }
+ return nullptr;
+}
+#endif
+
+void GtkCompositorWidget::DisableRendering() {
+ LOG("GtkCompositorWidget::DisableRendering [%p]\n", (void*)mWidget.get());
+ mIsRenderingSuspended = true;
+ mProvider.CleanupResources();
+#if defined(MOZ_X11)
+ mXWindow = {};
+#endif
+}
+
+#if defined(MOZ_WAYLAND)
+bool GtkCompositorWidget::ConfigureWaylandBackend() {
+ mProvider.Initialize(this);
+ return true;
+}
+#endif
+
+#if defined(MOZ_X11)
+bool GtkCompositorWidget::ConfigureX11Backend(Window aXWindow, bool aShaped) {
+ mXWindow = aXWindow;
+
+ // We don't have X window yet.
+ if (!mXWindow) {
+ mIsRenderingSuspended = true;
+ return false;
+ }
+
+ // Grab the window's visual and depth
+ XWindowAttributes windowAttrs;
+ if (!XGetWindowAttributes(DefaultXDisplay(), mXWindow, &windowAttrs)) {
+ NS_WARNING("GtkCompositorWidget(): XGetWindowAttributes() failed!");
+ return false;
+ }
+
+ Visual* visual = windowAttrs.visual;
+ int depth = windowAttrs.depth;
+
+ // Initialize the window surface provider
+ mProvider.Initialize(mXWindow, visual, depth, aShaped);
+ return true;
+}
+#endif
+
+void GtkCompositorWidget::EnableRendering(const uintptr_t aXWindow,
+ const bool aShaped) {
+ LOG("GtkCompositorWidget::EnableRendering() [%p]\n", mWidget.get());
+
+ if (!mIsRenderingSuspended) {
+ LOG(" quit, mIsRenderingSuspended = false\n");
+ return;
+ }
+#if defined(MOZ_WAYLAND)
+ if (GdkIsWaylandDisplay()) {
+ LOG(" configure widget %p\n", mWidget.get());
+ if (!ConfigureWaylandBackend()) {
+ return;
+ }
+ }
+#endif
+#if defined(MOZ_X11)
+ if (GdkIsX11Display()) {
+ LOG(" configure XWindow %p shaped %d\n", (void*)aXWindow, aShaped);
+ if (!ConfigureX11Backend((Window)aXWindow, aShaped)) {
+ return;
+ }
+ }
+#endif
+ mIsRenderingSuspended = false;
+}
+#ifdef MOZ_LOGGING
+bool GtkCompositorWidget::IsPopup() {
+ return mWidget ? mWidget->IsPopup() : false;
+}
+#endif
+
+} // namespace widget
+} // namespace mozilla