====== GUI programming using GTK ====== //dumping things from my1gtktest_single...// A useful makefile. To compile more.c that uses GTK2 (default is GTK3), run ''make APP_NAME=more GTK_VERS=2.0''. # makefile for simple gtk application written in single c source file ALLAPP = $(subst .c,,$(subst src/,,$(wildcard src/*.c))) ALLAPP += $(subst .c,,$(wildcard *.c)) GTKVER ?= 3.0 CFLAGS += $(shell pkg-config --cflags gtk+-$(GTKVER)) LFLAGS += $(shell pkg-config --libs gtk+-$(GTKVER)) .PHONY: dummy $(TARGET) dummy: @echo @echo "Run 'make ' or 'make GTKVER=2.0'" @echo " = { $(ALLAPP) }" @echo %: %.c gcc -Wall $(CFLAGS) -o $@ $+ $(LFLAGS) clean: rm -rf $(ALLAPP) ===== Sample Codes ===== /*----------------------------------------------------------------------------*/ #include /*----------------------------------------------------------------------------*/ void tray_icon_on_click(GtkStatusIcon *status_icon, gpointer user_data) { printf("Clicked on tray icon\n"); } /*----------------------------------------------------------------------------*/ void tray_icon_on_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data) { printf("Popup menu\n"); gtk_main_quit(); } /*----------------------------------------------------------------------------*/ static GtkStatusIcon *create_tray_icon() { GtkStatusIcon *tray_icon; tray_icon = gtk_status_icon_new(); g_signal_connect(G_OBJECT(tray_icon), "activate", G_CALLBACK(tray_icon_on_click), NULL); g_signal_connect(G_OBJECT(tray_icon), "popup-menu", G_CALLBACK(tray_icon_on_menu), NULL); gtk_status_icon_set_from_icon_name(tray_icon, GTK_STOCK_MEDIA_STOP); gtk_status_icon_set_tooltip(tray_icon, "Example Tray Icon"); gtk_status_icon_set_visible(tray_icon, TRUE); return tray_icon; } /*----------------------------------------------------------------------------*/ int main(int argc, char **argv) { GtkStatusIcon *tray_icon; gtk_init(&argc, &argv); tray_icon = create_tray_icon(); printf("embedded: "); if (!gtk_status_icon_is_embedded(tray_icon)) { printf("yes\n"); gtk_main(); printf("done\n"); } else { printf("no\nCannot embed tray icon - aborting!\n"); } return 0; } /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ #include /** * From, * https://developer.gnome.org/gtk3/stable/ch01s05.html * * - my rewrite to understand these new gtk3 stuffs (cairo surface! :o) **/ /*----------------------------------------------------------------------------*/ #define MY1APP_FULL "org.my1.gtktest" #define MY1APP_NAME "GTK Test" /*----------------------------------------------------------------------------*/ typedef struct _my1gtk_app_t { int stat; cairo_surface_t *surf; GtkApplication *main; GtkWidget *gwin; GtkWidget *view; GtkWidget *draw; } my1gtk_app_t; /*----------------------------------------------------------------------------*/ void my1gtk_app_destroy(gpointer data) { my1gtk_app_t* gapp = (my1gtk_app_t*)data; if (gapp->surf) cairo_surface_destroy(gapp->surf); } /*----------------------------------------------------------------------------*/ gboolean my1gtk_app_draw_cb(GtkWidget *widget,cairo_t *cr,gpointer data) { my1gtk_app_t* gapp = (my1gtk_app_t*)data; cairo_set_source_surface(cr,gapp->surf,0,0); cairo_paint(cr); return FALSE; } /*----------------------------------------------------------------------------*/ void clear_surface(my1gtk_app_t* gapp) { cairo_t *cr = cairo_create(gapp->surf); cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint(cr); cairo_destroy(cr); } /*----------------------------------------------------------------------------*/ gboolean my1gtk_app_conf_cb(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { my1gtk_app_t* gapp = (my1gtk_app_t*)data; if (gapp->surf) cairo_surface_destroy(gapp->surf); gapp->surf = 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)); clear_surface(gapp); return TRUE; } /*----------------------------------------------------------------------------*/ void draw_brush(GtkWidget *widget, gdouble x, gdouble y, gpointer data) { my1gtk_app_t* gapp = (my1gtk_app_t*)data; cairo_t *cr = cairo_create (gapp->surf); cairo_rectangle (cr,x-3,y-3,6,6); cairo_fill (cr); cairo_destroy (cr); gtk_widget_queue_draw_area(widget,x-3,y-3,6,6); } /*----------------------------------------------------------------------------*/ gboolean my1gtk_app_motion_cb(GtkWidget *widget, GdkEventMotion *event, gpointer data) { my1gtk_app_t* gapp = (my1gtk_app_t*)data; if (!gapp->surf) return FALSE; if (event->state&GDK_BUTTON1_MASK) draw_brush(widget,event->x,event->y,data); return TRUE; } /*----------------------------------------------------------------------------*/ gboolean my1gtk_app_bpress_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) { my1gtk_app_t* gapp = (my1gtk_app_t*)data; if (!gapp->surf) return FALSE; if (event->button == GDK_BUTTON_PRIMARY) draw_brush (widget,event->x,event->y,data); else if (event->button == GDK_BUTTON_SECONDARY) { clear_surface(gapp); gtk_widget_queue_draw(widget); } return TRUE; } /*----------------------------------------------------------------------------*/ void my1gtk_app_activate(GtkApplication *app, gpointer data) { my1gtk_app_t* gapp = (my1gtk_app_t*)data; /** app === gapp->main! assert?*/ gapp->gwin = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(gapp->gwin),MY1APP_NAME); g_signal_connect_swapped(gapp->gwin,"destroy", G_CALLBACK(my1gtk_app_destroy),data); gtk_container_set_border_width(GTK_CONTAINER(gapp->gwin),4); gapp->view = gtk_frame_new(0x0); gtk_frame_set_shadow_type(GTK_FRAME(gapp->view),GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(gapp->gwin),gapp->view); gapp->draw = gtk_drawing_area_new(); /* set a minimum size */ gtk_widget_set_size_request(gapp->draw,100,100); gtk_container_add(GTK_CONTAINER(gapp->view),gapp->draw); g_signal_connect(gapp->draw,"draw", G_CALLBACK(my1gtk_app_draw_cb),data); g_signal_connect(gapp->draw,"configure-event", G_CALLBACK(my1gtk_app_conf_cb),data); g_signal_connect(gapp->draw,"motion-notify-event", G_CALLBACK(my1gtk_app_motion_cb),data); g_signal_connect(gapp->draw,"button-press-event", G_CALLBACK(my1gtk_app_bpress_cb),data); gtk_widget_set_events(gapp->draw,gtk_widget_get_events(gapp->draw) | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); gtk_widget_show_all(gapp->gwin); } /*----------------------------------------------------------------------------*/ void my1gtk_app_init(my1gtk_app_t* gapp) { gapp->stat = 0; gapp->surf = 0x0; gapp->main = gtk_application_new(MY1APP_FULL,G_APPLICATION_FLAGS_NONE); g_signal_connect(gapp->main,"activate", G_CALLBACK(my1gtk_app_activate),(gpointer)gapp); } /*----------------------------------------------------------------------------*/ void my1gtk_app_exec(my1gtk_app_t* gapp, int argc, char* argv[]) { gapp->stat = g_application_run(G_APPLICATION(gapp->main),argc,argv); g_object_unref(gapp->main); } /*----------------------------------------------------------------------------*/ int main (int argc, char **argv) { my1gtk_app_t gapp; my1gtk_app_init(&gapp); my1gtk_app_exec(&gapp,argc,argv); return gapp.stat; } /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ #include /*----------------------------------------------------------------------------*/ #define MY1APP_FULL "org.my1.gtktest" #define MY1APP_NAME "GTK Test" /*----------------------------------------------------------------------------*/ GtkCssProvider *ccss; /*----------------------------------------------------------------------------*/ gboolean on_show_resize(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data) { char test[] = "GtkLabel { background-color: #AAAAAA; font-size: %.0fpx; }"; char buff[128]; snprintf(buff,128,test,((float)allocation->height*12.0/40.0)); printf("Resize: %d x %d => %s\n",allocation->width,allocation->height,buff); gtk_css_provider_load_from_data(ccss,buff, -1, NULL); /** my1image_view_t* view = (my1image_view_t*) user_data; printf("Resize: %d x %d\n",allocation->width,allocation->height); */ return TRUE; } /*----------------------------------------------------------------------------*/ static void activate(GtkApplication* app, gpointer data) { GtkWidget *gwin, *grid, *show; GtkCssProvider *gcss; GdkDisplay *disp; GdkScreen *gscr; gwin = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(gwin),MY1APP_FULL); grid = gtk_grid_new(); gtk_container_add(GTK_CONTAINER(gwin),grid); show = gtk_label_new("HAHA"); gtk_widget_set_hexpand(show,TRUE); gtk_widget_set_halign(show,GTK_ALIGN_FILL); gtk_widget_set_vexpand(show,TRUE); gtk_widget_set_valign(show,GTK_ALIGN_FILL); gtk_grid_attach(GTK_GRID(grid),show,0,0,1,1); gcss = gtk_css_provider_new(); disp = gdk_display_get_default(); gscr = gdk_display_get_default_screen(disp); gtk_style_context_add_provider_for_screen(gscr, GTK_STYLE_PROVIDER(gcss),GTK_STYLE_PROVIDER_PRIORITY_USER); gtk_css_provider_load_from_data(gcss, "GtkLabel { background-color: #AAAAAA;}\n" "GtkGrid { background-color: #4444AA;}", -1, NULL); ccss = gtk_css_provider_new(); gtk_style_context_add_provider_for_screen(gscr, GTK_STYLE_PROVIDER(ccss),GTK_STYLE_PROVIDER_PRIORITY_USER); g_signal_connect(G_OBJECT(show),"size-allocate", G_CALLBACK(on_show_resize),0x0); /**gtk_window_fullscreen(GTK_WINDOW(gwin));*/ gtk_widget_show_all(gwin); } /*----------------------------------------------------------------------------*/ int main(int argc, char **argv) { int stat; GtkApplication *gapp; gapp = gtk_application_new(MY1APP_FULL,G_APPLICATION_FLAGS_NONE); g_signal_connect(gapp,"activate",G_CALLBACK(activate),NULL); stat = g_application_run(G_APPLICATION(gapp),argc,argv); g_object_unref(gapp); return stat; } /*----------------------------------------------------------------------------*/