Problem mit Gtk4 und GLFW3
-
Hallo alle zusammen,
Ich wollte Einbettung mit GLFW3 Fenster in der Gtk4 Zeichnungsbereich ( DrawingArea )
Gtk4 ist ganz neu und ich verstehe ein bisschen nicht, weil Inhalt der GTK4 Framework zu viel verändert und umgebaut wurde. Ich kenne schon mit GDK-Window bzw gdk_win32_get_window_handle usw... Jetzt sieht GTK4 anders wie GdkSurface und viele neue Klassen.
Ich wollte jetzt mit GTk4 und GL;FW3 zum Einbetten ( to embed )
Ich habe Beuspiel Code von Gtk4 Gitlab herausgeholt und Änderung für Visual Studio 2019 Community ( Via VCPKG )Ihr wwusstet schon , dass Gtk4 unter vcpkg erhalten hat?
Logisch könnt ihr tippen ( Wenn ihr schon vcpkg gemacht habt )vcpkg install gtk:x64-windows --recurse
Es dauert sehr ewig ( ungefähr über 1 bis 2 Stunden oder mehr ) Weil vcpkg mit debug und release zum Vorbereiten, Bauen, Einpacken und Installieren ) sehr viel arbeitet.
Wenn ihr vcpkg bereit ist, dann könnt ihr Visual Studio 2019 oder 2022 Community starten und Includes
Ich zeige euch wie kann ich alle Include Verzeichnisse zum Kompilieren/Bauen
https://i.imgur.com/fJ1mc4X.pngDann schreibe ich ein erstes Fenster für Gtk4:
#include <gtk/gtk.h> void destroy_window(GtkWidget *widget, gpointer data) { gboolean* done = static_cast<gboolean*>(GINT_TO_POINTER(data)); *done = TRUE; g_main_context_wakeup(NULL); } int main(int argc, char* argv[]) { GtkWidget *window,; gtk_init(); gboolean done = FALSE; window = gtk_window_new(); g_signal_connect(window, "destroy", G_CALLBACK(destroy_window), &done); gtk_widget_show(window); while (!done) { g_main_context_iteration(NULL, !done); // Logik wenn ihr etwa coden bzw Aktualisieren ( Update ) oder Machen ( Render ) } return 0; }
Das war alles. Ihr habt verstanden, oder? Bitte merkt
static_cast<type>()
für MSVC / Visual Studio um Kompilieren-Fehler zu vermeiden.
Das ist unterschiedlich zwischen Win32 und Unix Wenn jemand ohne static_cast dann kompiliert es kein Fehler. Das ist unmöglich dass Kompilieren einen Fehler findet oder überhaupt nicht findet.Und ich wollte verstehen weil Win32 für HWND und HGDIOBJ als Konflikt zwingt.
Error: creating glfw_window (process:29928): Gdk-WARNING **: 15:21:59.931: ../src/58ebac2b91-58f2f5c120.clean/gdk/win32/gdksurface-win32.c:4615 window is not a native Win32 window
Das heißt Ich habe genauer gelesen, wie kann ich "native" binden?
GLFW Native Dokumentation ( ENGLISCH )Und ich habe versucht.
#include <stdio.h> #include <gtk/gtk.h> #include <gdk/win32/gdkwin32.h> #include <windows.h> #include <GLFW/glfw3.h> #define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_EXPOSE_NATIVE_WGL #include <GLFW/glfw3native.h> static void set_fullscreen_monitor_cb(GtkWidget* widget, gpointer user_data) { GdkFullscreenMode mode = static_cast<GdkFullscreenMode>(GPOINTER_TO_INT(user_data)); GdkDisplay* display; GdkSurface* surface; GdkMonitor* monitor; GdkToplevelLayout* layout; display = gtk_widget_get_display(widget); surface = gtk_native_get_surface(gtk_widget_get_native(widget)); if (mode == GDK_FULLSCREEN_ON_CURRENT_MONITOR) monitor = gdk_display_get_monitor_at_surface(display, surface); else monitor = NULL; layout = gdk_toplevel_layout_new(); gdk_toplevel_layout_set_resizable(layout, TRUE); gdk_toplevel_layout_set_fullscreen(layout, TRUE, monitor); gdk_toplevel_present(GDK_TOPLEVEL(surface), layout); gdk_toplevel_layout_unref(layout); } static void remove_fullscreen_cb(GtkWidget* widget, gpointer user_data) { GdkSurface* surface; GdkToplevelLayout* layout; surface = gtk_native_get_surface(gtk_widget_get_native(widget)); layout = gdk_toplevel_layout_new(); gdk_toplevel_layout_set_resizable(layout, TRUE); gdk_toplevel_layout_set_fullscreen(layout, FALSE, NULL); gdk_toplevel_present(GDK_TOPLEVEL(surface), layout); gdk_toplevel_layout_unref(layout); } void destroy_window(GtkWidget *widget, gpointer data) { gboolean* done = static_cast<gboolean*>(GINT_TO_POINTER(data)); *done = TRUE; g_main_context_wakeup(NULL); } HGDIOBJ get_window_hwnd(GtkWidget* widget) { return gdk_win32_surface_get_handle(gtk_native_get_surface(gtk_widget_get_native(widget))); } int main(int argc, char* argv[]) { GtkWidget *window, *vbox, *button, *darea; GLFWwindow *glfw_window; gtk_init(); gboolean done = FALSE; window = gtk_window_new(); g_signal_connect(window, "destroy", G_CALLBACK(destroy_window), &done); // <- You have forgot ?? vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_widget_set_valign(vbox, GTK_ALIGN_CENTER); gtk_widget_set_halign(vbox, GTK_ALIGN_CENTER); gtk_widget_set_margin_start(vbox, 5); gtk_widget_set_margin_end(vbox, 5); gtk_box_set_homogeneous(GTK_BOX(vbox), TRUE); gtk_window_set_child(GTK_WINDOW(window), vbox); // Trying embed GLFW in GTk4! Versuche´GLFW-Fenster im Gtk4 einzubetten darea = gtk_drawing_area_new(); gtk_drawing_area_set_content_height(GTK_DRAWING_AREA(darea), 200); gtk_box_append(GTK_BOX(vbox), darea); glfwInit(); glfwDefaultWindowHints(); glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); //glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); glfw_window = glfwCreateWindow(gtk_widget_get_width(darea), gtk_widget_get_height(darea), nullptr, nullptr, nullptr); if (glfw_window == nullptr) { printf("Error: creating glfw_window"); } glfwMakeContextCurrent(glfw_window); // HWND HWND from_gtk_darea = static_cast<HWND>(get_window_hwnd(darea)); SetParent(glfwGetWin32Window(glfw_window), from_gtk_darea); SetWindowPos(glfwGetWin32Window(glfw_window), from_gtk_darea, 0, 0, 0, 0, SWP_SHOWWINDOW); //SetActiveWindow(from_gtk_darea); // End of Embed GLFW3 button = gtk_button_new_with_label("Fullscreen on current monitor"); g_signal_connect(button, "clicked", G_CALLBACK(set_fullscreen_monitor_cb), GINT_TO_POINTER(GDK_FULLSCREEN_ON_CURRENT_MONITOR)); gtk_box_append(GTK_BOX(vbox), button); button = gtk_button_new_with_label("Fullscreen on all monitors"); g_signal_connect(button, "clicked", G_CALLBACK(set_fullscreen_monitor_cb), GINT_TO_POINTER(GDK_FULLSCREEN_ON_ALL_MONITORS)); gtk_box_append(GTK_BOX(vbox), button); button = gtk_button_new_with_label("Un-fullscreen"); g_signal_connect(button, "clicked", G_CALLBACK(remove_fullscreen_cb), NULL); gtk_box_append(GTK_BOX(vbox), button); gtk_widget_show(window); while (!done && !glfwWindowShouldClose(glfw_window)) { g_main_context_iteration(NULL, !done); glfwSwapBuffers(glfw_window); glfwPollEvents(); } glfwTerminate(); return 0; }
Und ich kann nicht ausführen, weil es Fehler nach dem Fertigstellen ausgibt, dass es im Eingabeaufforderungsfenster zeigt:
https://i.imgur.com/QBl1hYV.pngWie kann ich verstehen , dass ich HGDIOBJ zu HWND casten kann. Aber trotzdem , das geht es nicht...
Liebe Grüße!
-
@DeafMan1983 sagte in Problem mit Gtk4 und GLFW3:
HWND from_gtk_darea = static_cast<HWND>(get_window_hwnd(darea));
Probier's mal mit
HWND from_gtk_darea = static_cast<HWND>(get_window_hwnd(window));
Ich meine, die Funktion ist deklariert als
HGDIOBJ gdk_win32_surface_get_handle(GdkSurface *window);
Ich denke der Parametername "window" wird wohl so gemeint sein dass man nur eine
GdkSurface
übergeben darf welche ein Fenster "ist". Und auf eine mitgtk_drawing_area_new
erzeugteGdkSurface
wird das wohl nicht zutreffen.Und was die Funktion
get_window_hwnd
angeht... die sollte besser gleich einHWND
zurückgeben -HGDIOBJ
ist da total unpassend.
(HGDIOBJ
ist für GDI Handles, und ein Win32 Fenster ist halt kein GDI Objekt - d.h. ein Win32 Fenster Handle ist auch kein GDI Handle.)