7.10.2020
Knihovna GDK představuje relativně nízkoúrovňovou mezivrstvu mezi knihovnou GTK a okenním serverem. To však neznamená že v určitých případech nemůže být použita samostatně, pokud nechceme nebo nemůžeme mít aplikaci závislou na relativně velké a komplexní knihovně GTK a na druhé straně psát uživatelské rozhraní v Xlib nebo xcb nám přijde příliš nízkoúrovňové.
Okno vytvoříme pomocí funkce gdk_window_new, která nám v případě úspěchu vrátí ukazatel na typ GdkWindow. Parametry funkce jsou rodičovské okno, adresa struktury v jejíchž prvcích nastavíme požadované parametry okna a maska ve které určíme, které z parametrů této struktury jsou platné a mají být použity. Po vytvoření okno zobrazíme pomocí funkce gdk_window_show.
GdkWindow* window; /*globální proměnná*/ GdkWindowAttr attributes; gint attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_TITLE | GDK_WA_WMCLASS; if (!gdk_init_check(&argc, &argv)) return EXIT_FAILURE; memset(&attributes, 0, sizeof(attributes)); attributes.window_type = GDK_WINDOW_TOPLEVEL; attributes.x = 100; attributes.y = 50; attributes.event_mask = GDK_ALL_EVENTS_MASK; attributes.width = 440; attributes.height = 480; attributes.title = "GDK základní okno"; attributes.wclass = GDK_INPUT_OUTPUT; gdk_event_handler_set(on_gdk_event, NULL, NULL); window = gdk_window_new(NULL, &attributes, attr_mask); gdk_window_show(window);
Po vytvoření a zobrazení okna musíme realizovat smyčku událostí, ve které aplikace poběží dokud z této smyčky nevyskočíme nebo aplikaci neukončíme "natvrdo". K tomu využijeme knihovnu GLib, nad kterou je GDK postavena. Zbývající kód funkce main bude vypadat následovně.
main_loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(main_loop); g_main_loop_unref(main_loop); return EXIT_SUCCESS;
kde globální proměnná main_loop je definovaná takto:
GMainLoop* main_loop;
Nyní zbývá napsat obslužnou funkci událostí nastavenou ve výše uvedeném kódu funkcí gdk_event_handler_set.
void on_gdk_event(GdkEvent* event, gpointer data) { if (event->type == GDK_EXPOSE) { on_expose((GdkEventExpose*)event); } else if (event->type == GDK_DELETE) { on_end_app(); } }
Jak vidíme, v tomto nejjednodušším případě stačí obsloužit událost překreslení okna (GDK_EXPOSE) a zrušení okna (GDK_DELETE).
Při požadavku na překreslení okna zatím nebudeme nic vykreslovat (to si necháme na další pokračování), ale měli bychom zavolat funkce gdk_window_begin_draw_frame a gdk_window_end_draw_frame, čímž řekneme správci oken (jako je X11) že je okno překresleno.
void on_expose(GdkEventExpose* ev) { if (ev->region == NULL) return; GdkDrawingContext* dc = gdk_window_begin_draw_frame( ev->window, ev->region); gdk_window_end_draw_frame(ev->window, dc); }
V reakci na zrušení hlavního okna aplikace musíme korektně ukončit smyčku událostí, jinak by totiž i po zrušení okna proces zůstal běžet až do jeho ukončení zvenku.
void on_end_app() { gdk_window_destroy(window); g_main_loop_quit(main_loop); }
Tím máme kompletní základ aplikace v GDK. V příštím pokračovaní si ukážeme jak kreslit a vypisovat text do okna a následně si vytvoříme jednoduchý a rychlý prohlížeč obrázků ve stylu programu feh.
Na závěr celý výpis programu, který lze sestavit překladačem GCC následujícím příkazem (pro ladicí sestavení):
gcc gdk-okno.c -Wall -g `pkg-config --cflags --libs gdk-3.0` -ogdk-okno
#include <gdk/gdk.h> GMainLoop* main_loop; GdkWindow* window; void on_end_app() { gdk_window_destroy(window); g_main_loop_quit(main_loop); } void on_expose(GdkEventExpose* ev) { if (ev->region == NULL) return; GdkDrawingContext* dc = gdk_window_begin_draw_frame( ev->window, ev->region); gdk_window_end_draw_frame(ev->window, dc); } void on_gdk_event(GdkEvent* event, gpointer data) { if (event->type == GDK_EXPOSE) { on_expose((GdkEventExpose*)event); } else if (event->type == GDK_DELETE) { on_end_app(); } } int main(int argc, char** argv) { GdkWindowAttr attributes; gint attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_TITLE | GDK_WA_WMCLASS; if (!gdk_init_check(&argc, &argv)) return EXIT_FAILURE; memset(&attributes, 0, sizeof(attributes)); attributes.window_type = GDK_WINDOW_TOPLEVEL; attributes.x = 100; attributes.y = 50; attributes.event_mask = GDK_ALL_EVENTS_MASK; attributes.width = 440; attributes.height = 480; attributes.title = "GDK základní okno"; attributes.wclass = GDK_INPUT_OUTPUT; gdk_event_handler_set(on_gdk_event, NULL, NULL); window = gdk_window_new(NULL, &attributes, attr_mask); gdk_window_show(window); main_loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(main_loop); g_main_loop_unref(main_loop); return EXIT_SUCCESS; }
Školení
Kontakt
739 219 991
live:radekchalupa_1
Nové články