Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
osx.mm
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2011 Henrik Andersson.
4 Copyright (C) 2010 johannes hanika.
5 Copyright (C) 2010 Pascal de Bruijn.
6 Copyright (C) 2012 Richard Wonka.
7 Copyright (C) 2013-2014 Jérémy Rosen.
8 Copyright (C) 2014-2021 parafin.
9 Copyright (C) 2014 Tobias Ellinghaus.
10 Copyright (C) 2015 Pedro Côrte-Real.
11 Copyright (C) 2020 Hubert Kowalski.
12 Copyright (C) 2020 Pascal Obry.
13 Copyright (C) 2022, 2025 Aurélien PIERRE.
14 Copyright (C) 2023 lologor.
15 Copyright (C) 2024 Alynx Zhou.
16
17 darktable is free software: you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation, either version 3 of the License, or
20 (at your option) any later version.
21
22 darktable is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with darktable. If not, see <http://www.gnu.org/licenses/>.
29*/
30
31/* workaround to fix issue #12720 */
32#define _DARWIN_C_SOURCE
33
34#include "system/macros.h"
35#include "system/mem_alloc.h"
36#include <Carbon/Carbon.h>
37#include <ApplicationServices/ApplicationServices.h>
38#include <CoreServices/CoreServices.h>
39#include <AppKit/AppKit.h>
40#include <gtk/gtk.h>
41#include <gdk/gdkquartz.h>
42#include <gio/gio.h>
43#include <glib.h>
44#include <string.h>
45#ifdef MAC_INTEGRATION
46#include <gtkosxapplication.h>
47#endif
48#ifdef HAVE_P11KIT
49#define P11_KIT_FUTURE_UNSTABLE_API
50#include <p11-kit/p11-kit.h>
51#endif
52#include "osx.h"
53#include "libintl.h"
54
56{
57#if 0
58 GdkScreen *screen = gtk_widget_get_screen(widget);
59 if(!screen)
60 screen = gdk_screen_get_default();
61 if(!screen)
62 return;
63
64 CGDirectDisplayID id = CGMainDisplayID();
65 CGSize size_in_mm = CGDisplayScreenSize(id);
66 int width = CGDisplayPixelsWide(id);
67 int height = CGDisplayPixelsHigh(id);
68 gdk_screen_set_resolution(screen,
69 25.4 * sqrt(width * width + height * height)
70 / sqrt(size_in_mm.width * size_in_mm.width + size_in_mm.height * size_in_mm.height));
71#endif
72}
73
75{
76 @autoreleasepool
77 {
78 NSScreen *nsscreen = [NSScreen mainScreen];
79 if([nsscreen respondsToSelector: NSSelectorFromString(@"backingScaleFactor")])
80 {
81 return [[nsscreen valueForKey: @"backingScaleFactor"] floatValue];
82 }
83 else
84 {
85 return [[nsscreen valueForKey: @"userSpaceScaleFactor"] floatValue];
86 }
87 }
88}
89
91{
92#ifdef GDK_WINDOWING_QUARTZ
93 @autoreleasepool
94 {
95 GdkWindow *window = gtk_widget_get_window(widget);
96 if(window)
97 {
98 NSWindow *native = gdk_quartz_window_get_nswindow(window);
99 [native setCollectionBehavior: ([native collectionBehavior] & ~NSWindowCollectionBehaviorFullScreenPrimary) | NSWindowCollectionBehaviorFullScreenAuxiliary];
100 }
101 }
102#endif
103}
104
106{
107#ifdef GDK_WINDOWING_QUARTZ
108 if(gtk_widget_get_realized(widget))
110 else
111 g_signal_connect(G_OBJECT(widget), "realize", G_CALLBACK(dt_osx_disable_fullscreen), NULL);
112#endif
113}
114
115gboolean dt_osx_file_trash(const char *filename, GError **error)
116{
117 @autoreleasepool
118 {
119 NSFileManager *fm = [NSFileManager defaultManager];
120 NSError *err;
121
122 NSURL *url = [NSURL fileURLWithPath:@(filename)];
123
124 if ([fm respondsToSelector:@selector(trashItemAtURL:resultingItemURL:error:)]) {
125 if (![fm trashItemAtURL:url resultingItemURL:nil error:&err]) {
126 if (!IS_NULL_PTR(error))
127 *error = g_error_new_literal(G_IO_ERROR, err.code == NSFileNoSuchFileError ? G_IO_ERROR_NOT_FOUND : G_IO_ERROR_FAILED, err.localizedDescription.UTF8String);
128 return FALSE;
129 }
130 } else {
131 if (!IS_NULL_PTR(error))
132 *error = g_error_new_literal(G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "trash not supported on OS X versions < 10.8");
133 return FALSE;
134 }
135 return TRUE;
136 }
137}
138
140{
141 char *result = NULL;
142#ifdef MAC_INTEGRATION
143 gchar *bundle_id;
144
145#ifdef GTK_TYPE_OSX_APPLICATION
146 bundle_id = quartz_application_get_bundle_id();
147 if(bundle_id)
148 result = quartz_application_get_resource_path();
149#else
150 bundle_id = gtkosx_application_get_bundle_id();
151 if(bundle_id)
152 result = gtkosx_application_get_resource_path();
153#endif
154 dt_free(bundle_id);
155
156#endif
157
158 return result;
159}
160
161static char* _get_user_locale()
162{
163 @autoreleasepool
164 {
165 NSLocale* locale_ns = [NSLocale currentLocale];
166 NSString* locale_c;
167 if([locale_ns respondsToSelector: @selector(languageCode)] && [locale_ns respondsToSelector: @selector(countryCode)])
168 {
169 locale_c = [NSString stringWithFormat: @"%@_%@", [locale_ns languageCode], [locale_ns countryCode]];
170 }
171 else
172 {
173 // not ideal, but better than nothing
174 locale_c = [locale_ns localeIdentifier];
175 }
176 return strdup([locale_c UTF8String]);
177 }
178}
179
180static void _setup_ssl_trust(const char* const res_path)
181{
182#ifdef HAVE_P11KIT
183 gchar* const hash = g_compute_checksum_for_string(G_CHECKSUM_SHA1, res_path, strlen(res_path));
184 gchar* const file_path = g_build_filename(g_get_user_data_dir(), "ansel", "pkcs11", hash, "p11-kit-trust.module", NULL);
185 dt_free(hash);
186 {
187 GFile* const cfg_file = g_file_new_for_path(file_path);
188 {
189 GFile* const cfg_dir = g_file_get_parent(cfg_file);
190 g_file_make_directory_with_parents(cfg_dir, NULL, NULL);
191 {
192 const char* const dir_path = g_file_get_path(cfg_dir);
193 p11_kit_override_system_files("", NULL, "", dir_path, NULL);
194 // p11_kit_override_system_files function doesn't copy its parameters,
195 // so do NOT call g_free(dir_path);
196 }
197 g_object_unref(cfg_dir);
198 }
199 {
200 gchar* const buf = g_strdup_printf("module: %s/lib/pkcs11/p11-kit-trust.so\n"
201 "trust-policy: yes\n"
202 "x-init-reserved: paths=%s/share/curl/curl-ca-bundle.crt\n",
203 res_path, res_path);
204 g_file_replace_contents(cfg_file, buf, strlen(buf), NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, NULL);
205 dt_free(buf);
206 }
207 g_object_unref(cfg_file);
208 }
209 dt_free(file_path);
210#endif
211}
212
214{
215 // check that LC_CTYPE is set to something sane
216 // on macOS it's usually set to UTF-8
217 // which is fine for native setlocale function
218 // but since we link with libintl
219 // we are actually using libintl_setlocale (in case of macOS)
220 // which expects LC_CTYPE to be normal locale name
221 // otherwise calling setlocale(LC_ALL, "") fails
222 const gchar* ctype = g_getenv("LC_CTYPE");
223 if(ctype)
224 {
225 char *saved_locale = strdup(setlocale(LC_ALL, NULL));
226 if(!setlocale(LC_ALL, ctype))
227 {
228 g_unsetenv("LC_CTYPE");
229 }
230 else
231 {
232 setlocale(LC_ALL, saved_locale);
233 }
234 dt_free(saved_locale);
235 }
236 // set LANG according to user settings, unless already set
237 // otherwise we may get some non-default interface language
238 // and not even detect it
239 char* user_locale = _get_user_locale();
240 g_setenv("LANG", user_locale, FALSE);
241 dt_free(user_locale);
242 // set all required paths if we are in the app bundle
243 char* res_path = dt_osx_get_bundle_res_path();
244 if(res_path)
245 {
246 g_setenv("GTK_DATA_PREFIX", res_path, TRUE);
247 g_setenv("GTK_EXE_PREFIX", res_path, TRUE);
248 g_setenv("GTK_PATH", res_path, TRUE);
249 gchar* etc_path = g_build_filename(res_path, "etc", NULL);
250 gchar* lib_path = g_build_filename(res_path, "lib", NULL);
251 {
252 g_setenv("XDG_CONFIG_DIRS", etc_path, TRUE);
253 {
254 gchar* gtk_im_path = g_build_filename(etc_path, "gtk-3.0", "gtk.immodules", NULL);
255 g_setenv("GTK_IM_MODULE_FILE", gtk_im_path, TRUE);
256 dt_free(gtk_im_path);
257 }
258 {
259 gchar* pixbuf_path = g_build_filename(etc_path, "gtk-3.0", "loaders.cache", NULL);
260 g_setenv("GDK_PIXBUF_MODULE_FILE", pixbuf_path, TRUE);
261 dt_free(pixbuf_path);
262 }
263 }
264 {
265 gchar* share_path = g_build_filename(res_path, "share", NULL);
266 g_setenv("XDG_DATA_DIRS", share_path, TRUE);
267 {
268 gchar* schema_path = g_build_filename(share_path, "glib-2.0", "schemas", NULL);
269 g_setenv("GSETTINGS_SCHEMA_DIR", schema_path, TRUE);
270 dt_free(schema_path);
271 }
272 dt_free(share_path);
273 }
274 {
275 {
276 gchar* gio_path = g_build_filename(lib_path, "gio", "modules", NULL);
277 g_setenv("GIO_MODULE_DIR", gio_path, TRUE);
278 dt_free(gio_path);
279 }
280 }
281
282 _setup_ssl_trust(res_path); //uses GIO, so call after GIO_MODULE_DIR is set
283 dt_free(etc_path);
284 dt_free(lib_path);
285 dt_free(res_path);
286 }
287}
288
290{
291 [NSApp activateIgnoringOtherApps:YES];
292}
293
294// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
295// vim: shiftwidth=2 expandtab tabstop=2 cindent
296// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
GtkWidget * window
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
static void dt_osx_disable_fullscreen(GtkWidget *widget)
Definition osx.mm:90
void dt_osx_focus_window()
Definition osx.mm:289
char * dt_osx_get_bundle_res_path()
Definition osx.mm:139
static void _setup_ssl_trust(const char *const res_path)
Definition osx.mm:180
void dt_osx_prepare_environment()
Definition osx.mm:213
gboolean dt_osx_file_trash(const char *filename, GError **error)
Definition osx.mm:115
static char * _get_user_locale()
Definition osx.mm:161
void dt_osx_autoset_dpi(GtkWidget *widget)
Definition osx.mm:55
void dt_osx_disallow_fullscreen(GtkWidget *widget)
Definition osx.mm:105
float dt_osx_get_ppd()
Definition osx.mm:74