AcceleratedSurfaceX11.cpp [plain text]
#include "config.h"
#include "AcceleratedSurfaceX11.h"
#if PLATFORM(X11)
#include "WebPage.h"
#include <WebCore/PlatformDisplayX11.h>
#include <WebCore/RefPtrCairo.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xcomposite.h>
#include <cairo-xlib.h>
#if USE(GTK4)
#include <gdk/x11/gdkx.h>
#else
#include <gdk/gdkx.h>
#endif
#include <wtf/RunLoop.h>
namespace WebKit {
using namespace WebCore;
std::unique_ptr<AcceleratedSurfaceX11> AcceleratedSurfaceX11::create(WebPage& webPage, Client& client)
{
if (!downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).supportsXComposite())
return nullptr;
return std::unique_ptr<AcceleratedSurfaceX11>(new AcceleratedSurfaceX11(webPage, client));
}
#if !USE(GTK4)
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());
}
#endif
AcceleratedSurfaceX11::AcceleratedSurfaceX11(WebPage& webPage, Client& client)
: AcceleratedSurface(webPage, client)
, m_display(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native())
{
Screen* screen = DefaultScreenOfDisplay(m_display);
ASSERT(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native() == m_display);
#if USE(GTK4)
auto* visual = WK_XVISUAL(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()));
#else
auto* visual = GDK_VISUAL_XVISUAL(defaultVisual());
#endif
XUniqueColormap colormap(XCreateColormap(m_display, RootWindowOfScreen(screen), visual, AllocNone));
int depth = visual == screen->root_visual ? screen->root_depth : 32;
XSetWindowAttributes windowAttributes;
windowAttributes.override_redirect = True;
windowAttributes.colormap = colormap.get();
windowAttributes.border_pixel = 0;
m_parentWindow = XCreateWindow(m_display,
RootWindowOfScreen(screen),
-1, -1, 1, 1,
0,
depth,
InputOutput,
visual,
CWOverrideRedirect | CWColormap | CWBorderPixel,
&windowAttributes);
XMapWindow(m_display, m_parentWindow.get());
windowAttributes.event_mask = StructureNotifyMask;
windowAttributes.override_redirect = False;
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);
m_window.reset();
m_parentWindow.reset();
}
void AcceleratedSurfaceX11::createPixmap()
{
m_pixmap = XCompositeNameWindowPixmap(m_display, m_window.get());
#if USE(GTK4)
auto* visual = WK_XVISUAL(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()));
#else
auto* visual = GDK_VISUAL_XVISUAL(defaultVisual());
#endif
RefPtr<cairo_surface_t> surface = adoptRef(cairo_xlib_surface_create(m_display, m_pixmap.get(), visual, 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::hostResize(const IntSize& size)
{
if (!AcceleratedSurface::hostResize(size))
return false;
XResizeWindow(m_display, m_window.get(), std::max(1, m_size.width()), std::max(1, m_size.height()));
XFlush(m_display);
RunLoop::main().dispatchAfter(5_s, [pixmap = WTFMove(m_pixmap)] { });
createPixmap();
return true;
}
void AcceleratedSurfaceX11::didRenderFrame()
{
m_client.frameComplete();
}
}
#endif // PLATFORM(X11)