mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-05 19:08:12 +00:00
Added missing files
This commit is contained in:
229
src/core/unix/SDL_gtk.c
Normal file
229
src/core/unix/SDL_gtk.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
#include "SDL_gtk.h"
|
||||
|
||||
#define SDL_GTK_SYM2_OPTIONAL(ctx, lib, sub, fn, sym) \
|
||||
ctx.sub.fn = (void *)SDL_LoadFunction(lib, #sym)
|
||||
|
||||
#define SDL_GTK_SYM2(ctx, lib, sub, fn, sym) \
|
||||
if (!(ctx.sub.fn = (void *)SDL_LoadFunction(lib, #sym))) { \
|
||||
return SDL_SetError("Could not load GTK functions"); \
|
||||
}
|
||||
|
||||
#define SDL_GTK_SYM_OPTIONAL(ctx, lib, sub, fn) \
|
||||
SDL_GTK_SYM2_OPTIONAL(ctx, lib, sub, fn, sub##_##fn)
|
||||
|
||||
#define SDL_GTK_SYM(ctx, lib, sub, fn) \
|
||||
SDL_GTK_SYM2(ctx, lib, sub, fn, sub##_##fn)
|
||||
|
||||
// we never link directly to gtk
|
||||
static const char *gdk_names[] = {
|
||||
#ifdef SDL_PLATFORM_OPENBSD
|
||||
"libgdk-3.so",
|
||||
#else
|
||||
"libgdk-3.so.0",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *gtk_names[] = {
|
||||
#ifdef SDL_PLATFORM_OPENBSD
|
||||
"libgtk-3.so",
|
||||
#else
|
||||
"libgtk-3.so.0",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static void *libgdk = NULL;
|
||||
static void *libgtk = NULL;
|
||||
|
||||
static SDL_GtkContext gtk;
|
||||
static GMainContext *sdl_main_context;
|
||||
|
||||
gulong signal_connect(gpointer instance, const gchar *detailed_signal, void *c_handler, gpointer data)
|
||||
{
|
||||
return gtk.g.signal_connect_data(instance, detailed_signal, SDL_G_CALLBACK(c_handler), data, NULL, (SDL_GConnectFlags)0);
|
||||
}
|
||||
|
||||
static void QuitGtk(void)
|
||||
{
|
||||
SDL_UnloadObject(libgdk);
|
||||
SDL_UnloadObject(libgtk);
|
||||
|
||||
libgdk = NULL;
|
||||
libgtk = NULL;
|
||||
}
|
||||
|
||||
static void *FindLib(const char **names)
|
||||
{
|
||||
const char **name_ptr = names;
|
||||
void *handle = NULL;
|
||||
|
||||
do {
|
||||
handle = SDL_LoadObject(*name_ptr);
|
||||
} while (*++name_ptr && !handle);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static bool IsGtkInit()
|
||||
{
|
||||
return libgdk != NULL && libgtk != NULL;
|
||||
}
|
||||
|
||||
static bool InitGtk(void)
|
||||
{
|
||||
if (!SDL_GetHintBoolean("SDL_ENABLE_GTK", true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsGtkInit()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
libgdk = FindLib(gdk_names);
|
||||
libgtk = FindLib(gtk_names);
|
||||
|
||||
if (!libgdk || !libgtk) {
|
||||
QuitGtk();
|
||||
return SDL_SetError("Could not load GTK libraries");
|
||||
}
|
||||
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, init_check);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, menu_new);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, separator_menu_item_new);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, menu_item_new_with_label);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, menu_item_set_submenu);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, menu_item_get_label);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, menu_item_set_label);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, menu_shell_append);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, menu_shell_insert);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, check_menu_item_new_with_label);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, check_menu_item_get_active);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, check_menu_item_set_active);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, widget_show);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, widget_destroy);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, widget_get_sensitive);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, widget_set_sensitive);
|
||||
SDL_GTK_SYM(gtk, libgtk, gtk, settings_get_default);
|
||||
|
||||
SDL_GTK_SYM(gtk, libgdk, g, signal_connect_data);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, mkdtemp);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, object_ref);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, object_ref_sink);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, object_unref);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, object_get);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, signal_handler_disconnect);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_push_thread_default);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_pop_thread_default);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_new);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_acquire);
|
||||
SDL_GTK_SYM(gtk, libgdk, g, main_context_iteration);
|
||||
|
||||
gtk.g.signal_connect = signal_connect;
|
||||
|
||||
if (gtk.gtk.init_check(0, NULL) == GTK_FALSE) {
|
||||
QuitGtk();
|
||||
return SDL_SetError("Could not init GTK");
|
||||
}
|
||||
|
||||
sdl_main_context = gtk.g.main_context_new();
|
||||
if (!sdl_main_context) {
|
||||
QuitGtk();
|
||||
return SDL_SetError("Could not create GTK context");
|
||||
}
|
||||
|
||||
if (!gtk.g.main_context_acquire(sdl_main_context)) {
|
||||
QuitGtk();
|
||||
return SDL_SetError("Could not acquire GTK context");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static SDL_InitState gtk_init;
|
||||
|
||||
bool SDL_Gtk_Init(void)
|
||||
{
|
||||
static bool is_gtk_available = true;
|
||||
|
||||
if (!is_gtk_available) {
|
||||
return false; // don't keep trying if this fails.
|
||||
}
|
||||
|
||||
if (SDL_ShouldInit(>k_init)) {
|
||||
if (InitGtk()) {
|
||||
SDL_SetInitialized(>k_init, true);
|
||||
} else {
|
||||
is_gtk_available = false;
|
||||
SDL_SetInitialized(>k_init, true);
|
||||
SDL_Gtk_Quit();
|
||||
}
|
||||
}
|
||||
|
||||
return IsGtkInit();
|
||||
}
|
||||
|
||||
void SDL_Gtk_Quit(void)
|
||||
{
|
||||
if (!SDL_ShouldQuit(>k_init)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QuitGtk();
|
||||
SDL_zero(gtk);
|
||||
sdl_main_context = NULL;
|
||||
|
||||
SDL_SetInitialized(>k_init, false);
|
||||
}
|
||||
|
||||
SDL_GtkContext *SDL_Gtk_GetContext(void)
|
||||
{
|
||||
return IsGtkInit() ? >k : NULL;
|
||||
}
|
||||
|
||||
SDL_GtkContext *SDL_Gtk_EnterContext(void)
|
||||
{
|
||||
SDL_Gtk_Init();
|
||||
|
||||
if (IsGtkInit()) {
|
||||
gtk.g.main_context_push_thread_default(sdl_main_context);
|
||||
return >k;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SDL_Gtk_ExitContext(SDL_GtkContext *ctx)
|
||||
{
|
||||
if (ctx) {
|
||||
ctx->g.main_context_pop_thread_default(sdl_main_context);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_UpdateGtk(void)
|
||||
{
|
||||
if (IsGtkInit()) {
|
||||
gtk.g.main_context_iteration(sdl_main_context, GTK_FALSE);
|
||||
}
|
||||
}
|
123
src/core/unix/SDL_gtk.h
Normal file
123
src/core/unix/SDL_gtk.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_gtk_h_
|
||||
#define SDL_gtk_h_
|
||||
|
||||
/* Glib 2.0 */
|
||||
|
||||
typedef unsigned long gulong;
|
||||
typedef void *gpointer;
|
||||
typedef char gchar;
|
||||
typedef int gint;
|
||||
typedef unsigned int guint;
|
||||
typedef double gdouble;
|
||||
typedef gint gboolean;
|
||||
typedef void (*GCallback)(void);
|
||||
typedef struct _GClosure GClosure;
|
||||
typedef void (*GClosureNotify) (gpointer data, GClosure *closure);
|
||||
typedef gboolean (*GSourceFunc) (gpointer user_data);
|
||||
|
||||
typedef struct _GParamSpec GParamSpec;
|
||||
typedef struct _GMainContext GMainContext;
|
||||
|
||||
typedef enum SDL_GConnectFlags
|
||||
{
|
||||
SDL_G_CONNECT_DEFAULT = 0,
|
||||
SDL_G_CONNECT_AFTER = 1 << 0,
|
||||
SDL_G_CONNECT_SWAPPED = 1 << 1
|
||||
} SDL_GConnectFlags;
|
||||
|
||||
#define SDL_G_CALLBACK(f) ((GCallback) (f))
|
||||
#define SDL_G_TYPE_CIC(ip, gt, ct) ((ct*) ip)
|
||||
#define SDL_G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (SDL_G_TYPE_CIC ((instance), (g_type), c_type))
|
||||
|
||||
#define GTK_FALSE 0
|
||||
#define GTK_TRUE 1
|
||||
|
||||
|
||||
/* GTK 3.0 */
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
typedef struct _GtkMenuItem GtkMenuItem;
|
||||
typedef struct _GtkMenuShell GtkMenuShell;
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkCheckMenuItem GtkCheckMenuItem;
|
||||
typedef struct _GtkSettings GtkSettings;
|
||||
|
||||
#define GTK_MENU_ITEM(obj) (SDL_G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_MENU_ITEM, GtkMenuItem))
|
||||
#define GTK_WIDGET(widget) (SDL_G_TYPE_CHECK_INSTANCE_CAST ((widget), GTK_TYPE_WIDGET, GtkWidget))
|
||||
#define GTK_CHECK_MENU_ITEM(obj) (SDL_G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CHECK_MENU_ITEM, GtkCheckMenuItem))
|
||||
#define GTK_MENU(obj) (SDL_G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_MENU, GtkMenu))
|
||||
|
||||
|
||||
typedef struct SDL_GtkContext
|
||||
{
|
||||
/* Glib 2.0 */
|
||||
struct
|
||||
{
|
||||
gulong (*signal_connect)(gpointer instance, const gchar *detailed_signal, void *c_handler, gpointer data);
|
||||
gulong (*signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, SDL_GConnectFlags connect_flags);
|
||||
void (*object_unref)(gpointer object);
|
||||
gchar *(*mkdtemp)(gchar *template);
|
||||
gpointer (*object_ref_sink)(gpointer object);
|
||||
gpointer (*object_ref)(gpointer object);
|
||||
void (*object_get)(gpointer object, const gchar *first_property_name, ...);
|
||||
void (*signal_handler_disconnect)(gpointer instance, gulong handler_id);
|
||||
void (*main_context_push_thread_default)(GMainContext *context);
|
||||
void (*main_context_pop_thread_default)(GMainContext *context);
|
||||
GMainContext *(*main_context_new)(void);
|
||||
gboolean (*main_context_acquire)(GMainContext *context);
|
||||
gboolean (*main_context_iteration)(GMainContext *context, gboolean may_block);
|
||||
} g;
|
||||
|
||||
/* GTK 3.0 */
|
||||
struct
|
||||
{
|
||||
gboolean (*init_check)(int *argc, char ***argv);
|
||||
GtkWidget *(*menu_new)(void);
|
||||
GtkWidget *(*separator_menu_item_new)(void);
|
||||
GtkWidget *(*menu_item_new_with_label)(const gchar *label);
|
||||
void (*menu_item_set_submenu)(GtkMenuItem *menu_item, GtkWidget *submenu);
|
||||
GtkWidget *(*check_menu_item_new_with_label)(const gchar *label);
|
||||
void (*check_menu_item_set_active)(GtkCheckMenuItem *check_menu_item, gboolean is_active);
|
||||
void (*widget_set_sensitive)(GtkWidget *widget, gboolean sensitive);
|
||||
void (*widget_show)(GtkWidget *widget);
|
||||
void (*menu_shell_append)(GtkMenuShell *menu_shell, GtkWidget *child);
|
||||
void (*menu_shell_insert)(GtkMenuShell *menu_shell, GtkWidget *child, gint position);
|
||||
void (*widget_destroy)(GtkWidget *widget);
|
||||
const gchar *(*menu_item_get_label)(GtkMenuItem *menu_item);
|
||||
void (*menu_item_set_label)(GtkMenuItem *menu_item, const gchar *label);
|
||||
gboolean (*check_menu_item_get_active)(GtkCheckMenuItem *check_menu_item);
|
||||
gboolean (*widget_get_sensitive)(GtkWidget *widget);
|
||||
GtkSettings *(*settings_get_default)(void);
|
||||
} gtk;
|
||||
} SDL_GtkContext;
|
||||
|
||||
extern bool SDL_Gtk_Init(void);
|
||||
extern void SDL_Gtk_Quit(void);
|
||||
extern SDL_GtkContext *SDL_Gtk_EnterContext(void);
|
||||
extern void SDL_Gtk_ExitContext(SDL_GtkContext *gtk);
|
||||
extern void SDL_UpdateGtk(void);
|
||||
|
||||
#endif // SDL_gtk_h_
|
Reference in New Issue
Block a user