changeset 237:a7d0d543b334

*: make OS X builds succeed new script: deploy_build.sh, creates the app bundle
author Paper <paper@paper.us.eu.org>
date Fri, 19 Jan 2024 11:14:44 -0500
parents 4d461ef7d424
children d2b7e974221e
files .builds/linux.yml .builds/windows.yml .hgignore CMakeLists.txt Makefile.am configure.ac dep/animia/Makefile.am dep/animia/include/animia/util/osx.h dep/animia/src/fd/proc.cc dep/animia/src/util/osx.cc dep/animia/src/win/quartz.cc dep/anitomy/Makefile.am dep/pugixml/Makefile.am include/sys/osx/dark_theme.h include/sys/osx/permissions.h m4/m4_ax_have_qt.m4 rc/linux/Minori.desktop rc/linux/Minori.desktop.in rc/osx/deploy_build.sh rc/osx/favicon.icns src/gui/window.cc src/sys/osx/permissions.cc
diffstat 22 files changed, 305 insertions(+), 138 deletions(-) [+]
line wrap: on
line diff
--- a/.builds/linux.yml	Fri Jan 19 00:24:02 2024 -0500
+++ b/.builds/linux.yml	Fri Jan 19 11:14:44 2024 -0500
@@ -2,7 +2,9 @@
 packages:
   - qtbase5-dev
   - qttools5-dev
-  - cmake
+  - automake
+  - autoconf
+  - libtool
   - clang
   - libcurl4-openssl-dev
   - wget
@@ -13,27 +15,26 @@
   - pkg-config
 sources:
   - https://hg.sr.ht/~mrpapersonic/minori
-environment:
-  BUILD_SUBMITTER: hg.sr.ht
 tasks:
   - build: |
+      # build
       cd minori
       autoreconf -i
-      cd dep/animia
-      autoreconf -i
-      cd ../anitomy
-      autoreconf -i
-      cd ../pugixml
-      autoreconf -i
-      cd ../..
       mkdir build
       cd build
       ../configure
       make
+      sudo make install
 
+      # resources
+      mkdir -p rc
+      cp ../rc/Minori.desktop rc/Minori.desktop
+      cp ../rc/favicon256.png rc/Minori.png
+
+      # use linuxdeploy to make an appimage
       wget -O linuxdeploy "https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20231026-1/linuxdeploy-x86_64.AppImage"
       chmod +x linuxdeploy
-      ./linuxdeploy --appdir Minori --executable minori -d rc/Minori.desktop -i rc/Minori.png --output appimage
+      LD_LIBRARY_PATH=/usr/local/lib ./linuxdeploy --appdir Minori --executable $(which minori) -d rc/Minori.desktop -i rc/Minori.png --output appimage
 artifacts:
   - minori/build/Minori-x86_64.AppImage
 triggers:
--- a/.builds/windows.yml	Fri Jan 19 00:24:02 2024 -0500
+++ b/.builds/windows.yml	Fri Jan 19 11:14:44 2024 -0500
@@ -8,24 +8,28 @@
   - lld
   - xz-utils
   - wine
-  - cmake
+  - automake
+  - autoconf
+  - libtool
   - ncurses-bin
   - qtbase5-dev
   - qttools5-dev
 sources:
   - https://hg.sr.ht/~mrpapersonic/minori
-environment:
-  BUILD_SUBMITTER: hg.sr.ht
 tasks:
+  - autoreconf: |
+      cd minori
+      autoreconf -i
   - build-win64: |
       export WINEARCH=win64
       git clone https://github.com/holyblackcat/quasi-msys2 quasi-msys2-win64
       cd quasi-msys2-win64
       echo MINGW64 >msystem.txt
-      make install _gcc _qt5-base _qt5-tools _curl _autotools
-      cd ../minori
+      make install _gcc _qt5-base _qt5-tools _curl
+      mkdir -p ../minori/build64
+      cd ../minori/build64
       sudo bash -c 'echo -n 1 >/proc/sys/fs/binfmt_misc/status'
-      bash -c 'source ../../quasi-msys2-win64/env/all.src && autoreconf -i && cd dep/animia && autoreconf -i && cd ../anitomy && autoreconf -i && cd ../pugixml && autoreconf -i && ../.. && mkdir build64 && cd build64 && ../configure && make'
+      bash -c 'source ../../quasi-msys2-win64/env/all.src && ../configure && make'
   - get-wine32: |
       sudo dpkg --add-architecture i386
       sudo apt-get update
@@ -37,11 +41,10 @@
       cd quasi-msys2-win32
       echo MINGW32 >msystem.txt
       make install _gcc _qt5-base _qt5-tools _curl
-      cd ../minori
-      mkdir build32
-      cd build32
+      mkdir -p ../minori/build32
+      cd ../minori/build32
       sudo bash -c 'echo -n 1 >/proc/sys/fs/binfmt_misc/status'
-      bash -c 'source ../../quasi-msys2-win32/env/all.src && autoreconf -i && cd dep/animia && autoreconf -i && cd ../anitomy && autoreconf -i && cd ../pugixml && autoreconf -i && ../.. && mkdir build32 && cd build32 && ../configure && make'
+      bash -c 'source ../../quasi-msys2-win32/env/all.src && ../configure && make'
 triggers:
   - action: email
     condition: failure
--- a/.hgignore	Fri Jan 19 00:24:02 2024 -0500
+++ b/.hgignore	Fri Jan 19 11:14:44 2024 -0500
@@ -1,5 +1,14 @@
 syntax: glob
 
+**/m4/libtool.m4
+**/m4/lt*.m4
+**/build-aux
+**/aclocal.m4
+**/Makefile.in
+**/configure
+**/*~
+**/autom4te.cache
+
 # stupid OS X things
 .DS_Store
 ._*
--- a/CMakeLists.txt	Fri Jan 19 00:24:02 2024 -0500
+++ b/CMakeLists.txt	Fri Jan 19 11:14:44 2024 -0500
@@ -165,6 +165,7 @@
 	list(APPEND SRC_FILES
 		src/sys/osx/dark_theme.cc
 		src/sys/osx/filesystem.cc
+		src/sys/osx/permissions.cc
 		${app_icon_osx}
 	)
 	list(APPEND DEFINES MACOSX)
--- a/Makefile.am	Fri Jan 19 00:24:02 2024 -0500
+++ b/Makefile.am	Fri Jan 19 11:14:44 2024 -0500
@@ -79,8 +79,10 @@
 endif
 
 if BUILD_OSX
-files_osx = src/sys/osx/dark_theme.cc src/sys/osx/filesystem.cc
-libs_osx = Foundation AppKit
+files_osx = src/sys/osx/dark_theme.cc src/sys/osx/filesystem.cc src/sys/osx/permissions.cc
+cflags_osx = -mmacosx-version-min=10.15
+libs_osx = -lobjc
+ldflags_osx = -framework Foundation -framework AppKit
 endif
 
 minori_SOURCES = \
@@ -139,19 +141,17 @@
 	-I$(top_srcdir)/dep/anitomy \
 	-I$(top_srcdir)/dep
 
-minori_CPPFLAGS = $(minori_includes) @QT_CXXFLAGS@ @LIBCURL_CPPFLAGS@
-minori_CXXFLAGS = $(cflags_glib) $(cflags_win) $(cflags_osx)
+minori_CPPFLAGS = @LIBCURL_CPPFLAGS@ $(minori_includes)
+minori_CXXFLAGS = @QT_CXXFLAGS@ $(cflags_osx) $(cflags_glib) $(cflags_win) -std=c++17
+minori_LDFLAGS = $(ldflags_osx)
 
 minori_DEPENDENCIES = dep/pugixml/libpugixml.la dep/animia/libanimia.la dep/anitomy/libanitomy.la
 minori_LDADD = $(libs_glib) $(libs_osx) @LIBCURL@ @QT_LIBS@ dep/pugixml/libpugixml.la dep/animia/libanimia.la dep/anitomy/libanitomy.la
 
-.qrc_qrc.cc:
-	
-
 .h_moc.cc:
 	@MKDIR_P@ -- `dirname $@`
 	@QT_MOC@ -o $@ $(minori_includes) $<
 
-SUFFIXES = .h _moc.cc .qrc _qrc.cc
+SUFFIXES = .h _moc.cc
 SUBDIRS = $(subdirs)
 ACLOCAL_AMFLAGS = -I m4
--- a/configure.ac	Fri Jan 19 00:24:02 2024 -0500
+++ b/configure.ac	Fri Jan 19 11:14:44 2024 -0500
@@ -2,6 +2,7 @@
 
 AC_CANONICAL_HOST
 
+AC_CONFIG_SUBDIRS([dep/pugixml dep/animia dep/anitomy])
 AC_CONFIG_SRCDIR([src/main.cc])
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_MACRO_DIRS([m4])
@@ -9,9 +10,11 @@
 AM_INIT_AUTOMAKE([-Wall -Wportability foreign subdir-objects])
 
 # Do we have a C++17 compiler
+: ${CXXFLAGS=""}
 AC_PROG_CXX
-AX_CXX_COMPILE_STDCXX(17, noext, mandatory)
+AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
 
+# Init libtool
 AM_PROG_AR
 LT_INIT
 
@@ -26,7 +29,7 @@
 AC_PROG_MKDIR_P
 
 # libcurl?
-LIBCURL_CHECK_CONFIG(yes, 7.7.2, [have_libcurl=yes], [have_libcurl=no])
+LIBCURL_CHECK_CONFIG([yes], [7.7.2], [have_libcurl=yes], [have_libcurl=no])
 
 if test "x$have_libcurl" = "xno"; then
 	AC_MSG_ERROR([*** libcurl not found.])
@@ -56,7 +59,7 @@
 		# Everything else
 		AC_SUBST([GIO_CFLAGS])
 		AC_SUBST([GIO_LIBS])
-		PKG_CHECK_MODULES(GIO, gio-2.0, [build_glib=yes], [])
+		PKG_CHECK_MODULES([GIO], [gio-2.0], [build_glib=yes], [])
 		;;
 esac
 
@@ -65,7 +68,5 @@
 AM_CONDITIONAL([BUILD_GLIB], [test "x$build_glib" = "xyes"])
 AM_CONDITIONAL([BUILD_WINDRES], [test "x$WINDRES" != "x"])
 
-AC_CONFIG_SUBDIRS([dep/pugixml dep/animia dep/anitomy])
-
 AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
--- a/dep/animia/Makefile.am	Fri Jan 19 00:24:02 2024 -0500
+++ b/dep/animia/Makefile.am	Fri Jan 19 11:14:44 2024 -0500
@@ -7,8 +7,8 @@
 
 if BUILD_OSX
 files_osx = src/fd/xnu.cc src/win/quartz.cc src/util/osx.cc
-cflags_osx =
-libs_osx = Foundation CoreGraphics AppKit objc
+libs_osx = -lobjc
+ldflags_osx = -framework Foundation -framework CoreGraphics -framework ApplicationServices
 endif
 
 if BUILD_LINUX
@@ -57,9 +57,8 @@
 
 libanimia_la_CPPFLAGS = -I$(top_srcdir)/include @DEFS@
 
-libanimia_la_LDFLAGS = -version-info 0:0:0
-
-libanimia_la_CXXFLAGS = $(cflags_osx) $(cflags_x11) $(cflags_wayland)
+libanimia_la_CXXFLAGS = -std=c++17 $(cflags_osx) $(cflags_x11) $(cflags_wayland)
+libanimia_la_LDFLAGS = -version-info 0:0:0 $(ldflags_osx)
 
 libanimia_la_LIBADD = $(libs_wayland) $(libs_x11) $(libs_osx) $(libs_libutil) $(libs_libkvm)
 
--- a/dep/animia/include/animia/util/osx.h	Fri Jan 19 00:24:02 2024 -0500
+++ b/dep/animia/include/animia/util/osx.h	Fri Jan 19 11:14:44 2024 -0500
@@ -5,14 +5,10 @@
 #include <string>
 #include <cstdint>
 
-#ifdef HAVE_COREFOUNDATION
 #include <CoreFoundation/CoreFoundation.h>
-#endif
 
 namespace animia::internal::osx::util {
 
-#ifdef HAVE_COREFOUNDATION
-
 template<typename T>
 bool GetCFNumber(CFNumberRef num, T& result) {
 	if (!num)
@@ -28,8 +24,6 @@
 
 bool StringFromCFString(CFStringRef string, std::string& result);
 
-#endif // HAVE_COREFOUNDATION
-
 bool GetProcessName(pid_t pid, std::string& result);
 
 }
--- a/dep/animia/src/fd/proc.cc	Fri Jan 19 00:24:02 2024 -0500
+++ b/dep/animia/src/fd/proc.cc	Fri Jan 19 11:14:44 2024 -0500
@@ -7,8 +7,6 @@
 #include <sstream>
 #include <string>
 
-#include <iostream>
-
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
--- a/dep/animia/src/util/osx.cc	Fri Jan 19 00:24:02 2024 -0500
+++ b/dep/animia/src/util/osx.cc	Fri Jan 19 11:14:44 2024 -0500
@@ -8,7 +8,6 @@
 
 namespace animia::internal::osx::util {
 
-#ifdef HAVE_COREFOUNDATION
 /* all of these LaunchServices things use *internal functions* that are subject
  * to change. Granted, it's not very likely that these will change very much
  * because I'm fairly sure Apple uses them lots in their own internal code.
@@ -104,7 +103,6 @@
 
 	return true;
 }
-#endif // HAVE_COREFOUNDATION
 
 static bool GetProcessArgs(pid_t pid, std::string& args) {
 	/* sysctl shouldn't touch these, so we define them as const */
--- a/dep/animia/src/win/quartz.cc	Fri Jan 19 00:24:02 2024 -0500
+++ b/dep/animia/src/win/quartz.cc	Fri Jan 19 11:14:44 2024 -0500
@@ -2,8 +2,7 @@
  * win/quartz.cc: support for macOS (the Quartz Compositor)
  *
  * This file does not require an Objective-C++ compiler,
- * but it *does* require an Objective-C runtime and linking
- * with AppKit in order to receive proper window titles.
+ * but it *does* require an Objective-C runtime.
 */
 #include "animia/win/quartz.h"
 #include "animia/util/osx.h"
@@ -14,51 +13,50 @@
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <CoreGraphics/CoreGraphics.h>
+#include <ApplicationServices/ApplicationServices.h>
 
 namespace animia::internal::quartz {
 
+/* all of these LaunchServices things use *internal functions* that are subject
+ * to change. Granted, it's not very likely that these will change very much
+ * because I'm fairly sure Apple uses them lots in their own internal code.
+*/
+#if __LP64__
+typedef long NSInteger;
+#else
+typedef int NSInteger;
+#endif
+typedef int CGSConnection;
+
+typedef CGSConnection (*CGSDefaultConnectionForThreadSpec)(void);
+typedef CGError (*CGSCopyWindowPropertySpec)(const CGSConnection, NSInteger, CFStringRef, CFStringRef*);
+
+static CGSDefaultConnectionForThreadSpec CGSDefaultConnectionForThread = nullptr;
+static CGSCopyWindowPropertySpec CGSCopyWindowProperty = nullptr;
+
+static const CFStringRef kCoreGraphicsBundleID = CFSTR("com.apple.CoreGraphics");
+
+/* Objective-C */
 typedef id (*object_message_send)(id, SEL, ...);
 typedef id (*class_message_send)(Class, SEL, ...);
 
 static const object_message_send obj_send = reinterpret_cast<object_message_send>(objc_msgSend);
 static const class_message_send cls_send = reinterpret_cast<class_message_send>(objc_msgSend);
 
-static bool GetWindowTitle(unsigned int wid, std::string& result) {
-	// NSApplication* app = [NSApplication sharedApplication];
-	const id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication"));
-
-	// NSWindow* window = [app windowWithWindowNumber: wid];
-	const id window = obj_send(app, sel_getUid("windowWithWindowNumber:"), wid);
-	if (!window)
-		return false;
-
-	// NSString* title = [window title];
-	const CFStringRef title = reinterpret_cast<CFStringRef>(obj_send(window, sel_getUid("title")));
-	if (!title)
+static bool GetCoreGraphicsPrivateSymbols() {
+	CFBundleRef core_graphics_bundle = CFBundleGetBundleWithIdentifier(kCoreGraphicsBundleID);
+	if (!core_graphics_bundle)
 		return false;
 
-	// return [title UTF8String];
-	return osx::util::StringFromCFString(title, result);
-}
-
-static bool GetProcessBundleIdentifier(pid_t pid, std::string& result) {
-	/* The Bundle ID is essentially OS X's solution to Windows'
-	 * "class name"; theoretically, it should be different for
-	 * each program, although it requires an app bundle.
-	*/
-
-	// NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier: pid];
-	const id app = cls_send(objc_getClass("NSRunningApplication"), sel_getUid("runningApplicationWithProcessIdentifier:"), pid);
-	if (!app)
+	CGSDefaultConnectionForThread = (CGSDefaultConnectionForThreadSpec)CFBundleGetFunctionPointerForName(core_graphics_bundle, CFSTR("CGSDefaultConnectionForThread"));
+	if (!CGSDefaultConnectionForThread)
 		return false;
 
-	// NSString* bundle_id = [app bundleIdentifier];
-	const CFStringRef bundle_id = reinterpret_cast<CFStringRef>(obj_send(app, sel_getUid("bundleIdentifier")));
-	if (!bundle_id)
+	CGSCopyWindowProperty = (CGSCopyWindowPropertySpec)CFBundleGetFunctionPointerForName(core_graphics_bundle, CFSTR("CGSCopyWindowProperty"));
+	if (!CGSCopyWindowProperty)
 		return false;
 
-	// return [bundle_id UTF8String];
-	return osx::util::StringFromCFString(bundle_id, result);
+	return true;
 }
 
 template<typename T>
@@ -77,11 +75,110 @@
 	return true;
 }
 
+static bool GetWindowTitleAccessibility(unsigned int wid, pid_t pid, std::string& result) {
+	CGRect bounds = {0};
+	{
+		const CGWindowID wids[1] = {wid};
+		CFArrayRef arr = CFArrayCreate(kCFAllocatorDefault, (CFTypeRef*)wids, 1, NULL);
+
+		CFArrayRef dicts = CGWindowListCreateDescriptionFromArray(arr);
+
+		CFRelease(arr);
+
+		if (!dicts || CFArrayGetCount(dicts) < 1)
+			return false;
+
+		CFDictionaryRef dict = (CFDictionaryRef)CFArrayGetValueAtIndex(dicts, 0);
+		if (!dict) {
+			CFRelease(dicts);
+			return false;
+		}
+
+		CFDictionaryRef bounds_dict = nullptr;
+		if (!CFDictionaryGetValueIfPresent(dict, kCGWindowBounds, reinterpret_cast<CFTypeRef*>(&bounds_dict)) || !bounds_dict) {
+			CFRelease(dicts);
+			return false;
+		}
+
+		if (!CGRectMakeWithDictionaryRepresentation(bounds_dict, &bounds)) {
+			CFRelease(dicts);
+			return false;
+		}
+
+		CFRelease(dicts);
+	}
+
+	/* now we can actually do stuff */
+	AXUIElementRef axapp = AXUIElementCreateApplication(pid);
+	CFArrayRef windows;
+	if ((AXUIElementCopyAttributeValue(axapp, kAXWindowsAttribute, (CFTypeRef*)&windows) != kAXErrorSuccess) || !windows)
+		return false;
+
+	const CFIndex count = CFArrayGetCount(windows);
+	for (CFIndex i = 0; i < count; i++) {
+		const AXUIElementRef window = (AXUIElementRef)CFArrayGetValueAtIndex(windows, i);
+
+		AXValueRef val;
+		if (AXUIElementCopyAttributeValue(window, kAXPositionAttribute, (CFTypeRef*)&val) == kAXErrorSuccess) {
+			CGPoint point;
+			if (!AXValueGetValue(val, kAXValueTypeCGPoint, (void*)&point) || (point.x != bounds.origin.x || point.y != bounds.origin.y))
+				continue;
+		} else continue;
+
+		if (AXUIElementCopyAttributeValue(window, kAXSizeAttribute, (CFTypeRef*)&val) == kAXErrorSuccess) {
+			CGSize size;
+			if (!AXValueGetValue(val, kAXValueTypeCGSize, (void*)&size) || (size.width != bounds.size.width || size.height != bounds.size.height))
+				continue;
+		} else continue;
+
+		CFStringRef title;
+		if (AXUIElementCopyAttributeValue(window, kAXTitleAttribute, (CFTypeRef*)&title) == kAXErrorSuccess) {
+			CFRelease(windows);
+			return osx::util::StringFromCFString(title, result);
+		}
+	}
+
+	CFRelease(windows);
+
+	return false;
+}
+
+static bool GetWindowTitle(unsigned int wid, pid_t pid, std::string& result) {
+	/* private internal OS X functions */
+	if ((CGSDefaultConnectionForThread && CGSCopyWindowProperty) || GetCoreGraphicsPrivateSymbols()) {
+		CFStringRef title = nullptr;
+
+		CGSCopyWindowProperty(CGSDefaultConnectionForThread(), wid, CFSTR("kCGSWindowTitle"), &title);
+		if (title && CFStringGetLength(title) && osx::util::StringFromCFString(title, result))
+			return true;
+	}
+
+	/* don't attempt to use accessibility if we aren't trusted */
+	return AXIsProcessTrusted() ? GetWindowTitleAccessibility(wid, pid, result) : false;
+}
+
+static bool GetProcessBundleIdentifier(pid_t pid, std::string& result) {
+	/* The Bundle ID is essentially OS X's solution to Windows'
+	 * "class name"; theoretically, it should be different for
+	 * each program, although it requires an app bundle.
+	*/
+	const id app = cls_send(objc_getClass("NSRunningApplication"), sel_getUid("runningApplicationWithProcessIdentifier:"), pid);
+	if (!app)
+		return false;
+
+	CFStringRef bundle_id = reinterpret_cast<CFStringRef>(obj_send(app, sel_getUid("bundleIdentifier")));
+	if (!bundle_id)
+		return false;
+
+	result = osx::util::StringFromCFString(bundle_id, result);
+	return true;
+}
+
 bool EnumerateWindows(window_proc_t window_proc) {
 	if (!window_proc)
 		return false;
 
-	const CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
+	const CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
 	if (!windows)
 		return false;
 
@@ -102,13 +199,12 @@
 		{
 			CFDictionaryGetValue(window, CFSTR("kCGWindowNumber"), win.id);
 
-			if (!GetProcessBundleIdentifier(proc.pid, win.class_name)) {
+			if (!GetProcessBundleIdentifier(proc.pid, win.class_name))
 				// Fallback to the Quartz window name, which is unlikely to be filled, but it
 				// *could* be.
 				CFDictionaryGetValue(window, CFSTR("kCGWindowName"), win.class_name);
-			}
 
-			GetWindowTitle(win.id, win.text);
+			GetWindowTitle(win.id, proc.pid, win.text);
 		}
 
 		if (!window_proc(proc, win)) {
--- a/dep/anitomy/Makefile.am	Fri Jan 19 00:24:02 2024 -0500
+++ b/dep/anitomy/Makefile.am	Fri Jan 19 11:14:44 2024 -0500
@@ -19,4 +19,5 @@
 	anitomy/token.h	\
 	anitomy/tokenizer.h
 
+libanitomy_la_CXXFLAGS = -std=c++17
 ACLOCAL_AMFLAGS = -I m4
\ No newline at end of file
--- a/dep/pugixml/Makefile.am	Fri Jan 19 00:24:02 2024 -0500
+++ b/dep/pugixml/Makefile.am	Fri Jan 19 11:14:44 2024 -0500
@@ -2,4 +2,5 @@
 libpugixml_la_SOURCES = src/pugixml.cpp
 include_HEADERS = src/pugixml.hpp
 
+libpugixml_la_CXXFLAGS = -std=c++11
 ACLOCAL_AMFLAGS = -I m4
--- a/include/sys/osx/dark_theme.h	Fri Jan 19 00:24:02 2024 -0500
+++ b/include/sys/osx/dark_theme.h	Fri Jan 19 11:14:44 2024 -0500
@@ -11,4 +11,4 @@
 
 } // namespace osx
 
-#endif // __sys__osx__dark_theme_h
\ No newline at end of file
+#endif // __sys__osx__dark_theme_h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/sys/osx/permissions.h	Fri Jan 19 11:14:44 2024 -0500
@@ -0,0 +1,10 @@
+#ifndef __sys__osx__permissions_h
+#define __sys__osx__permissions_h
+
+namespace osx {
+
+bool AskForPermissions();
+
+} // namespace osx
+
+#endif // __sys__osx__permissions_h
--- a/m4/m4_ax_have_qt.m4	Fri Jan 19 00:24:02 2024 -0500
+++ b/m4/m4_ax_have_qt.m4	Fri Jan 19 11:14:44 2024 -0500
@@ -87,35 +87,38 @@
     CONFIG -= debug_and_release
     CONFIG += release
 }
-qtHaveModule(axcontainer):       QT += axcontainer
-qtHaveModule(axserver):          QT += axserver
-qtHaveModule(concurrent):        QT += concurrent
+# commented out all the modules we don't use
+#   - paper
+#qtHaveModule(axcontainer):       QT += axcontainer
+#qtHaveModule(axserver):          QT += axserver
+#qtHaveModule(concurrent):        QT += concurrent
 qtHaveModule(core):              QT += core
-qtHaveModule(dbus):              QT += dbus
-qtHaveModule(declarative):       QT += declarative
-qtHaveModule(designer):          QT += designer
+#qtHaveModule(dbus):              QT += dbus
+#qtHaveModule(declarative):       QT += declarative
+#qtHaveModule(designer):          QT += designer
 qtHaveModule(gui):               QT += gui
-qtHaveModule(help):              QT += help
-qtHaveModule(multimedia):        QT += multimedia
-qtHaveModule(multimediawidgets): QT += multimediawidgets
-qtHaveModule(network):           QT += network
-qtHaveModule(opengl):            QT += opengl
-qtHaveModule(printsupport):      QT += printsupport
-qtHaveModule(qml):               QT += qml
-qtHaveModule(qmltest):           QT += qmltest
-qtHaveModule(x11extras):         QT += x11extras
-qtHaveModule(script):            QT += script
-qtHaveModule(scripttools):       QT += scripttools
-qtHaveModule(sensors):           QT += sensors
-qtHaveModule(serialport):        QT += serialport
-qtHaveModule(sql):               QT += sql
-qtHaveModule(svg):               QT += svg
-qtHaveModule(testlib):           QT += testlib
-qtHaveModule(uitools):           QT += uitools
-qtHaveModule(webkit):            QT += webkit
-qtHaveModule(webkitwidgets):     QT += webkitwidgets
-qtHaveModule(xml):               QT += xml
-qtHaveModule(xmlpatterns):       QT += xmlpatterns
+#qtHaveModule(help):              QT += help
+#qtHaveModule(multimedia):        QT += multimedia
+#qtHaveModule(multimediawidgets): QT += multimediawidgets
+#qtHaveModule(network):           QT += network
+#qtHaveModule(opengl):            QT += opengl
+#qtHaveModule(printsupport):      QT += printsupport
+#qtHaveModule(qml):               QT += qml
+#qtHaveModule(qmltest):           QT += qmltest
+#qtHaveModule(x11extras):         QT += x11extras
+#qtHaveModule(script):            QT += script
+#qtHaveModule(scripttools):       QT += scripttools
+#qtHaveModule(sensors):           QT += sensors
+#qtHaveModule(serialport):        QT += serialport
+#qtHaveModule(sql):               QT += sql
+#qtHaveModule(svg):               QT += svg
+#qtHaveModule(testlib):           QT += testlib
+#qtHaveModule(uitools):           QT += uitools
+#qtHaveModule(webkit):            QT += webkit
+#qtHaveModule(webkitwidgets):     QT += webkitwidgets
+#qtHaveModule(xml):               QT += xml
+#qtHaveModule(xmlpatterns):       QT += xmlpatterns
+qtHaveModule(widgets):            QT += widgets
 percent.target = %
 percent.commands = @echo -n "\$(\$(@))\ "
 QMAKE_EXTRA_TARGETS += percent
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rc/linux/Minori.desktop	Fri Jan 19 11:14:44 2024 -0500
@@ -0,0 +1,24 @@
+[Desktop Entry]
+
+# The type as listed above
+Type=Application
+
+# The version of the desktop entry specification to which this file complies
+Version=1.4
+
+# The name of the application
+Name=Minori
+
+# A comment which can/will be used as a tooltip
+Comment=A lightweight anime tracker built with Qt.
+
+# Executable name
+Exec=minori
+
+# Favicon
+Icon=Minori
+
+# Describes whether this application needs to be run in a terminal or not
+Terminal=false
+
+Categories=Utility;Qt;
\ No newline at end of file
--- a/rc/linux/Minori.desktop.in	Fri Jan 19 00:24:02 2024 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-[Desktop Entry]
-
-# The type as listed above
-Type=Application
-
-# The version of the desktop entry specification to which this file complies
-Version=1.4
-
-# The name of the application
-Name=Minori
-
-# A comment which can/will be used as a tooltip
-Comment=@RC_INFO_STRING@
-
-# Executable name
-Exec=minori
-
-# Favicon
-Icon=Minori
-
-# Describes whether this application needs to be run in a terminal or not
-Terminal=false
-
-Categories=Utility;Qt;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rc/osx/deploy_build.sh	Fri Jan 19 11:14:44 2024 -0500
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# deploy_build.sh:
+# run this in your build dir to get a usable app bundle
+
+SCRIPT_DIR=$(dirname -- "$0")
+BUNDLE_NAME="Minori"
+
+cp -r "$SCRIPT_DIR/$BUNDLE_NAME.app" .
+mkdir -p "$BUNDLE_NAME.app/Contents/MacOS"
+cp ".libs/minori" "$BUNDLE_NAME.app/Contents/MacOS/minori"
+mkdir -p "$BUNDLE_NAME.app/Contents/Frameworks"
+for i in animia pugixml anitomy; do
+	cp "dep/$i/.libs/lib$i.0.dylib" "$BUNDLE_NAME.app/Contents/Frameworks"
+	install_name_tool -change "/usr/local/lib/lib$i.0.dylib" "@executable_path/../Frameworks/lib$i.0.dylib" "$BUNDLE_NAME.app/Contents/MacOS/minori"
+done
+macdeployqt "$BUNDLE_NAME.app"
Binary file rc/osx/favicon.icns has changed
--- a/src/gui/window.cc	Fri Jan 19 00:24:02 2024 -0500
+++ b/src/gui/window.cc	Fri Jan 19 11:14:44 2024 -0500
@@ -43,6 +43,7 @@
 
 #ifdef MACOSX
 #	include "sys/osx/dark_theme.h"
+#	include "sys/osx/permissions.h"
 #elif defined(WIN32)
 #	include "sys/win32/dark_theme.h"
 #endif
@@ -72,7 +73,6 @@
 	new QHBoxLayout(main_widget.get());
 
 	AddMainWidgets();
-
 	setCentralWidget(main_widget.get());
 
 	CreateBars();
@@ -114,6 +114,11 @@
 		thread->start();
 	});
 
+#ifdef MACOSX
+	if (!osx::AskForPermissions())
+		return;
+#endif
+
 	timer->start(5000);
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sys/osx/permissions.cc	Fri Jan 19 11:14:44 2024 -0500
@@ -0,0 +1,30 @@
+#include "sys/osx/permissions.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#include <QCoreApplication>
+#include <QMessageBox>
+#include <QDesktopServices>
+#include <QUrl>
+
+namespace osx {
+
+bool AskForPermissions() {
+	if (::AXIsProcessTrusted())
+		return true;
+
+	QMessageBox msg;
+	msg.setIcon(QMessageBox::Information);
+	msg.setText(QCoreApplication::tr("Permissions needed!"));
+	msg.setInformativeText(QCoreApplication::tr("Minori needs access to accessibility features for certain features to work. Open System Preferences?"));
+	msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+	msg.setDefaultButton(QMessageBox::Yes);
+	int ret = msg.exec();
+	if (ret != QMessageBox::Yes)
+		return false;
+
+	QDesktopServices::openUrl(QUrl("x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"));
+	return true;
+}
+
+}