diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebKit2/WebProcess/WebPage/gtk | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage/gtk')
14 files changed, 871 insertions, 304 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.cpp new file mode 100644 index 000000000..6b20cd85d --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2016 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AcceleratedSurface.h" + +#include "WebPage.h" +#include <WebCore/PlatformDisplay.h> + +#if PLATFORM(WAYLAND) +#include "AcceleratedSurfaceWayland.h" +#endif + +#if USE(REDIRECTED_XCOMPOSITE_WINDOW) +#include "AcceleratedSurfaceX11.h" +#endif + +using namespace WebCore; + +namespace WebKit { + +std::unique_ptr<AcceleratedSurface> AcceleratedSurface::create(WebPage& webPage) +{ +#if PLATFORM(WAYLAND) + if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland) + return AcceleratedSurfaceWayland::create(webPage); +#endif +#if USE(REDIRECTED_XCOMPOSITE_WINDOW) + if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) + return AcceleratedSurfaceX11::create(webPage); +#endif + return nullptr; +} + +AcceleratedSurface::AcceleratedSurface(WebPage& webPage) + : m_webPage(webPage) + , m_size(webPage.size()) +{ + m_size.scale(m_webPage.deviceScaleFactor()); +} + +bool AcceleratedSurface::resize(const IntSize& size) +{ + IntSize scaledSize(size); + scaledSize.scale(m_webPage.deviceScaleFactor()); + if (scaledSize == m_size) + return false; + + m_size = scaledSize; + return true; +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.h b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.h new file mode 100644 index 000000000..26b4c8a53 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <WebCore/IntSize.h> +#include <wtf/Noncopyable.h> + +namespace WebKit { + +class WebPage; + +class AcceleratedSurface { + WTF_MAKE_NONCOPYABLE(AcceleratedSurface); WTF_MAKE_FAST_ALLOCATED; +public: + static std::unique_ptr<AcceleratedSurface> create(WebPage&); + virtual ~AcceleratedSurface() = default; + + virtual uint64_t window() const { ASSERT_NOT_REACHED(); return 0; } + virtual uint64_t surfaceID() const { ASSERT_NOT_REACHED(); return 0; }; + virtual bool resize(const WebCore::IntSize&); + virtual bool shouldPaintMirrored() const { return false; } + +protected: + AcceleratedSurface(WebPage&); + + WebPage& m_webPage; + WebCore::IntSize m_size; +}; + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp new file mode 100644 index 000000000..b6f0b87f7 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2016 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AcceleratedSurfaceWayland.h" + +#if PLATFORM(WAYLAND) + +#include "WebKit2WaylandClientProtocol.h" +#include "WebProcess.h" +#include <WebCore/PlatformDisplayWayland.h> +#include <cstring> +#include <wayland-egl.h> +#include <wtf/NeverDestroyed.h> + +using namespace WebCore; + +namespace WebKit { + +class WaylandCompositorDisplay final : public PlatformDisplayWayland { + WTF_MAKE_NONCOPYABLE(WaylandCompositorDisplay); +public: + static std::unique_ptr<WaylandCompositorDisplay> create() + { + struct wl_display* display = wl_display_connect(WebProcess::singleton().waylandCompositorDisplayName().utf8().data()); + if (!display) { + WTFLogAlways("PlatformDisplayWayland initialization: failed to connect to the Wayland display: %s", WebProcess::singleton().waylandCompositorDisplayName().utf8().data()); + return nullptr; + } + + return std::unique_ptr<WaylandCompositorDisplay>(new WaylandCompositorDisplay(display)); + } + + void bindSurfaceToPage(struct wl_surface* surface, WebPage& page) + { + if (!m_webkitgtk) + return; + + wl_webkitgtk_bind_surface_to_page(reinterpret_cast<struct wl_webkitgtk*>(m_webkitgtk.get()), surface, page.pageID()); + wl_display_roundtrip(m_display); + } + +private: + WaylandCompositorDisplay(struct wl_display* display) + { + initialize(display); + PlatformDisplay::setSharedDisplayForCompositing(*this); + } + + void registryGlobal(const char* interface, uint32_t name) override + { + PlatformDisplayWayland::registryGlobal(interface, name); + if (!std::strcmp(interface, "wl_webkitgtk")) + m_webkitgtk.reset(static_cast<struct wl_proxy*>(wl_registry_bind(m_registry.get(), name, &wl_webkitgtk_interface, 1))); + } + + WlUniquePtr<struct wl_proxy> m_webkitgtk; +}; + +static std::unique_ptr<WaylandCompositorDisplay>& waylandCompositorDisplay() +{ + static NeverDestroyed<std::unique_ptr<WaylandCompositorDisplay>> waylandDisplay(WaylandCompositorDisplay::create()); + return waylandDisplay; +} + +std::unique_ptr<AcceleratedSurfaceWayland> AcceleratedSurfaceWayland::create(WebPage& webPage) +{ + return waylandCompositorDisplay() ? std::unique_ptr<AcceleratedSurfaceWayland>(new AcceleratedSurfaceWayland(webPage)) : nullptr; +} + +AcceleratedSurfaceWayland::AcceleratedSurfaceWayland(WebPage& webPage) + : AcceleratedSurface(webPage) + , m_surface(waylandCompositorDisplay()->createSurface()) + , m_window(wl_egl_window_create(m_surface.get(), std::max(1, m_size.width()), std::max(1, m_size.height()))) +{ + waylandCompositorDisplay()->bindSurfaceToPage(m_surface.get(), m_webPage); +} + +AcceleratedSurfaceWayland::~AcceleratedSurfaceWayland() +{ + wl_egl_window_destroy(m_window); +} + +bool AcceleratedSurfaceWayland::resize(const IntSize& size) +{ + if (!AcceleratedSurface::resize(size)) + return false; + + wl_egl_window_resize(m_window, m_size.width(), m_size.height(), 0, 0); + return true; +} + +} // namespace WebKit + +#endif // PLATFORM(WAYLAND) diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h new file mode 100644 index 000000000..38a2fbcd0 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if PLATFORM(WAYLAND) + +#include "AcceleratedSurface.h" +#include "WebPage.h" +#include <WebCore/WlUniquePtr.h> +#include <wayland-egl.h> + +namespace WebKit { + +class AcceleratedSurfaceWayland final : public AcceleratedSurface { + WTF_MAKE_NONCOPYABLE(AcceleratedSurfaceWayland); WTF_MAKE_FAST_ALLOCATED; +public: + static std::unique_ptr<AcceleratedSurfaceWayland> create(WebPage&); + ~AcceleratedSurfaceWayland(); + + uint64_t window() const override { return reinterpret_cast<uint64_t>(m_window); } + uint64_t surfaceID() const override { return m_webPage.pageID(); } + bool resize(const WebCore::IntSize&) override; + bool shouldPaintMirrored() const override { return true; } + +private: + AcceleratedSurfaceWayland(WebPage&); + + WebCore::WlUniquePtr<struct wl_surface> m_surface; + struct wl_egl_window* m_window { nullptr }; +}; + +} // namespace WebKit + +#endif // PLATFORM(WAYLAND) diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceX11.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceX11.cpp new file mode 100644 index 000000000..665e25789 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceX11.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2012-2016 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AcceleratedSurfaceX11.h" + +#if USE(REDIRECTED_XCOMPOSITE_WINDOW) + +#include "WebPage.h" +#include <WebCore/PlatformDisplayX11.h> +#include <WebCore/RefPtrCairo.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xcomposite.h> +#include <cairo-xlib.h> +#include <gdk/gdkx.h> +#include <wtf/RunLoop.h> + +using namespace WebCore; + +namespace WebKit { + +std::unique_ptr<AcceleratedSurfaceX11> AcceleratedSurfaceX11::create(WebPage& webPage) +{ + if (!downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).supportsXComposite()) + return nullptr; + return std::unique_ptr<AcceleratedSurfaceX11>(new AcceleratedSurfaceX11(webPage)); +} + +static GdkVisual* defaultVisual() +{ + if (GdkVisual* visual = gdk_screen_get_rgba_visual(gdk_screen_get_default())) + return visual; + return gdk_screen_get_system_visual(gdk_screen_get_default()); +} + +AcceleratedSurfaceX11::AcceleratedSurfaceX11(WebPage& webPage) + : AcceleratedSurface(webPage) + , m_display(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native()) +{ + Screen* screen = DefaultScreenOfDisplay(m_display); + + ASSERT(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native() == m_display); + + GdkVisual* visual = defaultVisual(); + XUniqueColormap colormap(XCreateColormap(m_display, RootWindowOfScreen(screen), GDK_VISUAL_XVISUAL(visual), AllocNone)); + + XSetWindowAttributes windowAttributes; + windowAttributes.override_redirect = True; + windowAttributes.colormap = colormap.get(); + + // CWBorderPixel must be present when the depth doesn't match the parent's one. + // See http://cgit.freedesktop.org/xorg/xserver/tree/dix/window.c?id=xorg-server-1.16.0#n703. + windowAttributes.border_pixel = 0; + + m_parentWindow = XCreateWindow(m_display, + RootWindowOfScreen(screen), + -1, -1, 1, 1, + 0, + gdk_visual_get_depth(visual), + InputOutput, + GDK_VISUAL_XVISUAL(visual), + CWOverrideRedirect | CWColormap | CWBorderPixel, + &windowAttributes); + XMapWindow(m_display, m_parentWindow.get()); + + windowAttributes.event_mask = StructureNotifyMask; + windowAttributes.override_redirect = False; + + // Create the window of at last 1x1 since X doesn't allow to create empty windows. + m_window = XCreateWindow(m_display, + m_parentWindow.get(), + 0, 0, + std::max(1, m_size.width()), + std::max(1, m_size.height()), + 0, + CopyFromParent, + InputOutput, + CopyFromParent, + CWEventMask, + &windowAttributes); + XMapWindow(m_display, m_window.get()); + + while (1) { + XEvent event; + XWindowEvent(m_display, m_window.get(), StructureNotifyMask, &event); + if (event.type == MapNotify && event.xmap.window == m_window.get()) + break; + } + XSelectInput(m_display, m_window.get(), NoEventMask); + XCompositeRedirectWindow(m_display, m_window.get(), CompositeRedirectManual); + createPixmap(); +} + +AcceleratedSurfaceX11::~AcceleratedSurfaceX11() +{ + ASSERT(m_display); + ASSERT(m_window); + ASSERT(m_parentWindow); + + // Explicitly reset these because we need to ensure it happens in this order. + m_window.reset(); + m_parentWindow.reset(); +} + +void AcceleratedSurfaceX11::createPixmap() +{ + m_pixmap = XCompositeNameWindowPixmap(m_display, m_window.get()); + RefPtr<cairo_surface_t> surface = adoptRef(cairo_xlib_surface_create(m_display, m_pixmap.get(), GDK_VISUAL_XVISUAL(defaultVisual()), m_size.width(), m_size.height())); + RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get())); + cairo_set_operator(cr.get(), CAIRO_OPERATOR_CLEAR); + cairo_paint(cr.get()); + XSync(m_display, False); +} + +bool AcceleratedSurfaceX11::resize(const IntSize& size) +{ + if (!AcceleratedSurface::resize(size)) + return false; + + // Resize the window to at last 1x1 since X doesn't allow to create empty windows. + XResizeWindow(m_display, m_window.get(), std::max(1, m_size.width()), std::max(1, m_size.height())); + XFlush(m_display); + + // Release the previous pixmap later to give some time to the UI process to update. + RunLoop::main().dispatchAfter(std::chrono::seconds(5), [pixmap = WTFMove(m_pixmap)] { }); + createPixmap(); + return true; +} + +} // namespace WebCore + +#endif // USE(REDIRECTED_XCOMPOSITE_WINDOW) diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceX11.h b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceX11.h new file mode 100644 index 000000000..740f58978 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceX11.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012-2016 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if USE(REDIRECTED_XCOMPOSITE_WINDOW) + +#include "AcceleratedSurface.h" +#include <WebCore/XUniqueResource.h> + +typedef struct _XDisplay Display; +typedef unsigned long Pixmap; +typedef unsigned long Window; + +namespace WebKit { + +class WebPage; + +class AcceleratedSurfaceX11 final : public AcceleratedSurface { + WTF_MAKE_NONCOPYABLE(AcceleratedSurfaceX11); WTF_MAKE_FAST_ALLOCATED; +public: + static std::unique_ptr<AcceleratedSurfaceX11> create(WebPage&); + ~AcceleratedSurfaceX11(); + + uint64_t window() const override { return m_window.get(); } + uint64_t surfaceID() const override { return m_pixmap.get(); } + bool resize(const WebCore::IntSize&) override; + bool shouldPaintMirrored() const override { return false; } + +private: + AcceleratedSurfaceX11(WebPage&); + + void createPixmap(); + + Display* m_display { nullptr }; + WebCore::XUniqueWindow m_window; + WebCore::XUniqueWindow m_parentWindow; + WebCore::XUniquePixmap m_pixmap; +}; + +} // namespace WebKit + +#endif // USE(REDIRECTED_XCOMPOSITE_WINDOW) diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp index 70f6c8365..40bb07d9f 100644 --- a/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp +++ b/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp @@ -29,6 +29,7 @@ #if USE(TEXTURE_MAPPER_GL) +#include "AcceleratedSurface.h" #include "DrawingAreaImpl.h" #include "TextureMapperGL.h" #include "WebPage.h" @@ -46,63 +47,103 @@ #include <WebCore/MainFrame.h> #include <WebCore/Page.h> #include <WebCore/Settings.h> -#include <wtf/CurrentTime.h> - #include <gdk/gdk.h> -#if defined(GDK_WINDOWING_X11) -#define Region XRegion -#define Font XFont -#define Cursor XCursor -#define Screen XScreen -#include <gdk/gdkx.h> -#endif +#include <wtf/CurrentTime.h> using namespace WebCore; namespace WebKit { -PassRefPtr<LayerTreeHostGtk> LayerTreeHostGtk::create(WebPage* webPage) +LayerTreeHostGtk::RenderFrameScheduler::RenderFrameScheduler(std::function<bool()> renderer) + : m_renderer(WTFMove(renderer)) + , m_timer(RunLoop::main(), this, &LayerTreeHostGtk::RenderFrameScheduler::renderFrame) { - RefPtr<LayerTreeHostGtk> host = adoptRef(new LayerTreeHostGtk(webPage)); - host->initialize(); - return host.release(); + // We use a RunLoop timer because otherwise GTK+ event handling during dragging can starve WebCore timers, which have a lower priority. + // Use a higher priority than WebCore timers. + m_timer.setPriority(GDK_PRIORITY_REDRAW - 1); } -LayerTreeHostGtk::LayerTreeHostGtk(WebPage* webPage) - : LayerTreeHost(webPage) - , m_isValid(true) - , m_notifyAfterScheduledLayerFlush(false) - , m_lastFlushTime(0) - , m_layerFlushSchedulingEnabled(true) - , m_layerFlushTimerCallbackId(0) +LayerTreeHostGtk::RenderFrameScheduler::~RenderFrameScheduler() { } -GLContext* LayerTreeHostGtk::glContext() +void LayerTreeHostGtk::RenderFrameScheduler::start() { - if (m_context) - return m_context.get(); + if (m_timer.isActive()) + return; + m_fireTime = 0; + nextFrame(); +} + +void LayerTreeHostGtk::RenderFrameScheduler::stop() +{ + m_timer.stop(); +} + +static inline bool shouldSkipNextFrameBecauseOfContinousImmediateFlushes(double current, double lastImmediateFlushTime) +{ + // 100ms is about a perceptable delay in UI, so when scheduling layer flushes immediately for more than 100ms, + // we skip the next frame to ensure pending timers have a change to be fired. + static const double maxDurationOfImmediateFlushes = 0.100; + if (!lastImmediateFlushTime) + return false; + return lastImmediateFlushTime + maxDurationOfImmediateFlushes < current; +} - uint64_t windowHandle = m_webPage->nativeWindowHandle(); - if (!windowHandle) - return 0; +void LayerTreeHostGtk::RenderFrameScheduler::nextFrame() +{ + static const double targetFramerate = 1 / 60.0; + // When rendering layers takes more time than the target delay (0.016), we end up scheduling layer flushes + // immediately. Since the layer flush timer has a higher priority than WebCore timers, these are never + // fired while we keep scheduling layer flushes immediately. + double current = monotonicallyIncreasingTime(); + double timeToNextFlush = std::max(targetFramerate - (current - m_fireTime), 0.0); + if (timeToNextFlush) + m_lastImmediateFlushTime = 0; + else if (!m_lastImmediateFlushTime) + m_lastImmediateFlushTime = current; + + if (shouldSkipNextFrameBecauseOfContinousImmediateFlushes(current, m_lastImmediateFlushTime)) { + timeToNextFlush = targetFramerate; + m_lastImmediateFlushTime = 0; + } + + m_timer.startOneShot(timeToNextFlush); +} + +void LayerTreeHostGtk::RenderFrameScheduler::renderFrame() +{ + m_fireTime = monotonicallyIncreasingTime(); + if (!m_renderer() || m_timer.isActive()) + return; + nextFrame(); +} - m_context = GLContext::createContextForWindow(windowHandle, GLContext::sharingContext()); - return m_context.get(); +Ref<LayerTreeHostGtk> LayerTreeHostGtk::create(WebPage& webPage) +{ + return adoptRef(*new LayerTreeHostGtk(webPage)); } -void LayerTreeHostGtk::initialize() +LayerTreeHostGtk::LayerTreeHostGtk(WebPage& webPage) + : LayerTreeHost(webPage) + , m_surface(AcceleratedSurface::create(webPage)) + , m_renderFrameScheduler(std::bind(&LayerTreeHostGtk::renderFrame, this)) { - m_rootLayer = GraphicsLayer::create(graphicsLayerFactory(), this); + m_rootLayer = GraphicsLayer::create(graphicsLayerFactory(), *this); m_rootLayer->setDrawsContent(false); - m_rootLayer->setSize(m_webPage->size()); + m_rootLayer->setSize(m_webPage.size()); + + m_scaleMatrix.makeIdentity(); + m_scaleMatrix.scale(m_webPage.deviceScaleFactor() * m_webPage.pageScaleFactor()); + downcast<GraphicsLayerTextureMapper>(*m_rootLayer).layer().setAnchorPoint(FloatPoint3D()); + downcast<GraphicsLayerTextureMapper>(*m_rootLayer).layer().setTransform(m_scaleMatrix); // The non-composited contents are a child of the root layer. - m_nonCompositedContentLayer = GraphicsLayer::create(graphicsLayerFactory(), this); + m_nonCompositedContentLayer = GraphicsLayer::create(graphicsLayerFactory(), *this); m_nonCompositedContentLayer->setDrawsContent(true); - m_nonCompositedContentLayer->setContentsOpaque(m_webPage->drawsBackground() && !m_webPage->drawsTransparentBackground()); - m_nonCompositedContentLayer->setSize(m_webPage->size()); - if (m_webPage->corePage()->settings().acceleratedDrawingEnabled()) + m_nonCompositedContentLayer->setContentsOpaque(m_webPage.drawsBackground()); + m_nonCompositedContentLayer->setSize(m_webPage.size()); + if (m_webPage.corePage()->settings().acceleratedDrawingEnabled()) m_nonCompositedContentLayer->setAcceleratesDrawing(true); #ifndef NDEBUG @@ -113,46 +154,45 @@ void LayerTreeHostGtk::initialize() m_rootLayer->addChild(m_nonCompositedContentLayer.get()); m_nonCompositedContentLayer->setNeedsDisplay(); - m_layerTreeContext.windowHandle = m_webPage->nativeWindowHandle(); + if (m_surface) { + createTextureMapper(); + m_layerTreeContext.contextID = m_surface->surfaceID(); + } +} + +bool LayerTreeHostGtk::makeContextCurrent() +{ + uint64_t nativeHandle = m_surface ? m_surface->window() : m_layerTreeContext.contextID; + if (!nativeHandle) { + m_context = nullptr; + return false; + } - GLContext* context = glContext(); - if (!context) - return; + if (m_context) + return m_context->makeContextCurrent(); - // The creation of the TextureMapper needs an active OpenGL context. - context->makeContextCurrent(); + m_context = GLContext::createContextForWindow(reinterpret_cast<GLNativeWindowType>(nativeHandle), &PlatformDisplay::sharedDisplayForCompositing()); + if (!m_context) + return false; - m_textureMapper = TextureMapperGL::create(); - static_cast<TextureMapperGL*>(m_textureMapper.get())->setEnableEdgeDistanceAntialiasing(true); - toTextureMapperLayer(m_rootLayer.get())->setTextureMapper(m_textureMapper.get()); + if (!m_context->makeContextCurrent()) + return false; - if (m_webPage->hasPageOverlay()) { - PageOverlayList& pageOverlays = m_webPage->pageOverlays(); - PageOverlayList::iterator end = pageOverlays.end(); - for (PageOverlayList::iterator it = pageOverlays.begin(); it != end; ++it) - createPageOverlayLayer(it->get()); - } + // Do not do frame sync when rendering offscreen in the web process to ensure that SwapBuffers never blocks. + // Rendering to the actual screen will happen later anyway since the UI process schedules a redraw for every update, + // the compositor will take care of syncing to vblank. + if (m_surface) + m_context->swapInterval(0); - scheduleLayerFlush(); + return true; } LayerTreeHostGtk::~LayerTreeHostGtk() { - ASSERT(!m_isValid); ASSERT(!m_rootLayer); cancelPendingLayerFlush(); } -const LayerTreeContext& LayerTreeHostGtk::layerTreeContext() -{ - return m_layerTreeContext; -} - -void LayerTreeHostGtk::setShouldNotifyAfterNextScheduledLayerFlush(bool notifyAfterScheduledLayerFlush) -{ - m_notifyAfterScheduledLayerFlush = notifyAfterScheduledLayerFlush; -} - void LayerTreeHostGtk::setRootCompositingLayer(GraphicsLayer* graphicsLayer) { m_nonCompositedContentLayer->removeAllChildren(); @@ -166,7 +206,10 @@ void LayerTreeHostGtk::setRootCompositingLayer(GraphicsLayer* graphicsLayer) void LayerTreeHostGtk::invalidate() { - ASSERT(m_isValid); + // This can trigger destruction of GL objects so let's make sure that + // we have the right active context + if (m_context) + m_context->makeContextCurrent(); cancelPendingLayerFlush(); m_rootLayer = nullptr; @@ -174,28 +217,20 @@ void LayerTreeHostGtk::invalidate() m_textureMapper = nullptr; m_context = nullptr; - m_isValid = false; + LayerTreeHost::invalidate(); + + m_surface = nullptr; } void LayerTreeHostGtk::setNonCompositedContentsNeedDisplay() { m_nonCompositedContentLayer->setNeedsDisplay(); - - PageOverlayLayerMap::iterator end = m_pageOverlayLayers.end(); - for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(); it != end; ++it) - it->value->setNeedsDisplay(); - scheduleLayerFlush(); } void LayerTreeHostGtk::setNonCompositedContentsNeedDisplayInRect(const IntRect& rect) { m_nonCompositedContentLayer->setNeedsDisplayInRect(rect); - - PageOverlayLayerMap::iterator end = m_pageOverlayLayers.end(); - for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(); it != end; ++it) - it->value->setNeedsDisplayInRect(rect); - scheduleLayerFlush(); } @@ -224,88 +259,50 @@ void LayerTreeHostGtk::sizeDidChange(const IntSize& newSize) m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(0, oldSize.height(), newSize.width(), newSize.height() - oldSize.height())); m_nonCompositedContentLayer->setNeedsDisplay(); - PageOverlayLayerMap::iterator end = m_pageOverlayLayers.end(); - for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(); it != end; ++it) - it->value->setSize(newSize); + if (m_surface && m_surface->resize(newSize)) + m_layerTreeContext.contextID = m_surface->surfaceID(); compositeLayersToContext(ForResize); } void LayerTreeHostGtk::deviceOrPageScaleFactorChanged() { + if (m_surface && m_surface->resize(m_webPage.size())) + m_layerTreeContext.contextID = m_surface->surfaceID(); + // Other layers learn of the scale factor change via WebPage::setDeviceScaleFactor. m_nonCompositedContentLayer->deviceOrPageScaleFactorChanged(); -} -void LayerTreeHostGtk::forceRepaint() -{ - scheduleLayerFlush(); + m_scaleMatrix.makeIdentity(); + m_scaleMatrix.scale(m_webPage.deviceScaleFactor() * m_webPage.pageScaleFactor()); + downcast<GraphicsLayerTextureMapper>(*m_rootLayer).layer().setTransform(m_scaleMatrix); } -void LayerTreeHostGtk::didInstallPageOverlay(PageOverlay* pageOverlay) -{ - createPageOverlayLayer(pageOverlay); - scheduleLayerFlush(); -} - -void LayerTreeHostGtk::didUninstallPageOverlay(PageOverlay* pageOverlay) -{ - destroyPageOverlayLayer(pageOverlay); - scheduleLayerFlush(); -} - -void LayerTreeHostGtk::setPageOverlayNeedsDisplay(PageOverlay* pageOverlay, const IntRect& rect) +void LayerTreeHostGtk::forceRepaint() { - GraphicsLayer* layer = m_pageOverlayLayers.get(pageOverlay); - if (!layer) - return; - - layer->setNeedsDisplayInRect(rect); scheduleLayerFlush(); } -void LayerTreeHostGtk::notifyAnimationStarted(const WebCore::GraphicsLayer*, double time) +void LayerTreeHostGtk::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& graphicsContext, GraphicsLayerPaintingPhase, const FloatRect& clipRect) { + if (graphicsLayer == m_nonCompositedContentLayer.get()) + m_webPage.drawRect(graphicsContext, enclosingIntRect(clipRect)); } -void LayerTreeHostGtk::notifyFlushRequired(const WebCore::GraphicsLayer*) +float LayerTreeHostGtk::deviceScaleFactor() const { + return m_webPage.deviceScaleFactor(); } -void LayerTreeHostGtk::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& graphicsContext, GraphicsLayerPaintingPhase, const IntRect& clipRect) -{ - if (graphicsLayer == m_nonCompositedContentLayer.get()) { - m_webPage->drawRect(graphicsContext, clipRect); - return; - } - - for (auto& pageOverlayLayer : m_pageOverlayLayers) { - if (pageOverlayLayer.value.get() == graphicsLayer) { - m_webPage->drawPageOverlay(pageOverlayLayer.key, graphicsContext, clipRect); - break; - } - } -} - -gboolean LayerTreeHostGtk::layerFlushTimerFiredCallback(LayerTreeHostGtk* layerTreeHost) +float LayerTreeHostGtk::pageScaleFactor() const { - layerTreeHost->layerFlushTimerFired(); - return FALSE; + return m_webPage.pageScaleFactor(); } -void LayerTreeHostGtk::layerFlushTimerFired() +bool LayerTreeHostGtk::renderFrame() { - ASSERT(m_layerFlushTimerCallbackId); - m_layerFlushTimerCallbackId = 0; - flushAndRenderLayers(); - - if (toTextureMapperLayer(m_rootLayer.get())->descendantsOrSelfHaveRunningAnimations() && !m_layerFlushTimerCallbackId) { - const double targetFPS = 60; - double nextFlush = std::max((1 / targetFPS) - (currentTime() - m_lastFlushTime), 0.0); - m_layerFlushTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, nextFlush * 1000.0, reinterpret_cast<GSourceFunc>(layerFlushTimerFiredCallback), this, 0); - g_source_set_name_by_id(m_layerFlushTimerCallbackId, "[WebKit] layerFlushTimerFiredCallback"); - } + return downcast<GraphicsLayerTextureMapper>(*m_rootLayer).layer().descendantsOrSelfHaveRunningAnimations(); } bool LayerTreeHostGtk::flushPendingLayerChanges() @@ -313,17 +310,19 @@ bool LayerTreeHostGtk::flushPendingLayerChanges() m_rootLayer->flushCompositingStateForThisLayerOnly(); m_nonCompositedContentLayer->flushCompositingStateForThisLayerOnly(); - PageOverlayLayerMap::iterator end = m_pageOverlayLayers.end(); - for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(); it != end; ++it) - it->value->flushCompositingStateForThisLayerOnly(); + if (!m_webPage.corePage()->mainFrame().view()->flushCompositingStateIncludingSubframes()) + return false; + + if (m_viewOverlayRootLayer) + m_viewOverlayRootLayer->flushCompositingState(FloatRect(FloatPoint(), m_rootLayer->size())); - return m_webPage->corePage()->mainFrame().view()->flushCompositingStateIncludingSubframes(); + downcast<GraphicsLayerTextureMapper>(*m_rootLayer).updateBackingStoreIncludingSubLayers(); + return true; } void LayerTreeHostGtk::compositeLayersToContext(CompositePurpose purpose) { - GLContext* context = glContext(); - if (!context || !context->makeContextCurrent()) + if (!makeContextCurrent()) return; // The window size may be out of sync with the page size at this point, and getting @@ -331,34 +330,38 @@ void LayerTreeHostGtk::compositeLayersToContext(CompositePurpose purpose) // we set the viewport parameters directly from the window size. IntSize contextSize = m_context->defaultFrameBufferSize(); glViewport(0, 0, contextSize.width(), contextSize.height()); - - if (purpose == ForResize) { - glClearColor(1, 1, 1, 0); + if (purpose == ForResize || !m_webPage.drawsBackground()) { + glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); } - m_textureMapper->beginPainting(); - toTextureMapperLayer(m_rootLayer.get())->paint(); + ASSERT(m_textureMapper); + + TextureMapper::PaintFlags paintFlags = 0; + + if (m_surface && m_surface->shouldPaintMirrored()) + paintFlags |= TextureMapper::PaintingMirrored; + + m_textureMapper->beginPainting(paintFlags); + downcast<GraphicsLayerTextureMapper>(*m_rootLayer).layer().paint(); m_textureMapper->endPainting(); - context->swapBuffers(); + m_context->swapBuffers(); } void LayerTreeHostGtk::flushAndRenderLayers() { { RefPtr<LayerTreeHostGtk> protect(this); - m_webPage->layoutIfNeeded(); + m_webPage.layoutIfNeeded(); if (!m_isValid) return; } - GLContext* context = glContext(); - if (!context || !context->makeContextCurrent()) + if (!makeContextCurrent()) return; - m_lastFlushTime = currentTime(); if (!flushPendingLayerChanges()) return; @@ -367,76 +370,59 @@ void LayerTreeHostGtk::flushAndRenderLayers() if (m_notifyAfterScheduledLayerFlush) { // Let the drawing area know that we've done a flush of the layer changes. - static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers(); + m_webPage.drawingArea()->layerHostDidFlushLayers(); m_notifyAfterScheduledLayerFlush = false; } } -void LayerTreeHostGtk::createPageOverlayLayer(PageOverlay* pageOverlay) +void LayerTreeHostGtk::scheduleLayerFlush() { - std::unique_ptr<GraphicsLayer> layer = GraphicsLayer::create(graphicsLayerFactory(), this); -#ifndef NDEBUG - layer->setName("LayerTreeHost page overlay content"); -#endif - - layer->setAcceleratesDrawing(m_webPage->corePage()->settings().acceleratedDrawingEnabled()); - layer->setDrawsContent(true); - layer->setSize(m_webPage->size()); - layer->setShowDebugBorder(m_webPage->corePage()->settings().showDebugBorders()); - layer->setShowRepaintCounter(m_webPage->corePage()->settings().showRepaintCounter()); + if (!m_layerFlushSchedulingEnabled || !m_textureMapper) + return; - m_rootLayer->addChild(layer.get()); - m_pageOverlayLayers.add(pageOverlay, std::move(layer)); + m_renderFrameScheduler.start(); } -void LayerTreeHostGtk::destroyPageOverlayLayer(PageOverlay* pageOverlay) +void LayerTreeHostGtk::pageBackgroundTransparencyChanged() { - std::unique_ptr<GraphicsLayer> layer = m_pageOverlayLayers.take(pageOverlay); - ASSERT(layer); - - layer->removeFromParent(); + m_nonCompositedContentLayer->setContentsOpaque(m_webPage.drawsBackground()); } -void LayerTreeHostGtk::scheduleLayerFlush() +void LayerTreeHostGtk::cancelPendingLayerFlush() { - if (!m_layerFlushSchedulingEnabled) - return; - - // We use a GLib timer because otherwise GTK+ event handling during dragging can starve WebCore timers, which have a lower priority. - if (!m_layerFlushTimerCallbackId) { - m_layerFlushTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 0, reinterpret_cast<GSourceFunc>(layerFlushTimerFiredCallback), this, 0); - g_source_set_name_by_id(m_layerFlushTimerCallbackId, "[WebKit] layerFlushTimerFiredCallback"); - } + m_renderFrameScheduler.stop(); } -void LayerTreeHostGtk::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled) +void LayerTreeHostGtk::setViewOverlayRootLayer(GraphicsLayer* viewOverlayRootLayer) { - if (m_layerFlushSchedulingEnabled == layerFlushingEnabled) - return; - - m_layerFlushSchedulingEnabled = layerFlushingEnabled; - - if (m_layerFlushSchedulingEnabled) { - scheduleLayerFlush(); - return; - } - - cancelPendingLayerFlush(); + LayerTreeHost::setViewOverlayRootLayer(viewOverlayRootLayer); + if (m_viewOverlayRootLayer) + m_rootLayer->addChild(m_viewOverlayRootLayer); } -void LayerTreeHostGtk::pageBackgroundTransparencyChanged() +void LayerTreeHostGtk::createTextureMapper() { - m_nonCompositedContentLayer->setContentsOpaque(m_webPage->drawsBackground() && !m_webPage->drawsTransparentBackground()); + // The creation of the TextureMapper needs an active OpenGL context. + if (!makeContextCurrent()) + return; + + ASSERT(m_isValid); + ASSERT(!m_textureMapper); + m_textureMapper = TextureMapper::create(); + static_cast<TextureMapperGL*>(m_textureMapper.get())->setEnableEdgeDistanceAntialiasing(true); + downcast<GraphicsLayerTextureMapper>(*m_rootLayer).layer().setTextureMapper(m_textureMapper.get()); } -void LayerTreeHostGtk::cancelPendingLayerFlush() +#if PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW) +void LayerTreeHostGtk::setNativeSurfaceHandleForCompositing(uint64_t handle) { - if (!m_layerFlushTimerCallbackId) - return; + cancelPendingLayerFlush(); + m_layerTreeContext.contextID = handle; - g_source_remove(m_layerFlushTimerCallbackId); - m_layerFlushTimerCallbackId = 0; + createTextureMapper(); + scheduleLayerFlush(); } +#endif } // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.h b/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.h index bb30b0990..e356a3683 100644 --- a/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.h +++ b/Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.h @@ -34,80 +34,83 @@ #include "TextureMapperLayer.h" #include <WebCore/GLContext.h> #include <WebCore/GraphicsLayerClient.h> -#include <wtf/HashMap.h> -#include <wtf/OwnPtr.h> +#include <WebCore/TransformationMatrix.h> +#include <wtf/RunLoop.h> namespace WebKit { -class LayerTreeHostGtk : public LayerTreeHost, WebCore::GraphicsLayerClient { +class AcceleratedSurface; + +class LayerTreeHostGtk final : public LayerTreeHost, WebCore::GraphicsLayerClient { public: - static PassRefPtr<LayerTreeHostGtk> create(WebPage*); + static Ref<LayerTreeHostGtk> create(WebPage&); virtual ~LayerTreeHostGtk(); -protected: - explicit LayerTreeHostGtk(WebPage*); +private: + explicit LayerTreeHostGtk(WebPage&); WebCore::GraphicsLayer* rootLayer() const { return m_rootLayer.get(); } - void initialize(); + // LayerTreeHost + void scheduleLayerFlush() override; + void cancelPendingLayerFlush() override; + void setRootCompositingLayer(WebCore::GraphicsLayer*) override; + void invalidate() override; - // LayerTreeHost. - virtual void invalidate(); - virtual void sizeDidChange(const WebCore::IntSize& newSize); - virtual void deviceOrPageScaleFactorChanged(); - virtual void forceRepaint(); - virtual void setRootCompositingLayer(WebCore::GraphicsLayer*); - virtual void scheduleLayerFlush(); - virtual void setLayerFlushSchedulingEnabled(bool layerFlushingEnabled); - virtual void pageBackgroundTransparencyChanged() override; + void forceRepaint() override; + void sizeDidChange(const WebCore::IntSize& newSize) override; + void deviceOrPageScaleFactorChanged() override; + void pageBackgroundTransparencyChanged() override; -private: - // LayerTreeHost. - virtual const LayerTreeContext& layerTreeContext(); - virtual void setShouldNotifyAfterNextScheduledLayerFlush(bool); + void setNonCompositedContentsNeedDisplay() override; + void setNonCompositedContentsNeedDisplayInRect(const WebCore::IntRect&) override; + void scrollNonCompositedContents(const WebCore::IntRect& scrollRect) override; + void setViewOverlayRootLayer(WebCore::GraphicsLayer*) override; + +#if PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW) + void setNativeSurfaceHandleForCompositing(uint64_t) override; +#endif + + class RenderFrameScheduler { + public: + RenderFrameScheduler(std::function<bool()>); + ~RenderFrameScheduler(); - virtual void setNonCompositedContentsNeedDisplay() override; - virtual void setNonCompositedContentsNeedDisplayInRect(const WebCore::IntRect&) override; - virtual void scrollNonCompositedContents(const WebCore::IntRect& scrollRect); + void start(); + void stop(); - virtual void didInstallPageOverlay(PageOverlay*) override; - virtual void didUninstallPageOverlay(PageOverlay*) override; - virtual void setPageOverlayNeedsDisplay(PageOverlay*, const WebCore::IntRect&) override; + private: + void renderFrame(); + void nextFrame(); - virtual bool flushPendingLayerChanges(); + std::function<bool()> m_renderer; + RunLoop::Timer<RenderFrameScheduler> m_timer; + double m_fireTime { 0 }; + double m_lastImmediateFlushTime { 0 }; + }; // GraphicsLayerClient - virtual void notifyAnimationStarted(const WebCore::GraphicsLayer*, double time); - virtual void notifyFlushRequired(const WebCore::GraphicsLayer*); - virtual void paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& clipRect); - virtual void didCommitChangesForLayer(const WebCore::GraphicsLayer*) const { } + void paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::FloatRect& clipRect) override; + float deviceScaleFactor() const override; + float pageScaleFactor() const override; - void createPageOverlayLayer(PageOverlay*); - void destroyPageOverlayLayer(PageOverlay*); + bool flushPendingLayerChanges(); enum CompositePurpose { ForResize, NotForResize }; void compositeLayersToContext(CompositePurpose = NotForResize); void flushAndRenderLayers(); - void cancelPendingLayerFlush(); - - void layerFlushTimerFired(); - static gboolean layerFlushTimerFiredCallback(LayerTreeHostGtk*); - - WebCore::GLContext* glContext(); + bool renderFrame(); + bool makeContextCurrent(); + void createTextureMapper(); - LayerTreeContext m_layerTreeContext; - bool m_isValid; - bool m_notifyAfterScheduledLayerFlush; std::unique_ptr<WebCore::GraphicsLayer> m_rootLayer; std::unique_ptr<WebCore::GraphicsLayer> m_nonCompositedContentLayer; - typedef HashMap<PageOverlay*, std::unique_ptr<WebCore::GraphicsLayer>> PageOverlayLayerMap; - PageOverlayLayerMap m_pageOverlayLayers; - OwnPtr<WebCore::TextureMapper> m_textureMapper; - OwnPtr<WebCore::GLContext> m_context; - double m_lastFlushTime; - bool m_layerFlushSchedulingEnabled; - unsigned m_layerFlushTimerCallbackId; + std::unique_ptr<WebCore::TextureMapper> m_textureMapper; + std::unique_ptr<WebCore::GLContext> m_context; + WebCore::TransformationMatrix m_scaleMatrix; + std::unique_ptr<AcceleratedSurface> m_surface; + RenderFrameScheduler m_renderFrameScheduler; }; } // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/PrinterListGtk.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/PrinterListGtk.cpp index 2d54bcc6c..8ddc912f6 100644 --- a/Source/WebKit2/WebProcess/WebPage/gtk/PrinterListGtk.cpp +++ b/Source/WebKit2/WebProcess/WebPage/gtk/PrinterListGtk.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "PrinterListGtk.h" -#ifdef HAVE_GTK_UNIX_PRINTING +#if HAVE(GTK_UNIX_PRINTING) #include <gtk/gtkunixprint.h> @@ -34,27 +34,26 @@ namespace WebKit { PrinterListGtk* PrinterListGtk::s_sharedPrinterList = nullptr; -RefPtr<PrinterListGtk> PrinterListGtk::shared() +RefPtr<PrinterListGtk> PrinterListGtk::getOrCreate() { if (s_sharedPrinterList) - return s_sharedPrinterList; + return s_sharedPrinterList->isEnumeratingPrinters() ? nullptr : s_sharedPrinterList; return adoptRef(new PrinterListGtk); } -gboolean PrinterListGtk::enumeratePrintersFunction(GtkPrinter* printer) -{ - ASSERT(s_sharedPrinterList); - s_sharedPrinterList->addPrinter(printer); - return FALSE; -} - PrinterListGtk::PrinterListGtk() : m_defaultPrinter(nullptr) + , m_enumeratingPrinters(true) { ASSERT(!s_sharedPrinterList); s_sharedPrinterList = this; - gtk_enumerate_printers(reinterpret_cast<GtkPrinterFunc>(&enumeratePrintersFunction), nullptr, nullptr, TRUE); + gtk_enumerate_printers([](GtkPrinter* printer, gpointer) -> gboolean { + ASSERT(s_sharedPrinterList); + s_sharedPrinterList->addPrinter(printer); + return FALSE; + }, nullptr, nullptr, TRUE); + m_enumeratingPrinters = false; } PrinterListGtk::~PrinterListGtk() @@ -81,4 +80,4 @@ GtkPrinter* PrinterListGtk::findPrinter(const char* printerName) const } // namespace WebKit -#endif // HAVE_GTK_UNIX_PRINTING +#endif // HAVE(GTK_UNIX_PRINTING) diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/PrinterListGtk.h b/Source/WebKit2/WebProcess/WebPage/gtk/PrinterListGtk.h index 8d8a952b4..e13cb2995 100644 --- a/Source/WebKit2/WebProcess/WebPage/gtk/PrinterListGtk.h +++ b/Source/WebKit2/WebProcess/WebPage/gtk/PrinterListGtk.h @@ -26,11 +26,11 @@ #ifndef PrinterListGtk_h #define PrinterListGtk_h -#ifdef HAVE_GTK_UNIX_PRINTING +#if HAVE(GTK_UNIX_PRINTING) #include <wtf/RefCounted.h> #include <wtf/Vector.h> -#include <wtf/gobject/GRefPtr.h> +#include <wtf/glib/GRefPtr.h> typedef struct _GtkPrinter GtkPrinter; @@ -38,7 +38,7 @@ namespace WebKit { class PrinterListGtk: public RefCounted<PrinterListGtk> { public: - static RefPtr<PrinterListGtk> shared(); + static RefPtr<PrinterListGtk> getOrCreate(); ~PrinterListGtk(); GtkPrinter* findPrinter(const char*) const; @@ -47,16 +47,17 @@ public: private: PrinterListGtk(); - static gboolean enumeratePrintersFunction(GtkPrinter*); void addPrinter(GtkPrinter*); + bool isEnumeratingPrinters() const { return m_enumeratingPrinters; } Vector<GRefPtr<GtkPrinter>, 4> m_printerList; GtkPrinter* m_defaultPrinter; + bool m_enumeratingPrinters; static PrinterListGtk* s_sharedPrinterList; }; } // namespace WebKit -#endif // HAVE_GTK_UNIX_PRINTING +#endif // HAVE(GTK_UNIX_PRINTING) #endif // WebPrintOperationGtk_h diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/WebInspectorGtk.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/WebInspectorUIGtk.cpp index 5a0ef9e32..a0f1d4852 100644 --- a/Source/WebKit2/WebProcess/WebPage/gtk/WebInspectorGtk.cpp +++ b/Source/WebKit2/WebProcess/WebPage/gtk/WebInspectorUIGtk.cpp @@ -25,9 +25,8 @@ */ #include "config.h" -#include "WebInspector.h" - -#if ENABLE(INSPECTOR) +#include "WebInspectorUI.h" +#include "RemoteWebInspectorUI.h" #include <WebCore/FileSystem.h> #include <glib.h> @@ -35,16 +34,19 @@ namespace WebKit { -bool WebInspector::canSave() const +bool WebInspectorUI::canSave() { return false; } -String WebInspector::localizedStringsURL() const +String WebInspectorUI::localizedStringsURL() { return String("resource:///org/webkitgtk/inspector/Localizations/en.lproj/localizedStrings.js"); } -} // namespace WebKit +String RemoteWebInspectorUI::localizedStringsURL() +{ + return String("resource:///org/webkitgtk/inspector/Localizations/en.lproj/localizedStrings.js"); +} -#endif // ENABLE(INSPECTOR) +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp index 338cf565b..f0e34efdc 100644 --- a/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp +++ b/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp @@ -28,22 +28,26 @@ #include "config.h" #include "WebPage.h" +#include "EditorState.h" #include "NotImplemented.h" #include "WebEvent.h" +#include "WebFrame.h" #include "WebPageAccessibilityObject.h" #include "WebPageProxyMessages.h" +#include "WebProcess.h" #include "WindowsKeyboardCodes.h" #include <WebCore/BackForwardController.h> #include <WebCore/EventHandler.h> #include <WebCore/FocusController.h> #include <WebCore/Frame.h> +#include <WebCore/FrameView.h> #include <WebCore/KeyboardEvent.h> #include <WebCore/Page.h> #include <WebCore/PasteboardHelper.h> #include <WebCore/PlatformKeyboardEvent.h> #include <WebCore/Settings.h> -#include <WebCore/UserAgentGtk.h> -#include <wtf/gobject/GUniquePtr.h> +#include <WebCore/UserAgent.h> +#include <wtf/glib/GUniquePtr.h> using namespace WebCore; @@ -60,10 +64,46 @@ void WebPage::platformInitialize() GUniquePtr<gchar> plugID(atk_plug_get_id(ATK_PLUG(m_accessibilityObject.get()))); send(Messages::WebPageProxy::BindAccessibilityTree(String(plugID.get()))); #endif +} -#if USE(TEXTURE_MAPPER_GL) - m_nativeWindowHandle = 0; -#endif +void WebPage::platformDetach() +{ +} + +void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint shouldIncludePostLayoutData) const +{ + if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::No) { + result.isMissingPostLayoutData = true; + return; + } + + auto& postLayoutData = result.postLayoutData(); + postLayoutData.caretRectAtStart = frame.selection().absoluteCaretBounds(); + + const VisibleSelection& selection = frame.selection().selection(); + if (selection.isNone()) + return; + + const Editor& editor = frame.editor(); + if (selection.isRange()) { + if (editor.selectionHasStyle(CSSPropertyFontWeight, "bold") == TrueTriState) + postLayoutData.typingAttributes |= AttributeBold; + if (editor.selectionHasStyle(CSSPropertyFontStyle, "italic") == TrueTriState) + postLayoutData.typingAttributes |= AttributeItalics; + if (editor.selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline") == TrueTriState) + postLayoutData.typingAttributes |= AttributeUnderline; + if (editor.selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "line-through") == TrueTriState) + postLayoutData.typingAttributes |= AttributeStrikeThrough; + } else if (selection.isCaret()) { + if (editor.selectionStartHasStyle(CSSPropertyFontWeight, "bold")) + postLayoutData.typingAttributes |= AttributeBold; + if (editor.selectionStartHasStyle(CSSPropertyFontStyle, "italic")) + postLayoutData.typingAttributes |= AttributeItalics; + if (editor.selectionStartHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline")) + postLayoutData.typingAttributes |= AttributeUnderline; + if (editor.selectionStartHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "line-through")) + postLayoutData.typingAttributes |= AttributeStrikeThrough; + } } #if HAVE(ACCESSIBILITY) @@ -81,23 +121,12 @@ void WebPage::platformPreferencesDidChange(const WebPreferencesStore&) notImplemented(); } -static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity) -{ - page->focusController().focusedOrMainFrame().eventHandler().scrollRecursively(direction, granularity); -} - bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent) { if (keyboardEvent.type() != WebEvent::KeyDown && keyboardEvent.type() != WebEvent::RawKeyDown) return false; switch (keyboardEvent.windowsVirtualKeyCode()) { - case VK_BACK: - if (keyboardEvent.shiftKey()) - m_page->backForward().goForward(); - else - m_page->backForward().goBack(); - break; case VK_SPACE: scroll(m_page.get(), keyboardEvent.shiftKey() ? ScrollUp : ScrollDown, ScrollByPage); break; @@ -156,19 +185,12 @@ String WebPage::cachedSuggestedFilenameForURL(const URL&) return String(); } -PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const URL&) +RefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const URL&) { notImplemented(); return 0; } -#if USE(TEXTURE_MAPPER_GL) -void WebPage::setAcceleratedCompositingWindowId(int64_t nativeWindowHandle) -{ - m_nativeWindowHandle = nativeWindowHandle; -} -#endif - String WebPage::platformUserAgent(const URL& url) const { if (url.isNull() || !m_page->settings().needsSiteSpecificQuirks()) @@ -177,4 +199,33 @@ String WebPage::platformUserAgent(const URL& url) const return WebCore::standardUserAgentForURL(url); } +#if HAVE(GTK_GESTURES) +void WebPage::getCenterForZoomGesture(const IntPoint& centerInViewCoordinates, IntPoint& result) +{ + result = mainFrameView()->rootViewToContents(centerInViewCoordinates); + double scale = m_page->pageScaleFactor(); + result.scale(1 / scale, 1 / scale); +} +#endif + +void WebPage::setInputMethodState(bool enabled) +{ + if (m_inputMethodEnabled == enabled) + return; + + m_inputMethodEnabled = enabled; + send(Messages::WebPageProxy::SetInputMethodState(enabled)); +} + +void WebPage::collapseSelectionInFrame(uint64_t frameID) +{ + WebFrame* frame = WebProcess::singleton().webFrame(frameID); + if (!frame || !frame->coreFrame()) + return; + + // Collapse the selection without clearing it. + const VisibleSelection& selection = frame->coreFrame()->selection().selection(); + frame->coreFrame()->selection().setBase(selection.extent(), selection.affinity()); +} + } // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp index e79cc75c2..fdd419394 100644 --- a/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp +++ b/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp @@ -40,10 +40,11 @@ #include <WebCore/ResourceError.h> #include <WebCore/URL.h> #include <gtk/gtk.h> +#include <memory> #include <wtf/Vector.h> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GUniquePtr.h> -#ifdef HAVE_GTK_UNIX_PRINTING +#if HAVE(GTK_UNIX_PRINTING) #include "PrinterListGtk.h" #include <cairo-pdf.h> #include <cairo-ps.h> @@ -52,7 +53,7 @@ namespace WebKit { -#ifdef HAVE_GTK_UNIX_PRINTING +#if HAVE(GTK_UNIX_PRINTING) class WebPrintOperationGtkUnix final: public WebPrintOperationGtk { public: WebPrintOperationGtkUnix(WebPage* page, const PrintInfo& printInfo) @@ -66,7 +67,8 @@ public: m_printContext = printContext; m_callbackID = callbackID; - RefPtr<PrinterListGtk> printerList = PrinterListGtk::shared(); + RefPtr<PrinterListGtk> printerList = PrinterListGtk::getOrCreate(); + ASSERT(printerList); const char* printerName = gtk_print_settings_get_printer(m_printSettings.get()); GtkPrinter* printer = printerName ? printerList->findPrinter(printerName) : printerList->defaultPrinter(); if (!printer) { @@ -104,7 +106,7 @@ public: print(surface, 72, 72); } - void startPage(cairo_t* cr) override + void startPage(cairo_t*) override { if (!currentPageIsFirstPageOfSheet()) return; @@ -139,7 +141,7 @@ public: cairo_show_page(cr); } - static void printJobComplete(GtkPrintJob* printJob, WebPrintOperationGtkUnix* printOperation, const GError* error) + static void printJobComplete(GtkPrintJob*, WebPrintOperationGtkUnix* printOperation, const GError* error) { printOperation->printDone(error ? printError(printOperation->frameURL(), error->message) : WebCore::ResourceError()); printOperation->m_printJob = 0; @@ -148,13 +150,13 @@ public: static void printJobFinished(WebPrintOperationGtkUnix* printOperation) { printOperation->deref(); - WebProcess::shared().enableTermination(); + WebProcess::singleton().enableTermination(); } void endPrint() override { // Disable web process termination until the print job finishes. - WebProcess::shared().disableTermination(); + WebProcess::singleton().disableTermination(); cairo_surface_finish(gtk_print_job_get_surface(m_printJob.get(), 0)); // Make sure the operation is alive until the job is sent. @@ -208,6 +210,7 @@ struct PrintPagesData { , firstSheetNumber(0) , numberOfSheets(0) , firstPagePosition(0) + , lastPagePosition(0) , collated(0) , uncollated(0) , isDone(false) @@ -360,7 +363,6 @@ struct PrintPagesData { GRefPtr<GMainLoop> mainLoop; int totalPrinted; - size_t totalToPrint; int pageNumber; Vector<size_t> pages; size_t sheetNumber; @@ -379,11 +381,13 @@ struct PrintPagesData { PassRefPtr<WebPrintOperationGtk> WebPrintOperationGtk::create(WebPage* page, const PrintInfo& printInfo) { -#ifdef HAVE_GTK_UNIX_PRINTING +#if HAVE(GTK_UNIX_PRINTING) return adoptRef(new WebPrintOperationGtkUnix(page, printInfo)); #elif defined(G_OS_WIN32) return adoptRef(new WebPrintOperationGtkWin32(page, printInfo)); #else + UNUSED_PARAM(page); + UNUSED_PARAM(printInfo); return 0; #endif } @@ -695,7 +699,7 @@ void WebPrintOperationGtk::printPagesDone() { m_printPagesIdleId = 0; endPrint(); - m_cairoContext = 0; + m_cairoContext = nullptr; } void WebPrintOperationGtk::printDone(const WebCore::ResourceError& error) @@ -713,7 +717,7 @@ void WebPrintOperationGtk::print(cairo_surface_t* surface, double xDPI, double y { ASSERT(m_printContext); - OwnPtr<PrintPagesData> data = adoptPtr(new PrintPagesData(this)); + auto data = std::make_unique<PrintPagesData>(this); if (!data->isValid) { cairo_surface_finish(surface); printDone(invalidPageRangeToPrint(frameURL())); @@ -729,7 +733,7 @@ void WebPrintOperationGtk::print(cairo_surface_t* surface, double xDPI, double y // operation has finished. See https://bugs.webkit.org/show_bug.cgi?id=122801. unsigned idlePriority = m_printMode == PrintInfo::PrintModeSync ? G_PRIORITY_DEFAULT - 10 : G_PRIORITY_DEFAULT_IDLE + 10; GMainLoop* mainLoop = data->mainLoop.get(); - m_printPagesIdleId = gdk_threads_add_idle_full(idlePriority, printPagesIdle, data.leakPtr(), printPagesIdleDone); + m_printPagesIdleId = gdk_threads_add_idle_full(idlePriority, printPagesIdle, data.release(), printPagesIdleDone); if (m_printMode == PrintInfo::PrintModeSync) { ASSERT(mainLoop); g_main_loop_run(mainLoop); diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h b/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h index c201a2ef9..f5fec106c 100644 --- a/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h +++ b/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h @@ -30,7 +30,7 @@ #include <WebCore/RefPtrCairo.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/gobject/GRefPtr.h> +#include <wtf/glib/GRefPtr.h> typedef struct _GtkPrintSettings GtkPrintSettings; typedef struct _GtkPageSetup GtkPageSetup; |