diff --git a/src/osax/common.h b/src/osax/common.h index ed75d41a..2bc63a99 100644 --- a/src/osax/common.h +++ b/src/osax/common.h @@ -1,7 +1,7 @@ #ifndef SA_COMMON_H #define SA_COMMON_H -#define OSAX_VERSION "2.1.7" +#define OSAX_VERSION "2.1.8" #define OSAX_ATTRIB_DOCK_SPACES 0x01 #define OSAX_ATTRIB_DPPM 0x02 @@ -38,6 +38,7 @@ enum sa_opcode SA_OPCODE_WINDOW_SWAP_PROXY_OUT = 0x0F, SA_OPCODE_WINDOW_ORDER = 0x10, SA_OPCODE_WINDOW_ORDER_IN = 0x11, + SA_OPCODE_WINDOW_MOVE_SPACE = 0x12, }; #endif diff --git a/src/osax/payload.m b/src/osax/payload.m index 4381faff..b4665842 100644 --- a/src/osax/payload.m +++ b/src/osax/payload.m @@ -55,6 +55,7 @@ extern CGError SLSGetWindowTransform(int cid, uint32_t wid, CGAffineTransform *t); extern CGError SLSSetWindowTransform(int cid, uint32_t wid, CGAffineTransform t); extern CGError SLSOrderWindow(int cid, uint32_t wid, int order, uint32_t rel_wid); +extern void SLSMoveWindowsToManagedSpace(int cid, CFArrayRef window_list, uint64_t sid); extern void SLSManagedDisplaySetCurrentSpace(int cid, CFStringRef display_ref, uint64_t sid); extern uint64_t SLSManagedDisplayGetCurrentSpace(int cid, CFStringRef display_ref); extern CFStringRef SLSCopyManagedDisplayForSpace(int cid, uint64_t sid); @@ -869,6 +870,38 @@ static void do_window_order_in(char *message) CFRelease(transaction); } + +static inline CFArrayRef cfarray_of_cfnumbers(void *values, size_t size, int count, CFNumberType type) +{ + CFNumberRef temp[count]; + + for (int i = 0; i < count; ++i) { + temp[i] = CFNumberCreate(NULL, type, ((char *)values) + (size * i)); + } + + CFArrayRef result = CFArrayCreate(NULL, (const void **)temp, count, &kCFTypeArrayCallBacks); + + for (int i = 0; i < count; ++i) { + CFRelease(temp[i]); + } + + return result; +} + +static void do_window_move_space(char *message) +{ + uint32_t wid; + unpack(wid); + if (!wid) return; + + uint64_t sid; + unpack(sid); + + CFArrayRef window_list_ref = cfarray_of_cfnumbers(&wid, sizeof(uint32_t), 1, kCFNumberSInt32Type); + SLSMoveWindowsToManagedSpace(SLSMainConnectionID(), window_list_ref, sid); + CFRelease(window_list_ref); +} + static void do_handshake(int sockfd) { uint32_t attrib = 0; @@ -949,6 +982,9 @@ static void handle_message(int sockfd, char *message) case SA_OPCODE_WINDOW_ORDER_IN: { do_window_order_in(message); } break; + case SA_OPCODE_WINDOW_MOVE_SPACE: { + do_window_move_space(message); + } break; } } diff --git a/src/sa.h b/src/sa.h index 65a0a096..c7a34f92 100644 --- a/src/sa.h +++ b/src/sa.h @@ -25,5 +25,6 @@ bool scripting_addition_swap_window_proxy_in(struct window_animation *animation_ bool scripting_addition_swap_window_proxy_out(struct window_animation *animation_list, int animation_count); bool scripting_addition_order_window(uint32_t a_wid, int order, uint32_t b_wid); bool scripting_addition_order_window_in(uint32_t *window_list, int window_count); +bool scripting_addition_move_window_to_space(uint32_t wid, uint64_t sid); #endif diff --git a/src/sa.m b/src/sa.m index cbef5f9b..372d614f 100644 --- a/src/sa.m +++ b/src/sa.m @@ -602,6 +602,14 @@ bool scripting_addition_order_window_in(uint32_t *window_list, int window_count) return sa_payload_send(SA_OPCODE_WINDOW_ORDER_IN); } +bool scripting_addition_move_window_to_space(uint32_t wid, uint64_t sid) +{ + sa_payload_init(); + pack(wid); + pack(sid); + return sa_payload_send(SA_OPCODE_WINDOW_MOVE_SPACE); +} + #undef sa_payload_init #undef pack #undef sa_payload_send diff --git a/src/space_manager.c b/src/space_manager.c index abb563ba..f00d5323 100644 --- a/src/space_manager.c +++ b/src/space_manager.c @@ -696,9 +696,13 @@ uint64_t space_manager_active_space(void) void space_manager_move_window_to_space(uint64_t sid, struct window *window) { - CFArrayRef window_list_ref = cfarray_of_cfnumbers(&window->id, sizeof(uint32_t), 1, kCFNumberSInt32Type); - SLSMoveWindowsToManagedSpace(g_connection, window_list_ref, sid); - CFRelease(window_list_ref); + if (workspace_is_macos_sonoma14_5_or_newer()) { + scripting_addition_move_window_to_space(window->id, sid); + } else { + CFArrayRef window_list_ref = cfarray_of_cfnumbers(&window->id, sizeof(uint32_t), 1, kCFNumberSInt32Type); + SLSMoveWindowsToManagedSpace(g_connection, window_list_ref, sid); + CFRelease(window_list_ref); + } } static inline uint64_t space_manager_find_first_user_space_for_display(uint32_t did) diff --git a/src/workspace.h b/src/workspace.h index 50849625..bab0588e 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -31,5 +31,6 @@ void workspace_application_observe_activation_policy(void *context, struct proce int workspace_display_notch_height(uint32_t did); pid_t workspace_get_dock_pid(void); bool workspace_event_handler_begin(void **context); +bool workspace_is_macos_sonoma14_5_or_newer(void); #endif diff --git a/src/workspace.m b/src/workspace.m index 6cbf838e..1e63daf6 100644 --- a/src/workspace.m +++ b/src/workspace.m @@ -14,6 +14,17 @@ bool workspace_event_handler_begin(void **context) return true; } +bool workspace_is_macos_sonoma14_5_or_newer(void) +{ + NSOperatingSystemVersion os_version = [[NSProcessInfo processInfo] operatingSystemVersion]; + + if (os_version.majorVersion > 14) return true; + + if (os_version.majorVersion == 14 && os_version.minorVersion >= 5) return true; + + return false; +} + void *workspace_application_create_running_ns_application(struct process *process) { return [[NSRunningApplication runningApplicationWithProcessIdentifier:process->pid] retain];