| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 | 
							- #include "window-utils.h"
 
- #include <util/platform.h>
 
- #define WINDOW_NAME   ((NSString *) kCGWindowName)
 
- #define WINDOW_NUMBER ((NSString *) kCGWindowNumber)
 
- #define OWNER_NAME    ((NSString *) kCGWindowOwnerName)
 
- #define OWNER_PID     ((NSString *) kCGWindowOwnerPID)
 
- static NSComparator win_info_cmp = ^(NSDictionary *o1, NSDictionary *o2) {
 
-     NSComparisonResult res = [o1[OWNER_NAME] compare:o2[OWNER_NAME]];
 
-     if (res != NSOrderedSame)
 
-         return res;
 
-     res = [o1[OWNER_PID] compare:o2[OWNER_PID]];
 
-     if (res != NSOrderedSame)
 
-         return res;
 
-     res = [o1[WINDOW_NAME] compare:o2[WINDOW_NAME]];
 
-     if (res != NSOrderedSame)
 
-         return res;
 
-     return [o1[WINDOW_NUMBER] compare:o2[WINDOW_NUMBER]];
 
- };
 
- NSArray *enumerate_windows(void)
 
- {
 
-     NSArray *arr = (NSArray *) CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
 
-     [arr autorelease];
 
-     return [arr sortedArrayUsingComparator:win_info_cmp];
 
- }
 
- #define WAIT_TIME_MS 500
 
- #define WAIT_TIME_US WAIT_TIME_MS * 1000
 
- #define WAIT_TIME_NS WAIT_TIME_US * 1000
 
- bool find_window(cocoa_window_t cw, obs_data_t *settings, bool force)
 
- {
 
-     if (!force && cw->next_search_time > os_gettime_ns())
 
-         return false;
 
-     cw->next_search_time = os_gettime_ns() + WAIT_TIME_NS;
 
-     pthread_mutex_lock(&cw->name_lock);
 
-     if (!cw->window_name.length && !cw->owner_name.length)
 
-         goto invalid_name;
 
-     for (NSDictionary *dict in enumerate_windows()) {
 
-         if (![cw->owner_name isEqualToString:dict[OWNER_NAME]])
 
-             continue;
 
-         if (![cw->window_name isEqualToString:dict[WINDOW_NAME]])
 
-             continue;
 
-         pthread_mutex_unlock(&cw->name_lock);
 
-         NSNumber *window_id = (NSNumber *) dict[WINDOW_NUMBER];
 
-         cw->window_id = window_id.intValue;
 
-         NSNumber *owner_pid = (NSNumber *) dict[OWNER_PID];
 
-         cw->owner_pid = owner_pid.intValue;
 
-         obs_data_set_int(settings, "window", cw->window_id);
 
-         obs_data_set_int(settings, "owner_pid", cw->owner_pid);
 
-         return true;
 
-     }
 
- invalid_name:
 
-     pthread_mutex_unlock(&cw->name_lock);
 
-     return false;
 
- }
 
- void init_window(cocoa_window_t cw, obs_data_t *settings)
 
- {
 
-     pthread_mutex_init(&cw->name_lock, NULL);
 
-     cw->owner_name = @(obs_data_get_string(settings, "owner_name"));
 
-     cw->window_name = @(obs_data_get_string(settings, "window_name"));
 
-     [cw->owner_name retain];
 
-     [cw->window_name retain];
 
-     // Find initial window.
 
-     pthread_mutex_lock(&cw->name_lock);
 
-     if (!cw->window_name.length && !cw->owner_name.length)
 
-         goto invalid_name;
 
-     NSNumber *owner_pid = @(obs_data_get_int(settings, "owner_pid"));
 
-     NSNumber *window_id = @(obs_data_get_int(settings, "window"));
 
-     for (NSDictionary *dict in enumerate_windows()) {
 
-         bool owner_names_match = [cw->owner_name isEqualToString:dict[OWNER_NAME]];
 
-         bool ids_match = [owner_pid isEqualToNumber:dict[OWNER_PID]] && [window_id isEqualToNumber:dict[WINDOW_NUMBER]];
 
-         bool window_names_match = [cw->window_name isEqualToString:dict[WINDOW_NAME]];
 
-         if (owner_names_match && (ids_match || window_names_match)) {
 
-             pthread_mutex_unlock(&cw->name_lock);
 
-             cw->window_id = [dict[WINDOW_NUMBER] intValue];
 
-             cw->owner_pid = [dict[OWNER_PID] intValue];
 
-             obs_data_set_int(settings, "window", cw->window_id);
 
-             obs_data_set_int(settings, "owner_pid", cw->owner_pid);
 
-             return;
 
-         }
 
-     }
 
- invalid_name:
 
-     pthread_mutex_unlock(&cw->name_lock);
 
-     return;
 
- }
 
- void destroy_window(cocoa_window_t cw)
 
- {
 
-     pthread_mutex_destroy(&cw->name_lock);
 
-     [cw->owner_name release];
 
-     [cw->window_name release];
 
- }
 
- void update_window(cocoa_window_t cw, obs_data_t *settings)
 
- {
 
-     pthread_mutex_lock(&cw->name_lock);
 
-     [cw->owner_name release];
 
-     [cw->window_name release];
 
-     cw->owner_name = @(obs_data_get_string(settings, "owner_name"));
 
-     cw->window_name = @(obs_data_get_string(settings, "window_name"));
 
-     [cw->owner_name retain];
 
-     [cw->window_name retain];
 
-     pthread_mutex_unlock(&cw->name_lock);
 
-     cw->owner_pid = (int) obs_data_get_int(settings, "owner_pid");
 
-     cw->window_id = (unsigned int) obs_data_get_int(settings, "window");
 
- }
 
- static inline const char *make_name(NSString *owner, NSString *name)
 
- {
 
-     if (!owner.length)
 
-         return "";
 
-     NSString *str = [NSString stringWithFormat:@"[%@] %@", owner, name];
 
-     return str.UTF8String;
 
- }
 
- static inline NSDictionary *find_window_dict(NSArray *arr, int window_id)
 
- {
 
-     for (NSDictionary *dict in arr) {
 
-         NSNumber *wid = (NSNumber *) dict[WINDOW_NUMBER];
 
-         if (wid.intValue == window_id)
 
-             return dict;
 
-     }
 
-     return nil;
 
- }
 
- static inline bool window_changed_internal(obs_property_t *p, obs_data_t *settings)
 
- {
 
-     int window_id = (int) obs_data_get_int(settings, "window");
 
-     NSString *window_owner = @(obs_data_get_string(settings, "owner_name"));
 
-     NSString *window_name = @(obs_data_get_string(settings, "window_name"));
 
-     NSDictionary *win_info = @ {
 
-         OWNER_NAME: window_owner,
 
-         WINDOW_NAME: window_name,
 
-     };
 
-     NSArray *arr = enumerate_windows();
 
-     bool show_empty_names = obs_data_get_bool(settings, "show_empty_names");
 
-     NSDictionary *cur = find_window_dict(arr, window_id);
 
-     bool window_found = cur != nil;
 
-     bool window_added = window_found;
 
-     obs_property_list_clear(p);
 
-     for (NSDictionary *dict in arr) {
 
-         NSString *owner = (NSString *) dict[OWNER_NAME];
 
-         NSString *name = (NSString *) dict[WINDOW_NAME];
 
-         NSNumber *wid = (NSNumber *) dict[WINDOW_NUMBER];
 
-         if (!window_added && win_info_cmp(win_info, dict) == NSOrderedAscending) {
 
-             window_added = true;
 
-             size_t idx = obs_property_list_add_int(p, make_name(window_owner, window_name), window_id);
 
-             obs_property_list_item_disable(p, idx, true);
 
-         }
 
-         if (!show_empty_names && !name.length && window_id != wid.intValue)
 
-             continue;
 
-         obs_property_list_add_int(p, make_name(owner, name), wid.intValue);
 
-     }
 
-     if (!window_added) {
 
-         size_t idx = obs_property_list_add_int(p, make_name(window_owner, window_name), window_id);
 
-         obs_property_list_item_disable(p, idx, true);
 
-     }
 
-     if (!window_found)
 
-         return true;
 
-     NSString *owner = (NSString *) cur[OWNER_NAME];
 
-     NSString *window = (NSString *) cur[WINDOW_NAME];
 
-     obs_data_set_string(settings, "owner_name", owner.UTF8String);
 
-     obs_data_set_string(settings, "window_name", window.UTF8String);
 
-     return true;
 
- }
 
- static bool window_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings)
 
- {
 
-     UNUSED_PARAMETER(props);
 
-     @autoreleasepool {
 
-         return window_changed_internal(p, settings);
 
-     }
 
- }
 
- static bool toggle_empty_names(obs_properties_t *props, obs_property_t *p, obs_data_t *settings)
 
- {
 
-     UNUSED_PARAMETER(p);
 
-     return window_changed(props, obs_properties_get(props, "window"), settings);
 
- }
 
- void window_defaults(obs_data_t *settings)
 
- {
 
-     obs_data_set_default_int(settings, "window", kCGNullWindowID);
 
-     obs_data_set_default_bool(settings, "show_empty_names", false);
 
- }
 
- void add_window_properties(obs_properties_t *props)
 
- {
 
-     obs_property_t *window_list = obs_properties_add_list(props, "window", obs_module_text("WindowUtils.Window"),
 
-                                                           OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
 
-     obs_property_set_modified_callback(window_list, window_changed);
 
-     obs_property_t *empty =
 
-         obs_properties_add_bool(props, "show_empty_names", obs_module_text("WindowUtils.ShowEmptyNames"));
 
-     obs_property_set_modified_callback(empty, toggle_empty_names);
 
- }
 
- void show_window_properties(obs_properties_t *props, bool show)
 
- {
 
-     obs_property_set_visible(obs_properties_get(props, "window"), show);
 
-     obs_property_set_visible(obs_properties_get(props, "show_empty_names"), show);
 
- }
 
- CGDirectDisplayID get_display_migrate_settings(obs_data_t *settings)
 
- {
 
-     bool legacy_display_id = obs_data_has_user_value(settings, "display");
 
-     bool new_display_id = obs_data_has_user_value(settings, "display_uuid");
 
-     if (legacy_display_id && !new_display_id) {
 
-         CGDirectDisplayID display_id = (CGDirectDisplayID) obs_data_get_int(settings, "display");
 
-         CFUUIDRef display_uuid = CGDisplayCreateUUIDFromDisplayID(display_id);
 
-         if (display_uuid) {
 
-             CFStringRef uuid_string = CFUUIDCreateString(kCFAllocatorDefault, display_uuid);
 
-             obs_data_set_string(settings, "display_uuid", CFStringGetCStringPtr(uuid_string, kCFStringEncodingUTF8));
 
-             obs_data_erase(settings, "display");
 
-             CFRelease(uuid_string);
 
-             CFRelease(display_uuid);
 
-         } else {
 
-             return 0;
 
-         }
 
-     } else if (legacy_display_id && new_display_id) {
 
-         obs_data_erase(settings, "display");
 
-     }
 
-     const char *display_uuid = obs_data_get_string(settings, "display_uuid");
 
-     if (display_uuid) {
 
-         CFStringRef uuid_string = CFStringCreateWithCString(kCFAllocatorDefault, display_uuid, kCFStringEncodingUTF8);
 
-         CFUUIDRef uuid_ref = CFUUIDCreateFromString(kCFAllocatorDefault, uuid_string);
 
-         CGDirectDisplayID display = CGDisplayGetDisplayIDFromUUID(uuid_ref);
 
-         CFRelease(uuid_string);
 
-         CFRelease(uuid_ref);
 
-         return display;
 
-     } else {
 
-         return 0;
 
-     }
 
- }
 
 
  |