diff options
Diffstat (limited to 'widget/gtk/GtkCompositorWidget.cpp')
-rw-r--r-- | widget/gtk/GtkCompositorWidget.cpp | 246 |
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 |