AcceleratedSurfaceX11.cpp [plain text]
#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, Client& client)
{
if (!downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).supportsXComposite())
return nullptr;
return std::unique_ptr<AcceleratedSurfaceX11>(new AcceleratedSurfaceX11(webPage, client));
}
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, 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);
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();
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;
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());
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;
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 // USE(REDIRECTED_XCOMPOSITE_WINDOW)