mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Show the app icon on the macOS Dock via AppKit.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
0397519801
commit
6060a8d874
5 changed files with 97 additions and 6 deletions
|
|
@ -60,6 +60,10 @@ else()
|
||||||
target_link_libraries(maturita PRIVATE PkgConfig::GTK4 m)
|
target_link_libraries(maturita PRIVATE PkgConfig::GTK4 m)
|
||||||
target_compile_options(maturita PRIVATE
|
target_compile_options(maturita PRIVATE
|
||||||
-Wall -Wextra -Wno-deprecated-declarations)
|
-Wall -Wextra -Wno-deprecated-declarations)
|
||||||
|
if(APPLE)
|
||||||
|
target_link_libraries(maturita PRIVATE
|
||||||
|
"-framework AppKit" "-framework Foundation")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# The GTK stylesheet and window icon are loaded at runtime from the working
|
# The GTK stylesheet and window icon are loaded at runtime from the working
|
||||||
|
|
|
||||||
4
Makefile
4
Makefile
|
|
@ -23,6 +23,10 @@ TARGET = maturita.exe
|
||||||
LIBS += -mwindows
|
LIBS += -mwindows
|
||||||
else
|
else
|
||||||
TARGET = maturita
|
TARGET = maturita
|
||||||
|
# macOS Dock icon is set via AppKit (see macos_dock.c).
|
||||||
|
ifeq ($(shell uname -s 2>/dev/null),Darwin)
|
||||||
|
LIBS += -framework AppKit -framework Foundation
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SRC = $(wildcard *.c)
|
SRC = $(wildcard *.c)
|
||||||
|
|
|
||||||
55
macos_dock.c
Normal file
55
macos_dock.c
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include "maturita.h"
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <objc/message.h>
|
||||||
|
#include <objc/runtime.h>
|
||||||
|
|
||||||
|
/* Set the macOS Dock tile icon. GTK's window icon-name is ignored on
|
||||||
|
* Quartz, so we talk to AppKit directly via the Objective-C runtime. */
|
||||||
|
void macos_set_dock_icon(const char *path) {
|
||||||
|
Class nsstring;
|
||||||
|
Class nsimage;
|
||||||
|
Class nsapp;
|
||||||
|
id path_str;
|
||||||
|
id image;
|
||||||
|
id app;
|
||||||
|
|
||||||
|
if (!path || !path[0])
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsstring = objc_getClass("NSString");
|
||||||
|
nsimage = objc_getClass("NSImage");
|
||||||
|
nsapp = objc_getClass("NSApplication");
|
||||||
|
if (!nsstring || !nsimage || !nsapp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
path_str = ((id (*)(Class, SEL, const char *))objc_msgSend)(
|
||||||
|
nsstring, sel_registerName("stringWithUTF8String:"), path);
|
||||||
|
if (!path_str)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* NSImage has -initWithContentsOfFile:, not +imageWithContentsOfFile:. */
|
||||||
|
image = ((id (*)(id, SEL, id))objc_msgSend)(
|
||||||
|
((id (*)(Class, SEL))objc_msgSend)(
|
||||||
|
nsimage, sel_registerName("alloc")),
|
||||||
|
sel_registerName("initWithContentsOfFile:"),
|
||||||
|
path_str);
|
||||||
|
if (!image)
|
||||||
|
return;
|
||||||
|
|
||||||
|
app = ((id (*)(Class, SEL))objc_msgSend)(
|
||||||
|
nsapp, sel_registerName("sharedApplication"));
|
||||||
|
if (!app) {
|
||||||
|
((void (*)(id, SEL))objc_msgSend)(image, sel_registerName("release"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
((void (*)(id, SEL, id))objc_msgSend)(
|
||||||
|
app, sel_registerName("setApplicationIconImage:"), image);
|
||||||
|
((void (*)(id, SEL))objc_msgSend)(image, sel_registerName("release"));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void macos_set_dock_icon(const char *path) {
|
||||||
|
(void)path;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
37
main.c
37
main.c
|
|
@ -185,26 +185,51 @@ static gboolean ui_scale_tick(GtkWidget *w, GdkFrameClock *clock,
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *find_app_icon_file(void) {
|
||||||
|
static const char *paths[] = {
|
||||||
|
ICON_FILE,
|
||||||
|
ICON_THEME_DIR "/hicolor/512x512/apps/" ICON_NAME ".png",
|
||||||
|
ICON_FILE_ALT,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; paths[i]; i++) {
|
||||||
|
if (g_file_test(paths[i], G_FILE_TEST_IS_REGULAR))
|
||||||
|
return paths[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* GTK4 has no gtk_window_set_icon_from_file(); register a local hicolor
|
/* GTK4 has no gtk_window_set_icon_from_file(); register a local hicolor
|
||||||
* theme dir and set the window icon by name instead. */
|
* theme dir and set the window icon by name instead. On macOS the Dock
|
||||||
|
* tile ignores that, so also push the PNG through AppKit. */
|
||||||
static void setup_window_icon(GtkWindow *window) {
|
static void setup_window_icon(GtkWindow *window) {
|
||||||
GtkIconTheme *theme;
|
GtkIconTheme *theme;
|
||||||
static const char *dirs[] = { ICON_THEME_DIR, ICON_THEME_DIR_ALT, NULL };
|
static const char *dirs[] = { ICON_THEME_DIR, ICON_THEME_DIR_ALT, NULL };
|
||||||
|
const char *icon_file;
|
||||||
|
int i;
|
||||||
|
|
||||||
theme = gtk_icon_theme_get_for_display(gdk_display_get_default());
|
theme = gtk_icon_theme_get_for_display(gdk_display_get_default());
|
||||||
for (int i = 0; dirs[i]; i++) {
|
for (i = 0; dirs[i]; i++) {
|
||||||
if (g_file_test(dirs[i], G_FILE_TEST_IS_DIR))
|
if (g_file_test(dirs[i], G_FILE_TEST_IS_DIR))
|
||||||
gtk_icon_theme_add_search_path(theme, dirs[i]);
|
gtk_icon_theme_add_search_path(theme, dirs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gtk_icon_theme_has_icon(theme, ICON_NAME)) {
|
if (gtk_icon_theme_has_icon(theme, ICON_NAME)) {
|
||||||
|
gtk_window_set_default_icon_name(ICON_NAME);
|
||||||
|
gtk_window_set_icon_name(window, ICON_NAME);
|
||||||
|
} else {
|
||||||
g_warning("App icon '%s' not found (tried %s/ and %s/)",
|
g_warning("App icon '%s' not found (tried %s/ and %s/)",
|
||||||
ICON_NAME, ICON_THEME_DIR, ICON_THEME_DIR_ALT);
|
ICON_NAME, ICON_THEME_DIR, ICON_THEME_DIR_ALT);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_window_set_default_icon_name(ICON_NAME);
|
icon_file = find_app_icon_file();
|
||||||
gtk_window_set_icon_name(window, ICON_NAME);
|
if (icon_file)
|
||||||
|
macos_set_dock_icon(icon_file);
|
||||||
|
else
|
||||||
|
g_warning("Dock icon PNG not found (tried %s and %s)",
|
||||||
|
ICON_FILE, ICON_FILE_ALT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void activate(GtkApplication *app, gpointer user_data) {
|
void activate(GtkApplication *app, gpointer user_data) {
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,10 @@
|
||||||
#define CZ_SUBJ 3 /* index of "Český jazyk a literatura" */
|
#define CZ_SUBJ 3 /* index of "Český jazyk a literatura" */
|
||||||
#define CSS_FILE "style.css"
|
#define CSS_FILE "style.css"
|
||||||
#define ICON_NAME "maturita"
|
#define ICON_NAME "maturita"
|
||||||
|
#define ICON_FILE "assets/app-icon.png"
|
||||||
#define ICON_THEME_DIR "assets/icons" /* cwd when run from source tree */
|
#define ICON_THEME_DIR "assets/icons" /* cwd when run from source tree */
|
||||||
#define ICON_THEME_DIR_ALT "icons" /* next to the binary after install */
|
#define ICON_THEME_DIR_ALT "icons" /* next to the binary after install */
|
||||||
|
#define ICON_FILE_ALT "icons/hicolor/512x512/apps/maturita.png"
|
||||||
#define PROGRESS_DIR "progress"
|
#define PROGRESS_DIR "progress"
|
||||||
#define PROGRESS_U1 "progress/unit1.conf"
|
#define PROGRESS_U1 "progress/unit1.conf"
|
||||||
#define PROGRESS_U2 "progress/unit2.conf"
|
#define PROGRESS_U2 "progress/unit2.conf"
|
||||||
|
|
@ -1192,6 +1194,7 @@ GtkWidget *build_net_unit24_exercise_page(void);
|
||||||
GtkWidget *build_net_unit25_exercise_page(void);
|
GtkWidget *build_net_unit25_exercise_page(void);
|
||||||
GtkWidget *build_net_unit26_exercise_page(void);
|
GtkWidget *build_net_unit26_exercise_page(void);
|
||||||
GtkWidget *build_net_unit27_exercise_page(void);
|
GtkWidget *build_net_unit27_exercise_page(void);
|
||||||
|
void macos_set_dock_icon(const char *path);
|
||||||
void activate(GtkApplication *app, gpointer user_data);
|
void activate(GtkApplication *app, gpointer user_data);
|
||||||
int main(int argc, char **argv);
|
int main(int argc, char **argv);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue