GtkWidget draw event fired mutliple times - c

I have been scratching my head on Why is below code triggers on-draw callback three times as opposed to just once.
#include <iostream>
#include <gtk/gtk.h>
using namespace std;
void on_draw(){
cout << "drawing"<<endl;
}
int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *drgArea;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
drgArea = gtk_drawing_area_new();
// gtk_widget_set_redraw_on_allocate(drgArea, -1);
gtk_container_add(GTK_CONTAINER(window), drgArea);
gtk_widget_show_all(window);
g_signal_connect(drgArea, "expose-event",
G_CALLBACK(on_draw), NULL);
gtk_main();
return 0;
}

This is probably related to your compositor/window manager.
Using cinnamon [2.0.14] shows 2 redraws when starting up the application (no matter if I use gtk3/3.10.6/"draw" or gtk2/2.24.22/"expose-event").

Related

Need close GTK+ window after execute the function

I am programming on linux program and I am trying to prepare program with GTK+3, but I don't know how close program automatically after execute the function without kill that execute.
the step that i want in my program is:
open gtk window and this window there is button (open Xreader).
press button, it tells system to execute xreader program.
close gtk window automatically without needing to close xreader .
here is my code
#include<stdio.h>
#include<gtk/gtk.h>
static void
open_app(GtkWidget *Widget, gpointer data){
system("xreader");
gtk_main_quit();
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *button1;
gtk_init(&argc, &argv);
/*make window */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*give name to the window*/
gtk_window_set_title(GTK_WINDOW(window), "launcher");
/*make size of window*/
gtk_window_set_default_size(GTK_WINDOW(window), 700, 700);
/*open the window in the meddal*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
button1 = gtk_button_new_with_label("Open Xreader");
gtk_container_add(GTK_CONTAINER(window), button1);
gtk_widget_show_all(window);
g_signal_connect(button1,"clicked",G_CALLBACK(open_app), NULL);
g_signal_connect(window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
everytime trying to execute my program and press the button (open Xreader) gtk not close till close xreader .
You cannot use system here, because according to its documentation, https://man7.org/linux/man-pages/man3/system.3.html
system() returns after the command has been completed.
Since you are using gtk, don't forget library functions provided by glib. It has a bunch of functions related to process and thread handling. For example, you can use GSubprocess class from glib, g_subprocess_new.
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
static void open_app(GtkWidget *Widget, gpointer data) {
g_subprocess_new(G_SUBPROCESS_FLAGS_NONE, NULL, "xreader", NULL);
gtk_main_quit();
}
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *button1;
gtk_init(&argc, &argv);
/*make window */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*give name to the window*/
gtk_window_set_title(GTK_WINDOW(window), "launcher");
/*make size of window*/
gtk_window_set_default_size(GTK_WINDOW(window), 700, 700);
/*open the window in the meddal*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
button1 = gtk_button_new_with_label("Open Xreader");
gtk_container_add(GTK_CONTAINER(window), button1);
gtk_widget_show_all(window);
g_signal_connect(button1, "clicked", G_CALLBACK(open_app), NULL);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}

Creating and storing images with gtk2?

I am having some trouble drawing images with gtk2. I have tried this code:
#include <gtk/gtk.h>
static gboolean button_press_callback (GtkWidget *event_box, GdkEventButton *event, gpointer data)
{
g_print ("Event box clicked at coordinates %f,%f\n",
event->x, event->y);
/* Returning TRUE means we handled the event, so the signal
* emission should be stopped (don't call any further
* callbacks that may be connected). Return FALSE
* to continue invoking callbacks.
*/
return TRUE;
}
static GtkWidget*
create_image (void)
{
GtkWidget *image;
GtkWidget *event_box;
image = gtk_image_new_from_file ("image.png");
}
int main(int argc, char const *argv[])
{
create_image();
return 0;
}
It will not draw any images onscreen, infact I don`t see any window at all. Also, what is the best way to store an image in a variable for future use?
I suggest you to look at the gtk tutorial https://developer.gnome.org/gtk-tutorial/stable/, a lot of things are missing for your code to display here a sample on how to display a simple picture in a window :
#include <gtk/gtk.h>
GtkWidget* create_gui()
{
GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL); // create the application window
GtkWidget *img = gtk_image_new_from_file("image.png"); // image shall be in the same dir
gtk_container_add(GTK_CONTAINER(win), img); // add the image to the window
g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(gtk_main_quit), NULL); // end the application if user close the window
return win;
}
int main(int argc, char** argv) {
GtkWidget* win;
gtk_init(&argc, &argv);
win = create_gui();
gtk_widget_show_all(win); // display the window
gtk_main(); // start the event loop
return 0;
}
BTW, gtk 2 is no longer being maintained, I suggest you start with gtk3 if you can

C: How to replace GtkAlignment function with newer GtkWidget align property

I am a new C programmer coming from Java. After reading some old books and articles, I've written the following code:
#include <gtk/gtk.h>
static void activate(GtkApplication* app, gpointer user_data) {
GtkWidget *window;
GtkWidget *button1;
GtkWidget *box;
box = gtk_alignment_new(0, 0, 0, 0);
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "Calculator");
gtk_window_set_default_size(GTK_WINDOW(window), 300, 400);
gtk_container_add(GTK_CONTAINER(window), box);
button1 = gtk_button_new();
gtk_button_set_label(GTK_BUTTON(button1), "1");
gtk_widget_set_size_request(button1, 40, 30);
gtk_container_add(GTK_CONTAINER(box), button1);
gtk_widget_show_all(window);
}
int main(int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new("me.test.calculator", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
The code compiles and runs correctly. The problem is that gtk_alignment_new is deprecated and I want to get rid of it.
I've tried replacing gtk_alignment_new with:
gtk_widget_set_halign(box, GTK_ALIGN_START);
gtk_widget_set_valign(box, GTK_ALIGN_START);
but the window does not show up when using this method. Thanks.
You want to set the halign/valign properties of the button (and then add the button straight into the window) to achieve the same functional results as your original code. 'box' is no longer needed at all.
Note that a GtkWindow is a GtkBin so only takes a single child: you will need to add additional containers in between to actually make a calculator. Maybe start by adding a GtkGrid as the sole window child and then attach all your buttons into the grid.
Using jku's advice I've written the following code which compiles and runs correctly without using gtk_alignment_new:
#include <gtk/gtk.h>
static void activate(GtkApplication* app, gpointer user_data) {
GtkWidget *window;
GtkWidget *button1;
GtkWidget *fixed;
fixed = gtk_fixed_new();
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "Calculator");
gtk_window_set_default_size(GTK_WINDOW(window), 300, 400);
gtk_container_add(GTK_CONTAINER(window), fixed);
button1 = gtk_button_new();
gtk_button_set_label(GTK_BUTTON(button1), "1");
gtk_widget_set_size_request(button1, 45, 35);
gtk_fixed_put(GTK_FIXED(fixed), button1, 5, 200);
gtk_widget_show_all(window);
}
int main(int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new("me.test.calculator", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
NOTE: I ended up using GtxFixed because the size of the window will be fixed as well.

window always on top using xlib

I'm in the process of creating a gtk2 application which I would like drawn over all other apps at all times, I would rather use xlib to do that if it is possible
here's my code so far:
#include <gtk/gtk.h>
int main(int argc, char **argv)
{
gtk_init(&argc, &argv);
GtkWidget *mainwin;
mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show_all (mainwin);
gtk_main ();
return 0;
}
I'd like to do this in the simplest manner possible
thanks
Yes it is possible and not complicated
#include <gtk/gtk.h>
int main(int argc, char **argv)
{
gtk_init(&argc, &argv);
GtkWidget *mainwin;
mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_keep_above ( (GtkWindow *) mainwin, TRUE);
gtk_widget_show_all (mainwin);
gtk_main ();
return 0;
}
gtk_window_set_keep_above does trick if window manager is cooperative.

Taking a screenshot of a particular window with c/GTK [duplicate]

This question already has an answer here:
save current window as image using gtk#
(1 answer)
Closed 4 years ago.
This is a piece of code which creates a window:
#include <gtk/gtk.h>
static GtkWidget* createWindow()
{
GtkWidget *window;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
gtk_widget_set_name(window, "GtkLauncher");
g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
return window;
}
int main(int argc, char* argv[])
{
GtkWidget *main_window;
gtk_init(&argc, &argv);
if (!g_thread_supported())
g_thread_init(NULL);
main_window = createWindow();
gtk_widget_grab_focus(main_window);
gtk_widget_show_all(main_window);
gtk_main();
return 0;
}
And in here: Convert a GTK python script to C , i got how to take a screenshot.
gdk_get_default_root_window() will give me the screenshot of the desktop.
gdk_screen_get_active_window (gdk_screen_get_default()) will give me the screenshot of any active window.
Is there any way to take the screenshot of the window being created in the code above??
I think this should do it, although you may need to iterate the main loop after showing the window to get it to paint properly, in which case you'll need some more code (I haven't tested this)
#include <unistd.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <cairo.h>
static GtkWidget* createWindow()
{
GtkWidget *window;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
gtk_widget_set_name(window, "GtkLauncher");
g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
return window;
}
int main(int argc, char **argv)
{
gdk_init(&argc, &argv);
GtkWidget *main_window = createWindow();
gtk_widget_show_all(main_window);
// may not need this, it also may not be enough either
while (gtk_events_pending ()) gtk_main_iteration ();
GdkWindow *w = GDK_WINDOW(main_window);
gint width, height;
gdk_drawable_get_size(GDK_DRAWABLE(w), &width, &height);
GdkPixbuf *pb = gdk_pixbuf_get_from_drawable(NULL,
GDK_DRAWABLE(w),
NULL,
0,0,0,0,width,height);
if(pb != NULL) {
gdk_pixbuf_save(pb, "screenshot.png", "png", NULL);
g_print("Screenshot saved to screenshot.png.\n");
} else {
g_print("Unable to get the screenshot.\n");
}
return 0;
}
If it doesn't work you'll have to move the screenshot taking into an event handler that connects to some event (I'm not sure which probably window-state-event then you have to look at the event to figure out when to take the screenshot)

Resources