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 "common/darktable.h"
35#include <Carbon/Carbon.h>
36#include <ApplicationServices/ApplicationServices.h>
37#include <CoreServices/CoreServices.h>
38#include <AppKit/AppKit.h>
39#include <gtk/gtk.h>
40#include <gdk/gdkquartz.h>
41#include <gio/gio.h>
42#include <glib.h>
43#include <string.h>
44#ifdef MAC_INTEGRATION
45#include <gtkosxapplication.h>
46#endif
47#ifdef HAVE_P11KIT
48#define P11_KIT_FUTURE_UNSTABLE_API
49#include <p11-kit/p11-kit.h>
50#endif
51#include "osx.h"
52#include "libintl.h"
53
55{
56#if 0
57 GdkScreen *screen = gtk_widget_get_screen(widget);
58 if(!screen)
59 screen = gdk_screen_get_default();
60 if(!screen)
61 return;
62
63 CGDirectDisplayID id = CGMainDisplayID();
64 CGSize size_in_mm = CGDisplayScreenSize(id);
65 int width = CGDisplayPixelsWide(id);
66 int height = CGDisplayPixelsHigh(id);
67 gdk_screen_set_resolution(screen,
68 25.4 * sqrt(width * width + height * height)
69 / sqrt(size_in_mm.width * size_in_mm.width + size_in_mm.height * size_in_mm.height));
70#endif
71}
72
74{
75 @autoreleasepool
76 {
77 NSScreen *nsscreen = [NSScreen mainScreen];
78 if([nsscreen respondsToSelector: NSSelectorFromString(@"backingScaleFactor")])
79 {
80 return [[nsscreen valueForKey: @"backingScaleFactor"] floatValue];
81 }
82 else
83 {
84 return [[nsscreen valueForKey: @"userSpaceScaleFactor"] floatValue];
85 }
86 }
87}
88
90{
91#ifdef GDK_WINDOWING_QUARTZ
92 @autoreleasepool
93 {
94 GdkWindow *window = gtk_widget_get_window(widget);
95 if(window)
96 {
97 NSWindow *native = gdk_quartz_window_get_nswindow(window);
98 [native setCollectionBehavior: ([native collectionBehavior] & ~NSWindowCollectionBehaviorFullScreenPrimary) | NSWindowCollectionBehaviorFullScreenAuxiliary];
99 }
100 }
101#endif
102}
103
105{
106#ifdef GDK_WINDOWING_QUARTZ
107 if(gtk_widget_get_realized(widget))
109 else
110 g_signal_connect(G_OBJECT(widget), "realize", G_CALLBACK(dt_osx_disable_fullscreen), NULL);
111#endif
112}
113
114gboolean dt_osx_file_trash(const char *filename, GError **error)
115{
116 @autoreleasepool
117 {
118 NSFileManager *fm = [NSFileManager defaultManager];
119 NSError *err;
120
121 NSURL *url = [NSURL fileURLWithPath:@(filename)];
122
123 if ([fm respondsToSelector:@selector(trashItemAtURL:resultingItemURL:error:)]) {
124 if (![fm trashItemAtURL:url resultingItemURL:nil error:&err]) {
125 if (!IS_NULL_PTR(error))
126 *error = g_error_new_literal(G_IO_ERROR, err.code == NSFileNoSuchFileError ? G_IO_ERROR_NOT_FOUND : G_IO_ERROR_FAILED, err.localizedDescription.UTF8String);
127 return FALSE;
128 }
129 } else {
130 if (!IS_NULL_PTR(error))
131 *error = g_error_new_literal(G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "trash not supported on OS X versions < 10.8");
132 return FALSE;
133 }
134 return TRUE;
135 }
136}
137
139{
140 char *result = NULL;
141#ifdef MAC_INTEGRATION
142 gchar *bundle_id;
143
144#ifdef GTK_TYPE_OSX_APPLICATION
145 bundle_id = quartz_application_get_bundle_id();
146 if(bundle_id)
147 result = quartz_application_get_resource_path();
148#else
149 bundle_id = gtkosx_application_get_bundle_id();
150 if(bundle_id)
151 result = gtkosx_application_get_resource_path();
152#endif
153 dt_free(bundle_id);
154
155#endif
156
157 return result;
158}
159
160static char* _get_user_locale()
161{
162 @autoreleasepool
163 {
164 NSLocale* locale_ns = [NSLocale currentLocale];
165 NSString* locale_c;
166 if([locale_ns respondsToSelector: @selector(languageCode)] && [locale_ns respondsToSelector: @selector(countryCode)])
167 {
168 locale_c = [NSString stringWithFormat: @"%@_%@", [locale_ns languageCode], [locale_ns countryCode]];
169 }
170 else
171 {
172 // not ideal, but better than nothing
173 locale_c = [locale_ns localeIdentifier];
174 }
175 return strdup([locale_c UTF8String]);
176 }
177}
178
179static void _setup_ssl_trust(const char* const res_path)
180{
181#ifdef HAVE_P11KIT
182 gchar* const hash = g_compute_checksum_for_string(G_CHECKSUM_SHA1, res_path, strlen(res_path));
183 gchar* const file_path = g_build_filename(g_get_user_data_dir(), "ansel", "pkcs11", hash, "p11-kit-trust.module", NULL);
184 dt_free(hash);
185 {
186 GFile* const cfg_file = g_file_new_for_path(file_path);
187 {
188 GFile* const cfg_dir = g_file_get_parent(cfg_file);
189 g_file_make_directory_with_parents(cfg_dir, NULL, NULL);
190 {
191 const char* const dir_path = g_file_get_path(cfg_dir);
192 p11_kit_override_system_files("", NULL, "", dir_path, NULL);
193 // p11_kit_override_system_files function doesn't copy its parameters,
194 // so do NOT call g_free(dir_path);
195 }
196 g_object_unref(cfg_dir);
197 }
198 {
199 gchar* const buf = g_strdup_printf("module: %s/lib/pkcs11/p11-kit-trust.so\n"
200 "trust-policy: yes\n"
201 "x-init-reserved: paths=%s/share/curl/curl-ca-bundle.crt\n",
202 res_path, res_path);
203 g_file_replace_contents(cfg_file, buf, strlen(buf), NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, NULL);
204 dt_free(buf);
205 }
206 g_object_unref(cfg_file);
207 }
208 dt_free(file_path);
209#endif
210}
211
213{
214 // check that LC_CTYPE is set to something sane
215 // on macOS it's usually set to UTF-8
216 // which is fine for native setlocale function
217 // but since we link with libintl
218 // we are actually using libintl_setlocale (in case of macOS)
219 // which expects LC_CTYPE to be normal locale name
220 // otherwise calling setlocale(LC_ALL, "") fails
221 const gchar* ctype = g_getenv("LC_CTYPE");
222 if(ctype)
223 {
224 char *saved_locale = strdup(setlocale(LC_ALL, NULL));
225 if(!setlocale(LC_ALL, ctype))
226 {
227 g_unsetenv("LC_CTYPE");
228 }
229 else
230 {
231 setlocale(LC_ALL, saved_locale);
232 }
233 dt_free(saved_locale);
234 }
235 // set LANG according to user settings, unless already set
236 // otherwise we may get some non-default interface language
237 // and not even detect it
238 char* user_locale = _get_user_locale();
239 g_setenv("LANG", user_locale, FALSE);
240 dt_free(user_locale);
241 // set all required paths if we are in the app bundle
242 char* res_path = dt_osx_get_bundle_res_path();
243 if(res_path)
244 {
245 g_setenv("GTK_DATA_PREFIX", res_path, TRUE);
246 g_setenv("GTK_EXE_PREFIX", res_path, TRUE);
247 g_setenv("GTK_PATH", res_path, TRUE);
248 gchar* etc_path = g_build_filename(res_path, "etc", NULL);
249 gchar* lib_path = g_build_filename(res_path, "lib", NULL);
250 {
251 g_setenv("XDG_CONFIG_DIRS", etc_path, TRUE);
252 {
253 gchar* gtk_im_path = g_build_filename(etc_path, "gtk-3.0", "gtk.immodules", NULL);
254 g_setenv("GTK_IM_MODULE_FILE", gtk_im_path, TRUE);
255 dt_free(gtk_im_path);
256 }
257 {
258 gchar* pixbuf_path = g_build_filename(etc_path, "gtk-3.0", "loaders.cache", NULL);
259 g_setenv("GDK_PIXBUF_MODULE_FILE", pixbuf_path, TRUE);
260 dt_free(pixbuf_path);
261 }
262 }
263 {
264 gchar* share_path = g_build_filename(res_path, "share", NULL);
265 g_setenv("XDG_DATA_DIRS", share_path, TRUE);
266 {
267 gchar* schema_path = g_build_filename(share_path, "glib-2.0", "schemas", NULL);
268 g_setenv("GSETTINGS_SCHEMA_DIR", schema_path, TRUE);
269 dt_free(schema_path);
270 }
271 dt_free(share_path);
272 }
273 {
274 {
275 gchar* gio_path = g_build_filename(lib_path, "gio", "modules", NULL);
276 g_setenv("GIO_MODULE_DIR", gio_path, TRUE);
277 dt_free(gio_path);
278 }
279 }
280
281#ifdef HAVE_IMAGEMAGICK7
282 {
283 g_setenv("MAGICK_HOME", res_path, TRUE);
284 gchar* im_config_path = g_build_filename(etc_path, "ImageMagick-7", NULL);
285 g_setenv("MAGICK_CONFIGURE_PATH", im_config_path, TRUE);
286 dt_free(im_config_path);
287 gchar* im_modules_path = g_build_filename(lib_path, "ImageMagick", "modules-Q16HDRI", NULL);
288 g_setenv("MAGICK_CODER_MODULE_PATH", im_modules_path, TRUE);
289 g_setenv("MAGICK_CODER_FILTER_PATH", im_modules_path, TRUE);
290 dt_free(im_modules_path);
291 }
292#endif
293
294 _setup_ssl_trust(res_path); //uses GIO, so call after GIO_MODULE_DIR is set
295 dt_free(etc_path);
296 dt_free(lib_path);
297 dt_free(res_path);
298 }
299}
300
302{
303 [NSApp activateIgnoringOtherApps:YES];
304}
305
306// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
307// vim: shiftwidth=2 expandtab tabstop=2 cindent
308// 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
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
#define dt_free(ptr)
Definition darktable.h:456
#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 darktable.h:281
static void dt_osx_disable_fullscreen(GtkWidget *widget)
Definition osx.mm:89
void dt_osx_focus_window()
Definition osx.mm:301
char * dt_osx_get_bundle_res_path()
Definition osx.mm:138
static void _setup_ssl_trust(const char *const res_path)
Definition osx.mm:179
void dt_osx_prepare_environment()
Definition osx.mm:212
gboolean dt_osx_file_trash(const char *filename, GError **error)
Definition osx.mm:114
static char * _get_user_locale()
Definition osx.mm:160
void dt_osx_autoset_dpi(GtkWidget *widget)
Definition osx.mm:54
void dt_osx_disallow_fullscreen(GtkWidget *widget)
Definition osx.mm:104
float dt_osx_get_ppd()
Definition osx.mm:73
struct _GtkWidget GtkWidget
Definition splash.h:29