/** * gdk_window_set_gl_capability: * @window: the #GdkWindow to be used as the rendering area. * @glconfig: a #GdkGLConfig. * @attrib_list: this must be set to NULL or empty (first attribute of None). * * Set the OpenGL-capability to the @window. * This function creates a new #GdkGLWindow held by the @window. * attrib_list is currently unused. This must be set to NULL or empty * (first attribute of None). * * Return value: the #GdkGLWindow used by the @window if it is successful, * NULL otherwise. **/ GdkGLWindow * gdk_window_set_gl_capability (GdkWindow *window, GdkGLConfig *glconfig, const int *attrib_list) { GdkGLWindow *glwindow; GDK_GL_NOTE_FUNC (); g_return_val_if_fail (GDK_IS_WINDOW (window), NULL); g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), NULL); if (quark_gl_window == 0) quark_gl_window = g_quark_from_static_string (quark_gl_window_string); /* If already set */ glwindow = g_object_get_qdata (G_OBJECT (window), quark_gl_window); if (glwindow != NULL) return glwindow; /* * Create GdkGLWindow */ glwindow = gdk_gl_window_new (glconfig, window, attrib_list); if (glwindow == NULL) { g_warning ("cannot create GdkGLWindow\n"); return NULL; } g_object_set_qdata_full (G_OBJECT (window), quark_gl_window, glwindow, (GDestroyNotify) g_object_unref); /* * Set a background of "None" on window to avoid AIX X server crash */ GDK_GL_NOTE (MISC, g_message (" - window->bg_pixmap = %p", (void*)gdk_window_get_background_pattern (window))); gdk_window_set_background_pattern (window, NULL); GDK_GL_NOTE (MISC, g_message (" - window->bg_pixmap = %p", (void*)gdk_window_get_background_pattern (window))); return glwindow; }
static cairo_surface_t * snapshot_widget (GtkWidget *widget, SnapshotMode mode) { cairo_surface_t *surface; cairo_pattern_t *bg; GMainLoop *loop; cairo_t *cr; g_assert (gtk_widget_get_realized (widget)); surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget), CAIRO_CONTENT_COLOR, gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget)); loop = g_main_loop_new (NULL, FALSE); /* We wait until the widget is drawn for the first time. * We can not wait for a GtkWidget::draw event, because that might not * happen if the window is fully obscured by windowed child widgets. * Alternatively, we could wait for an expose event on widget's window. * Both of these are rather hairy, not sure what's best. */ gdk_event_handler_set (check_for_draw, loop, NULL); g_main_loop_run (loop); cr = cairo_create (surface); switch (mode) { case SNAPSHOT_WINDOW: { GdkWindow *window = gtk_widget_get_window (widget); if (gdk_window_get_window_type (window) == GDK_WINDOW_TOPLEVEL || gdk_window_get_window_type (window) == GDK_WINDOW_FOREIGN) { /* give the WM/server some time to sync. They need it. * Also, do use popups instead of toplevls in your tests * whenever you can. */ gdk_display_sync (gdk_window_get_display (window)); g_timeout_add (500, quit_when_idle, loop); g_main_loop_run (loop); } gdk_cairo_set_source_window (cr, window, 0, 0); cairo_paint (cr); } break; case SNAPSHOT_DRAW: bg = gdk_window_get_background_pattern (gtk_widget_get_window (widget)); if (bg) { cairo_set_source (cr, bg); cairo_paint (cr); } gtk_widget_draw (widget, cr); break; default: g_assert_not_reached(); break; } cairo_destroy (cr); g_main_loop_unref (loop); gtk_widget_destroy (widget); return surface; }
static void _gtk_pixel_cache_create_surface_if_needed (GtkPixelCache *cache, GdkWindow *window, cairo_rectangle_int_t *view_rect, cairo_rectangle_int_t *canvas_rect) { cairo_rectangle_int_t rect; int surface_w, surface_h; cairo_content_t content; cairo_pattern_t *bg; double red, green, blue, alpha; content = CAIRO_CONTENT_COLOR_ALPHA; bg = gdk_window_get_background_pattern (window); if (bg != NULL && cairo_pattern_get_type (bg) == CAIRO_PATTERN_TYPE_SOLID && cairo_pattern_get_rgba (bg, &red, &green, &blue, &alpha) == CAIRO_STATUS_SUCCESS && alpha == 1.0) content = CAIRO_CONTENT_COLOR; surface_w = view_rect->width; if (canvas_rect->width > surface_w) surface_w = MIN (surface_w + EXTRA_SIZE, canvas_rect->width); surface_h = view_rect->height; if (canvas_rect->height > surface_h) surface_h = MIN (surface_h + EXTRA_SIZE, canvas_rect->height); /* If current surface can't fit view_rect or is too large, kill it */ if (cache->surface != NULL && (cairo_surface_get_content (cache->surface) != content || cache->surface_w < view_rect->width || cache->surface_w > surface_w + ALLOW_LARGER_SIZE || cache->surface_h < view_rect->height || cache->surface_h > surface_h + ALLOW_LARGER_SIZE || cache->surface_scale != gdk_window_get_scale_factor (window))) { cairo_surface_destroy (cache->surface); cache->surface = NULL; if (cache->surface_dirty) cairo_region_destroy (cache->surface_dirty); cache->surface_dirty = NULL; } /* Don't allocate a surface if view >= canvas, as we won't be scrolling then anyway */ if (cache->surface == NULL && (view_rect->width < canvas_rect->width || view_rect->height < canvas_rect->height)) { cache->surface_x = -canvas_rect->x; cache->surface_y = -canvas_rect->y; cache->surface_w = surface_w; cache->surface_h = surface_h; cache->surface_scale = gdk_window_get_scale_factor (window); cache->surface = gdk_window_create_similar_surface (window, content, surface_w, surface_h); rect.x = 0; rect.y = 0; rect.width = surface_w; rect.height = surface_h; cache->surface_dirty = cairo_region_create_rectangle (&rect); } }