Is this simplification of GTK+ code correct? - c

I found the following GTK+3 code in Zetcode. It creates an animation using the cairo library while displaying an image:
#include <cairo.h>
#include <gtk/gtk.h>
/* compile with
*
* gcc spectrum.c -o spectrum `pkg-config --cflags --libs gtk+-3.0`
*
* */
static void do_drawing(cairo_t *);
struct {
gboolean timer;
cairo_surface_t *image;
cairo_surface_t *surface;
gint img_width;
gint img_height;
} glob;
static void init_vars()
{
glob.image = cairo_image_surface_create_from_png("beckov.png");
glob.img_width = cairo_image_surface_get_width(glob.image);
glob.img_height = cairo_image_surface_get_height(glob.image);
glob.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
glob.img_width, glob.img_height);
glob.timer = TRUE;
}
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
gpointer user_data)
{
do_drawing(cr);
return FALSE;
}
static void do_drawing(cairo_t *cr)
{
cairo_t *ic;
static gint count = 0;
ic = cairo_create(glob.surface);
gint i, j;
for (i = 0; i <= glob.img_height; i+=7) {
for (j = 0 ; j < count; j++) {
cairo_move_to(ic, 0, i+j);
cairo_line_to(ic, glob.img_width, i+j);
}
}
count++;
if (count == 8) glob.timer = FALSE;
cairo_set_source_surface(cr, glob.image, 10, 10);
cairo_mask_surface(cr, glob.surface, 10, 10);
cairo_stroke(ic);
cairo_destroy(ic);
}
static gboolean time_handler(GtkWidget *widget)
{
if (!glob.timer) return FALSE;
gtk_widget_queue_draw(widget);
return TRUE;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *darea;
init_vars();
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER (window), darea);
g_signal_connect(G_OBJECT(darea), "draw",
G_CALLBACK(on_draw_event), NULL);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 325, 250);
gtk_window_set_title(GTK_WINDOW(window), "Spectrum");
g_timeout_add(400, (GSourceFunc) time_handler, (gpointer) window);
gtk_widget_show_all(window);
gtk_main();
cairo_surface_destroy(glob.image);
cairo_surface_destroy(glob.surface);
return 0;
}
I achieve exatly the same result if I remove the do_drawing() function and move its code to the on_draw_event(), like:
#include <cairo.h>
#include <gtk/gtk.h>
/* compile with
*
* gcc spectrum.c -o spectrum `pkg-config --cflags --libs gtk+-3.0`
*
* */
struct {
gboolean timer;
cairo_surface_t *image;
cairo_surface_t *surface;
gint img_width;
gint img_height;
} glob;
static void init_vars()
{
glob.image = cairo_image_surface_create_from_png("beckov.png");
glob.img_width = cairo_image_surface_get_width(glob.image);
glob.img_height = cairo_image_surface_get_height(glob.image);
glob.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
glob.img_width, glob.img_height);
glob.timer = TRUE;
}
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
gpointer user_data)
{
cairo_t *ic;
static gint count = 0;
ic = cairo_create(glob.surface);
gint i, j;
for (i = 0; i <= glob.img_height; i+=7) {
for (j = 0 ; j < count; j++) {
cairo_move_to(ic, 0, i+j);
cairo_line_to(ic, glob.img_width, i+j);
}
}
count++;
if (count == 8) glob.timer = FALSE;
cairo_set_source_surface(cr, glob.image, 10, 10);
cairo_mask_surface(cr, glob.surface, 10, 10);
cairo_stroke(ic);
cairo_destroy(ic);
return FALSE;
}
static gboolean time_handler(GtkWidget *widget)
{
if (!glob.timer) return FALSE;
gtk_widget_queue_draw(widget);
return TRUE;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *darea;
init_vars();
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER (window), darea);
g_signal_connect(G_OBJECT(darea), "draw",
G_CALLBACK(on_draw_event), NULL);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 325, 250);
gtk_window_set_title(GTK_WINDOW(window), "Spectrum");
g_timeout_add(400, (GSourceFunc) time_handler, (gpointer) window);
gtk_widget_show_all(window);
gtk_main();
cairo_surface_destroy(glob.image);
cairo_surface_destroy(glob.surface);
return 0;
}
So... I wonder... Am I missing something here (loss of generality)?
Or was the call to do_drawing() in function on_draw_event() of the original code redundant?
Thanks

Yes. It's correct on compiler's side.
But it's a good practice for functions to solve exactly one task. do_drawing is busy with drawing lines and pixels, on_draw_event is busy with processing events. Probably in this code snippet there is no real reason to make a separate function, but usually on_draw_event would be much more complicated.

Related

How to handle double-click events in GTK+3?

I was wondering how to produce double clicks?
Take the following code that draws lines using single clicks http://zetcode.com/gfx/cairo/basicdrawing/:
#include <cairo.h>
#include <gtk/gtk.h>
static void do_drawing(cairo_t *);
struct {
int count;
double coordx[100];
double coordy[100];
} glob;
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
gpointer user_data)
{
do_drawing(cr);
return FALSE;
}
static void do_drawing(cairo_t *cr)
{
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 0.5);
int i, j;
for (i = 0; i <= glob.count - 1; i++ ) {
for (j = 0; j <= glob.count - 1; j++ ) {
cairo_move_to(cr, glob.coordx[i], glob.coordy[i]);
cairo_line_to(cr, glob.coordx[j], glob.coordy[j]);
}
}
glob.count = 0;
cairo_stroke(cr);
}
static gboolean clicked(GtkWidget *widget, GdkEventButton *event,
gpointer user_data)
{
if (event->button == 1) {
glob.coordx[glob.count] = event->x;
glob.coordy[glob.count++] = event->y;
}
if (event->button == 3) {
gtk_widget_queue_draw(widget);
}
return TRUE;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *darea;
glob.count = 0;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
g_signal_connect(G_OBJECT(darea), "draw",
G_CALLBACK(on_draw_event), NULL);
g_signal_connect(window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(window, "button-press-event",
G_CALLBACK(clicked), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
gtk_window_set_title(GTK_WINDOW(window), "Lines");
gtk_widget_show_all(window);
gtk_main();
return 0;
}
How do I get this program to respond to double clicks events instead of the single clicks?
I cannot find it in this list https://lazka.github.io/pgi-docs/Gtk-3.0/classes/Button.html#Gtk.Button.signals.clicked.
From GdkEventButton:
For double-clicks the order of events will be:
GDK_BUTTON_PRESS
GDK_BUTTON_RELEASE
GDK_BUTTON_PRESS
GDK_2BUTTON_PRESS
GDK_BUTTON_RELEASE
Note that the first click is received just like a normal button press,
while the second click results in a GDK_2BUTTON_PRESS being received
just after the GDK_BUTTON_PRESS.
(...)
For a double click to occur, the second button press must occur within 1/4 of a second of the first.
Each GdkEvent has a GdkEventType field that you can check for GDK_2BUTTON_PRESS or GDK_DOUBLE_BUTTON_PRESS (alias added in 3.6):
a mouse button has been double-clicked (clicked twice within a short
period of time). Note that each click also generates a
GDK_BUTTON_PRESS event.
in button-press-event callback.
#include <gtk/gtk.h>
gboolean clicked(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
{
if(event->type == GDK_DOUBLE_BUTTON_PRESS)
printf("double\n");
return TRUE;
}
int main (int argc, char *argv[])
{
gtk_init (&argc, &argv);
GtkWidget *window;
GtkWidget *label;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
label = gtk_label_new("label");
gtk_container_add(GTK_CONTAINER(window), label);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
g_signal_connect(window, "button-press-event", G_CALLBACK(clicked), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}

GTK3: Resize Image while retaining aspect-ratio

When I'm resizing the GtkWindow, i want the GtkImage to resize as well while keeping the same aspect ratio as before.
I can't find any good examples on how to set this up with GTK3
This is what i've tried so far:
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
GtkAllocation *allocation = g_new0 (GtkAllocation, 1);
gboolean resize_image(GtkWidget *widget, GdkEvent *event, GtkWidget *window) {
GdkPixbuf *pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(widget));
if (pixbuf == NULL) {
g_printerr("Failed to resize image\n");
return 1;
}
gtk_widget_get_allocation(GTK_WIDGET(widget), allocation);
pixbuf = gdk_pixbuf_scale_simple(pixbuf, widget->allocation.width, widget->allocation.height, GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(GTK_IMAGE(widget), pixbuf);
return FALSE;
}
int main(int argc, char **argv) {
GtkWidget *window = NULL;
GtkWidget *image = NULL;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
image = gtk_image_new_from_file("image.jpg");
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(image, "draw", G_CALLBACK(resize_image), (gpointer)window);
gtk_container_add(GTK_CONTAINER(window), image);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
return 0;
}
This code should just resize the Pixbuf to the size of the parent, but it doesn't work, i get these errors:
GdkPixbuf-CRITICAL **: gdk_pixbuf_get_width: assertion 'GDK_IS_PIXBUF
(pixbuf)' failed
GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT
(object)' failed
Even if this code would work, i wouldn't be able to keep the same aspect ratio, how to achieve this?
Thanks in Advance
Well, a trick to do this is using a GtkLayout between the image and the window.
Also, instead of using the draw signal, use the size-allocate signal.
We will load a GdkPixbuf and use it as reference for scaling, otherwise the quality would deteriorate with cumulative 'resizing'.
A simple approach would be:
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
struct _resize_widgets {
GtkWidget *image;
GdkPixbuf *pixbuf;
};
typedef struct _resize_widgets ResizeWidgets;
gboolean resize_image(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data) {
int x,y,w,h;
GdkPixbuf *pxbscaled;
GtkWidget *image = (GtkWidget *) ((ResizeWidgets *) user_data)->image;
GdkPixbuf *pixbuf= (GdkPixbuf *) ((ResizeWidgets *) user_data)->pixbuf;
x = 0;
y = 0;
h = allocation->height;
w = (gdk_pixbuf_get_width(pixbuf) * h) / gdk_pixbuf_get_height(pixbuf);
pxbscaled = gdk_pixbuf_scale_simple(pixbuf, w, h, GDK_INTERP_BILINEAR);
if (w < allocation->width) {
x = (allocation->width - w) / 2;
gtk_layout_move(GTK_LAYOUT(widget), image, x, y);
}
gtk_image_set_from_pixbuf(GTK_IMAGE(image), pxbscaled);
g_object_unref (pxbscaled);
return FALSE;
}
int main(int argc, char **argv) {
GtkWidget *window = NULL;
GtkWidget *image = NULL;
GtkWidget *container = NULL;
GdkPixbuf *pixbuf = NULL;
ResizeWidgets *widgets;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
container = gtk_layout_new(NULL, NULL);
image = gtk_image_new();
pixbuf = gdk_pixbuf_new_from_file ("image.png", NULL);
if (pixbuf == NULL) {
g_printerr("Failed to resize image\n");
return 1;
}
widgets = g_new0(ResizeWidgets, 1);
widgets->image = image;
widgets->pixbuf = pixbuf;
gtk_container_add(GTK_CONTAINER(window), container);
gtk_layout_put(GTK_LAYOUT(container), image, 0, 0);
gtk_widget_set_size_request (GTK_WIDGET(window), 20, 20);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(container, "size-allocate", G_CALLBACK(resize_image), widgets);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
g_object_unref (pixbuf);
g_free(widgets);
return 0;
}
Compile with gcc -o main main.cpkg-config --cflags --libs gtk+-3.0`
This will keep aspect ratio. If that is not desired, then the resize_image callback handler would be:
gboolean resize_image(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data) {
int x,y,w,h;
GdkPixbuf *pxbscaled;
GtkWidget *image = (GtkWidget *) ((ResizeWidgets *) user_data)->image;
GdkPixbuf *pixbuf= (GdkPixbuf *) ((ResizeWidgets *) user_data)->pixbuf;
pxbscaled = gdk_pixbuf_scale_simple(pixbuf, allocation->width, allocation->height, GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(GTK_IMAGE(image), pxbscaled);
g_object_unref (pxbscaled);
return FALSE;
}
This is a simple hack, there are other options obviously, like cairo for drawing or simply checking Eye of Gnome (eog) implementation which is much more complete.

Gtk does not detect the window either in fullscreen or unfullscreen

Here is a piece of my project ... and i have a problem with the fullscreen function:
#include "header.h"
gboolean my_gtk_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
GdkWindow *window = gtk_widget_get_window(widget);
GdkWindowState state = gdk_window_get_state(GDK_WINDOW(window));
switch(event->keyval) {
case GDK_KEY_F11:
if(state == GDK_WINDOW_STATE_FULLSCREEN) {
gtk_window_unfullscreen(GTK_WINDOW(widget));
}
else {
gtk_window_fullscreen(GTK_WINDOW(widget));
}
printf("win_state %d\n", state);
printf("gdk_state %d\n", GDK_WINDOW_STATE_FULLSCREEN);
break;
case GDK_KEY_Escape:
destroy(NULL, NULL);
break;
}
}
int main(int argc, char **argv)
{
GtkWidget *win;
char *s = "In progress";
gtk_init(&argc, &argv);
win = win_principal(win, s, 600, 400, 10);
g_signal_connect(G_OBJECT(win), "key-press-event", G_CALLBACK(my_gtk_key_press_event), NULL);
g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(destroy), NULL);
gtk_widget_show_all(win);
gtk_main();
return 0;
}
When in unfullscreen it prints 128 while in fullscreen it prints 144
And the value of GDK_WINDOW_STATE_FULLSCREEN is equal to 16 ...
how can I solve this problem? Or what is wrong?
GDK_WINDOW_STATE_FULLSCREEN is a bit flag, so, you cannot compare the state directly as you are doing but do a bitwise operation.
Change:
if (state == GDK_WINDOW_STATE_FULLSCREEN)
To:
if (state & GDK_WINDOW_STATE_FULLSCREEN)
Here is your code, without dependencies:
#include <gtk/gtk.h>
gboolean my_gtk_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
GdkWindow *window = gtk_widget_get_window(widget);
GdkWindowState state = gdk_window_get_state(GDK_WINDOW(window));
switch(event->keyval) {
case GDK_KEY_F11:
if (state & GDK_WINDOW_STATE_FULLSCREEN) {
gtk_window_unfullscreen(GTK_WINDOW(widget));
}
else {
gtk_window_fullscreen(GTK_WINDOW(widget));
}
break;
case GDK_KEY_Escape:
gtk_main_quit ();
break;
}
}
int main(int argc, char **argv)
{
GtkWidget *win;
char *s = "In progress";
gtk_init(&argc, &argv);
//win = win_principal(win, s, 600, 400, 10);
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW(win), 640, 400);
g_signal_connect(G_OBJECT(win), "key-press-event", G_CALLBACK(my_gtk_key_press_event), win);
g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(win);
gtk_main();
return 0;
}
Compile with:
gcc -o window window.c `pkg-config --cflags --libs gtk+-3.0`
The window will toggle Fullscreen with F11 and close with Esc.

How catch mouse wheel up/down events using GTK3?

how do I implement mouse wheel up/down events using C GTK3?
I have adapted this code in order to handle mouse scoll events:
#include <cairo.h>
#include <gtk/gtk.h>
static void do_drawing(cairo_t *);
struct {
int count;
double coordx[100];
double coordy[100];
} glob;
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
gpointer user_data)
{
do_drawing(cr);
return FALSE;
}
static void do_drawing(cairo_t *cr)
{
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 0.5);
int i, j;
for (i = 0; i <= glob.count - 1; i++ ) {
for (j = 0; j <= glob.count - 1; j++ ) {
cairo_move_to(cr, glob.coordx[i], glob.coordy[i]);
cairo_line_to(cr, glob.coordx[j], glob.coordy[j]);
}
}
glob.count = 0;
cairo_stroke(cr);
}
static gboolean clicked(GtkWidget *widget, GdkEventButton *event,
gpointer user_data)
{
if (event->button == 1) {
glob.coordx[glob.count] = event->x;
glob.coordy[glob.count++] = event->y;
}
if (event->button == 3) {
gtk_widget_queue_draw(widget);
}
return TRUE;
}
static gboolean mouse_scroll (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
printf("scrolled up! \n");
return TRUE;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *darea;
glob.count = 0;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
gtk_widget_add_events(window, GDK_SCROLL_MASK);
g_signal_connect(G_OBJECT(darea), "draw",
G_CALLBACK(on_draw_event), NULL);
g_signal_connect(window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(window, "button-press-event",
G_CALLBACK(clicked), NULL);
g_signal_connect(window, "scroll-event",
G_CALLBACK(mouse_scroll), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
gtk_window_set_title(GTK_WINDOW(window), "Lines");
gtk_widget_show_all(window);
gtk_main();
return 0;
}
However, this only catches a general mouse event, irrespective of whether the mouse is scrolled up or down. I want to know how can I get it to printf("scrolled up! \n") only when the mouse wheel is scrolled up.
Any ideas?
The *event parameter in mouse_scroll should point to GdkEventScroll structure which has direction member:
GdkScrollDirection direction; the direction to scroll to (one of
GDK_SCROLL_UP, GDK_SCROLL_DOWN, GDK_SCROLL_LEFT,
GDK_SCROLL_RIGHT or GDK_SCROLL_SMOOTH).

How do I make a GTK3 image-in-a-window shrinkable?

I have a simple GTK3 app that displays an image from a file in a window.
When you resize the window, the image is scaled in the expose callback to fit the window.
However, once the window has grown, you can't shrink it again; the resize handles only let you make the window ever bigger.
With GTK2 it was trivial to allow grow and shrink with gtk_window_set_policy(w,1,1,1).
How can the same effect be achieved in GTK3?
Here's the ever-growing code example:
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
gboolean resize_image(GtkWidget *widget, GdkEvent *event, void *data)
{
GdkPixbuf *pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(widget));
if (pixbuf == NULL)
{
g_printerr("Failed to get pixbuf\n");
return 1;
}
pixbuf = gdk_pixbuf_scale_simple(pixbuf,
widget->allocation.width, widget->allocation.height,
GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(GTK_IMAGE(widget), pixbuf);
return FALSE;
}
int main(int argc, char **argv)
{
GtkWidget *window = NULL;
GtkWidget *image = NULL;
if (argc < 2 || argc > 3)
{
g_printerr("Usage: %s <image>\n", argv[0]);
return 1;
}
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
image = gtk_image_new_from_file(argv[1]);
if (image == NULL)
{
g_printerr("Could not open \"%s\"\n", argv[1]);
return 1;
}
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(image, "expose-event", G_CALLBACK(resize_image), NULL);
gtk_container_add(GTK_CONTAINER(window), image);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
return 0;
}
Eric Cecashon on the gtk-list mailing list suggests using a cairo drawing area inside a 1x1 grid container, which works fairly well:
/*
gcc -Wall da_resize.c -o da_resize `pkg-config gtk+-3.0 --cflags --libs`
Tested on Ubuntu16.04, GTK3.18.
*/
#include<gtk/gtk.h>
gboolean draw_picture(GtkWidget *da, cairo_t *cr, gpointer data)
{
gint width=gtk_widget_get_allocated_width(da);
gint height=gtk_widget_get_allocated_height(da);
GdkPixbuf *temp=gdk_pixbuf_scale_simple((GdkPixbuf*)data, width, height, GDK_INTERP_BILINEAR);
gdk_cairo_set_source_pixbuf(cr, temp, 0, 0);
cairo_paint(cr);
g_object_unref(temp);
return FALSE;
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Resize Picture");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
//Needs a valid picture.
GdkPixbuf *pixbuf=gdk_pixbuf_new_from_file(argc>1 ? argv[1] : "image.jpg", NULL);
GtkWidget *da1=gtk_drawing_area_new();
gtk_widget_set_hexpand(da1, TRUE);
gtk_widget_set_vexpand(da1, TRUE);
g_signal_connect(da1, "draw", G_CALLBACK(draw_picture), pixbuf);
GtkWidget *grid=gtk_grid_new();
gtk_grid_attach(GTK_GRID(grid), da1, 0, 0, 1, 1);
gtk_container_add(GTK_CONTAINER(window), grid);
gtk_widget_show_all(window);
gtk_main();
g_object_unref(pixbuf);
return 0;
}

Resources