RedirectedXCompositeWindow::RedirectedXCompositeWindow(const IntSize& size, GLContextNeeded needsContext) : m_size(size) , m_window(0) , m_parentWindow(0) , m_pixmap(0) , m_needsContext(needsContext) , m_surface(0) , m_needsNewPixmapAfterResize(false) , m_damage(0) , m_damageNotifyCallback(0) , m_damageNotifyData(0) { Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); Screen* screen = DefaultScreenOfDisplay(display); // This is based on code from Chromium: src/content/common/gpu/image_transport_surface_linux.cc XSetWindowAttributes windowAttributes; windowAttributes.override_redirect = True; m_parentWindow = XCreateWindow(display, RootWindowOfScreen(screen), WidthOfScreen(screen) + 1, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect, &windowAttributes); XMapWindow(display, m_parentWindow); windowAttributes.event_mask = StructureNotifyMask; windowAttributes.override_redirect = False; m_window = XCreateWindow(display, m_parentWindow, 0, 0, size.width(), size.height(), 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &windowAttributes); XMapWindow(display, m_window); if (getWindowHashMap().isEmpty()) gdk_window_add_filter(0, reinterpret_cast<GdkFilterFunc>(filterXDamageEvent), 0); getWindowHashMap().add(m_window, this); while (1) { XEvent event; XWindowEvent(display, m_window, StructureNotifyMask, &event); if (event.type == MapNotify && event.xmap.window == m_window) break; } XSelectInput(display, m_window, NoEventMask); XCompositeRedirectWindow(display, m_window, CompositeRedirectManual); m_damage = XDamageCreate(display, m_window, XDamageReportNonEmpty); }
RedirectedXCompositeWindow::~RedirectedXCompositeWindow() { ASSERT(m_damage); ASSERT(m_window); ASSERT(m_parentWindow); getWindowHashMap().remove(m_window); if (getWindowHashMap().isEmpty()) gdk_window_remove_filter(0, reinterpret_cast<GdkFilterFunc>(filterXDamageEvent), 0); Display* display = GLContext::sharedX11Display(); XDamageDestroy(display, m_damage); XDestroyWindow(display, m_window); XDestroyWindow(display, m_parentWindow); cleanupPixmapAndPixmapSurface(); }
static GdkFilterReturn filterXDamageEvent(GdkXEvent* gdkXEvent, GdkEvent* event, void*) { XEvent* xEvent = static_cast<XEvent*>(gdkXEvent); if (xEvent->type != gDamageEventBase + XDamageNotify) return GDK_FILTER_CONTINUE; XDamageNotifyEvent* damageEvent = reinterpret_cast<XDamageNotifyEvent*>(xEvent); WindowHashMap& windowHashMap = getWindowHashMap(); WindowHashMap::iterator i = windowHashMap.find(damageEvent->drawable); if (i == windowHashMap.end()) return GDK_FILTER_CONTINUE; i->value->callDamageNotifyCallback(); XDamageSubtract(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), damageEvent->damage, None, None); return GDK_FILTER_REMOVE; }