I am trying to take a screenshot of the root window in gtk4. This is how I do it in gtk3--
GdkWindow *root_win = gdk_get_default_root_window();
gint width = gdk_window_get_width(root_win);
gint height = gdk_window_get_height(root_win);
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
width, height);
/*.........................*/
cairo_surface_write_to_png(surface, "image.png");
But gdk_get_default_root_window
function has been removed in gtk4. How to take a screen shot in Gtk4? Please do not recommend x11.
For reference, with GTK 2 & 3 without Cairo:
GdkPixbuf *image = NULL;
int width = 0, height = 0;
#if GTK_CHECK_VERSION (4,0,0)
width = gtk_widget_get_width (window);
height = gtk_widget_get_height (window);
GtkSnapshot *snapshot = gtk_snapshot_new (); // ?
// @todo
#elif GTK_CHECK_VERSION (3,0,0)
GdkWindow *root = gtk_widget_get_window (window);
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
image = gdk_pixbuf_get_from_window (root, 0, 0, width, height);
#else // GTK 2
GdkWindow *root = gtk_widget_get_window (window);
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
image = gdk_pixbuf_get_from_drawable (NULL, root,
gdk_colormap_get_system (), 0, 0, 0, 0, width, height);
#endif
gdk_pixbuf_save (image, "demo.png", "png", NULL, "compression", "9", NULL);
g_object_unref (image);
Since this question existed, I have repeatedly occupied myself with it, because I am also very interested in it. I have gained support here. https://discourse.gnome.org/t/gtk4-screenshot-with-gtksnapshot/27981/3?u=holger The problem is to get a "own" GtkSnapshot, which can then be converted into a GskTexture and printed out accordingly. It is important that the GtkWidget is already drawn.
In this example, I was guided by a contribution from April 2020. https://blog.gtk.org/
#include<gtk/gtk.h>
/* This is the important part */
void demo_snapshot(GtkWidget *widget, GtkSnapshot *snapshot);
void custom_snapshot(GtkWidget *widget) {
GtkSnapshot *snapshot = gtk_snapshot_new();
demo_snapshot(widget, snapshot);
int w = gtk_widget_get_width(widget);
int h = gtk_widget_get_height(widget);
GskRenderNode *node = gtk_snapshot_free_to_node (snapshot);
GskRenderer *renderer = gtk_native_get_renderer (gtk_widget_get_native (widget));
GdkTexture *texture = gsk_renderer_render_texture (renderer,
node,
&GRAPHENE_RECT_INIT (0, 0, w,h ));
gdk_texture_save_to_png (texture, "screenshot.png");
};
/* From here the GtkWidget to be printed begins*/
#define MY_TYPE_WIDGET (my_widget_get_type())
G_DECLARE_FINAL_TYPE (MyWidget, my_widget, MY, WIDGET, GtkWidget)
GtkWidget *my_widget_new();
/*********************************/
struct _MyWidget
{
GtkWidget parent_instance;
};
struct _MyWidgetClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE(MyWidget, my_widget, GTK_TYPE_WIDGET)
void
demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
{
GdkRGBA red, green, yellow, blue;
float w, h;
gdk_rgba_parse (&red, "red");
gdk_rgba_parse (&green, "green");
gdk_rgba_parse (&yellow, "yellow");
gdk_rgba_parse (&blue, "blue");
w = gtk_widget_get_width (widget) / 2.0;
h = gtk_widget_get_height (widget) / 2.0;
gtk_snapshot_append_color (snapshot, &red,
&GRAPHENE_RECT_INIT(0, 0, w, h));
gtk_snapshot_append_color (snapshot, &green,
&GRAPHENE_RECT_INIT(w, 0, w, h));
gtk_snapshot_append_color (snapshot, &yellow,
&GRAPHENE_RECT_INIT(0, h, w, h));
gtk_snapshot_append_color (snapshot, &blue,
&GRAPHENE_RECT_INIT(w, h, w, h));
}
static void click_cb (GtkGestureClick *gesture,
int n_press,
double x,
double y)
{
GtkEventController *controller = GTK_EVENT_CONTROLLER (gesture);
GtkWidget *widget = gtk_event_controller_get_widget (controller);
custom_snapshot(widget);
if (x < gtk_widget_get_width (widget) / 2.0 &&
y < gtk_widget_get_height (widget) / 2.0)
g_print ("red!\n");
else if (x > gtk_widget_get_width (widget) / 2.0 &&
y > gtk_widget_get_height (widget) / 2.0)
g_print ("blue!\n");
else if (x > gtk_widget_get_width (widget) / 2.0 &&
y < gtk_widget_get_height (widget) / 2.0)
g_print ("green!\n");
else if (x < gtk_widget_get_width (widget) / 2.0 &&
y > gtk_widget_get_height (widget) / 2.0)
g_print ("yellow!\n");
};
void
demo_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum_size,
int *natural_size,
int *minimum_baseline,
int *natural_baseline)
{
*minimum_size = 100;
*natural_size = 200;
};
static void my_widget_dispose(GObject *gobject)
{
MyWidget *self = MY_WIDGET(gobject);
G_OBJECT_CLASS (my_widget_parent_class)->dispose (gobject);
};
static void my_widget_class_init (MyWidgetClass *class)
{
G_OBJECT_CLASS(class)->dispose = my_widget_dispose;
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
// no layout manager necessary here
widget_class->snapshot = demo_snapshot;
widget_class->measure = demo_measure;
};
static void my_widget_init (MyWidget *self)
{
GtkGesture *controller = gtk_gesture_click_new ();
g_signal_connect_object (controller, "pressed",
G_CALLBACK (click_cb), NULL,G_CONNECT_DEFAULT);
gtk_widget_add_controller (GTK_WIDGET(self), GTK_EVENT_CONTROLLER(controller));
};
GtkWidget *my_widget_new()
{
MyWidget *self;
self = g_object_new(MY_TYPE_WIDGET,NULL);
return GTK_WIDGET (self);
};
/************************************************************/
static void activate (GtkApplication *app, gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new(app);
GtkWidget *widget = my_widget_new();
gtk_window_set_child(GTK_WINDOW(window),GTK_WIDGET(widget));
gtk_window_present(GTK_WINDOW (window));
};
int main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new("org.gtk.mywidget",
G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect(app, "activate", G_CALLBACK(activate),NULL);
status = g_application_run (G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
Have fun trying.