Skip to content

Commit

Permalink
#459 ffm is now able to focus a display upon hover
Browse files Browse the repository at this point in the history
  • Loading branch information
koekeishiya committed Jun 5, 2020
1 parent 3a59e49 commit 20bef34
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 74 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Changed
- If *focus follows mouse* is enabled, moving the cursor to a different display will now focus that display even if it is empty [#459](https://github.com/koekeishiya/yabai/issues/459)

## [3.1.0] - 2020-06-05
### Added
Expand Down
17 changes: 17 additions & 0 deletions src/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,17 @@ CFStringRef display_uuid(uint32_t did)
return uuid_str;
}

uint32_t display_id(CFStringRef uuid)
{
CFUUIDRef uuid_ref = CFUUIDCreateFromString(NULL, uuid);
if (!uuid_ref) return 0;

uint32_t did = CGDisplayGetDisplayIDFromUUID(uuid_ref);
CFRelease(uuid_ref);

return did;
}

CGRect display_bounds(uint32_t did)
{
return CGDisplayBounds(did);
Expand Down Expand Up @@ -125,6 +136,12 @@ CGRect display_bounds_constrained(uint32_t did)
return frame;
}

CGPoint display_center(uint32_t did)
{
CGRect bounds = display_bounds(did);
return (CGPoint) { bounds.origin.x + bounds.size.width/2, bounds.origin.y + bounds.size.height/2 };
}

uint64_t display_space_id(uint32_t did)
{
CFStringRef uuid = display_uuid(did);
Expand Down
2 changes: 2 additions & 0 deletions src/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ extern uint64_t SLSManagedDisplayGetCurrentSpace(int cid, CFStringRef uuid);

void display_serialize(FILE *rsp, uint32_t did);
CFStringRef display_uuid(uint32_t did);
uint32_t display_id(CFStringRef uuid);
CGRect display_bounds(uint32_t did);
CGRect display_bounds_constrained(uint32_t did);
CGPoint display_center(uint32_t did);
uint64_t display_space_id(uint32_t did);
int display_space_count(uint32_t did);
uint64_t *display_space_list(uint32_t did, int *count);
Expand Down
110 changes: 46 additions & 64 deletions src/display_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ CFStringRef display_manager_active_display_uuid(void)

uint32_t display_manager_active_display_id(void)
{
uint32_t result = 0;
CFStringRef uuid = display_manager_active_display_uuid();
CFUUIDRef uuid_ref = CFUUIDCreateFromString(NULL, uuid);
result = CGDisplayGetDisplayIDFromUUID(uuid_ref);
CFRelease(uuid_ref);
assert(uuid);

uint32_t result = display_id(uuid);
CFRelease(uuid);

return result;
}

Expand All @@ -59,29 +59,25 @@ uint32_t display_manager_dock_display_id(void)
CFStringRef uuid = display_manager_dock_display_uuid();
if (!uuid) return 0;

CFUUIDRef uuid_ref = CFUUIDCreateFromString(NULL, uuid);
uint32_t result = CGDisplayGetDisplayIDFromUUID(uuid_ref);
CFRelease(uuid_ref);
uint32_t result = display_id(uuid);
CFRelease(uuid);

return result;
}

CFStringRef display_manager_cursor_display_uuid(void)
CFStringRef display_manager_point_display_uuid(CGPoint point)
{
CGPoint cursor;
SLSGetCurrentCursorLocation(g_connection, &cursor);
return SLSCopyBestManagedDisplayForPoint(g_connection, cursor);
return SLSCopyBestManagedDisplayForPoint(g_connection, point);
}

uint32_t display_manager_cursor_display_id(void)
uint32_t display_manager_point_display_id(CGPoint point)
{
CFStringRef uuid = display_manager_cursor_display_uuid();
CFStringRef uuid = display_manager_point_display_uuid(point);
if (!uuid) return 0;

CFUUIDRef uuid_ref = CFUUIDCreateFromString(NULL, uuid);
uint32_t result = CGDisplayGetDisplayIDFromUUID(uuid_ref);
CFRelease(uuid_ref);
uint32_t result = display_id(uuid);
CFRelease(uuid);

return result;
}

Expand Down Expand Up @@ -110,9 +106,7 @@ uint32_t display_manager_arrangement_display_id(int arrangement)
int index = arrangement - 1;

if (in_range_ie(index, 0, count)) {
CFUUIDRef uuid_ref = CFUUIDCreateFromString(NULL, CFArrayGetValueAtIndex(displays, index));
result = CGDisplayGetDisplayIDFromUUID(uuid_ref);
CFRelease(uuid_ref);
result = display_id(CFArrayGetValueAtIndex(displays, index));
}

CFRelease(displays);
Expand Down Expand Up @@ -184,8 +178,11 @@ CGRect display_manager_dock_rect(void)
bool display_manager_active_display_is_animating(void)
{
CFStringRef uuid = display_manager_active_display_uuid();
assert(uuid);

bool result = SLSManagedDisplayIsAnimating(g_connection, uuid);
CFRelease(uuid);

return result;
}

Expand All @@ -196,6 +193,7 @@ bool display_manager_display_is_animating(uint32_t did)

bool result = SLSManagedDisplayIsAnimating(g_connection, uuid);
CFRelease(uuid);

return result;
}

Expand Down Expand Up @@ -237,57 +235,41 @@ static AXUIElementRef display_manager_find_element_at_point(CGPoint point)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
void display_manager_focus_display(uint32_t did)
void display_manager_focus_display_with_point(uint32_t did, CGPoint point)
{
int window_count;
uint32_t *window_list;
struct window *window;

CGRect bounds;
CGPoint point;
AXUIElementRef element_ref;

window_list = space_window_list(display_space_id(did), &window_count, false);
if (!window_list) goto fallback;

for (int i = 0; i < window_count; ++i) {
window = window_manager_find_window(&g_window_manager, window_list[i]);
if (!window || !window_is_standard(window)) continue;
int element_connection;
ProcessSerialNumber element_psn;

AXUIElementRef element_ref = display_manager_find_element_at_point(point);
if (!element_ref) goto click;

uint32_t element_id = ax_window_id(element_ref);
if (!element_id) goto err_ref;

SLSGetWindowOwner(g_connection, element_id, &element_connection);
SLSGetConnectionPSN(element_connection, &element_psn);
window_manager_focus_window_with_raise(&element_psn, element_id, element_ref);
CFRelease(element_ref);
goto out;

err_ref:
CFRelease(element_ref);
click:
CGPostMouseEvent(point, true, 1, true);
CGPostMouseEvent(point, true, 1, false);
out:;
}
#pragma clang diagnostic pop

void display_manager_focus_display(uint32_t did)
{
struct window *window = window_manager_find_window_on_space_by_rank(&g_window_manager, display_space_id(did), 1);
if (window) {
window_manager_focus_window_with_raise(&window->application->psn, window->id, window->ref);
free(window_list);
goto out;
}

free(window_list);

fallback:
bounds = display_bounds(did);
point = (CGPoint) { bounds.origin.x + bounds.size.width / 2, bounds.origin.y + bounds.size.height / 2 };
element_ref = display_manager_find_element_at_point(point);

if (element_ref) {
uint32_t element_id = ax_window_id(element_ref);

if (element_id) {
int element_connection;
ProcessSerialNumber element_psn;
SLSGetWindowOwner(g_connection, element_id, &element_connection);
SLSGetConnectionPSN(element_connection, &element_psn);
window_manager_focus_window_with_raise(&element_psn, element_id, element_ref);
} else {
CGPostMouseEvent(point, true, 1, true);
CGPostMouseEvent(point, true, 1, false);
}

CFRelease(element_ref);
} else {
CGPostMouseEvent(point, true, 1, true);
CGPostMouseEvent(point, true, 1, false);
display_manager_focus_display_with_point(did, display_center(did));
}
out:;
}
#pragma clang diagnostic pop

bool display_manager_begin(struct display_manager *dm)
{
Expand Down
5 changes: 3 additions & 2 deletions src/display_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ CFStringRef display_manager_active_display_uuid(void);
uint32_t display_manager_active_display_id(void);
CFStringRef display_manager_dock_display_uuid(void);
uint32_t display_manager_dock_display_id(void);
CFStringRef display_manager_cursor_display_uuid(void);
uint32_t display_manager_cursor_display_id(void);
CFStringRef display_manager_point_display_uuid(CGPoint point);
uint32_t display_manager_point_display_id(CGPoint point);
CFStringRef display_manager_arrangement_display_uuid(int arrangement);
uint32_t display_manager_arrangement_display_id(int arrangement);
uint32_t display_manager_prev_display_id(uint32_t did);
Expand All @@ -62,6 +62,7 @@ bool display_manager_active_display_is_animating(void);
bool display_manager_display_is_animating(uint32_t did);
uint32_t display_manager_active_display_count(void);
uint32_t *display_manager_active_display_list(uint32_t *count);
void display_manager_focus_display_with_point(uint32_t did, CGPoint point);
void display_manager_focus_display(uint32_t did);
bool display_manager_begin(struct display_manager *dm);
bool display_manager_end(void);
Expand Down
23 changes: 16 additions & 7 deletions src/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ static EVENT_CALLBACK(EVENT_HANDLER_MOUSE_UP)
bool did_change_s = did_change_w || did_change_h;

if (did_change_p && !did_change_s) {
uint64_t cursor_sid = display_space_id(display_manager_cursor_display_id());
uint64_t cursor_sid = display_space_id(display_manager_point_display_id(point));
struct view *dst_view = space_manager_find_view(&g_space_manager, cursor_sid);

struct window *window = window_manager_find_window_at_point_filtering_window(&g_window_manager, point, g_mouse_state.window->id);
Expand Down Expand Up @@ -1012,15 +1012,24 @@ static EVENT_CALLBACK(EVENT_HANDLER_MOUSE_MOVED)
g_mouse_state.last_moved_time = event_time;

struct window *window = window_manager_find_window_at_point(&g_window_manager, point);
if (!window || window->id == g_window_manager.focused_window_id) return EVENT_SUCCESS;
if (!window_level_is_standard(window) || !window_is_standard(window)) return EVENT_SUCCESS;
if (window) {
if (window->id == g_window_manager.focused_window_id) return EVENT_SUCCESS;

g_mouse_state.ffm_window_id = window->id;
if (!window_level_is_standard(window)) return EVENT_SUCCESS;
if (!window_is_standard(window)) return EVENT_SUCCESS;

if (g_window_manager.ffm_mode == FFM_AUTOFOCUS) {
window_manager_focus_window_without_raise(&window->application->psn, window->id);
g_mouse_state.ffm_window_id = window->id;

if (g_window_manager.ffm_mode == FFM_AUTOFOCUS) {
window_manager_focus_window_without_raise(&window->application->psn, window->id);
} else {
window_manager_focus_window_with_raise(&window->application->psn, window->id, window->ref);
}
} else {
window_manager_focus_window_with_raise(&window->application->psn, window->id, window->ref);
uint32_t cursor_did = display_manager_point_display_id(point);
if (g_display_manager.current_display_id != cursor_did) {
display_manager_focus_display_with_point(cursor_did, point);
}
}

return EVENT_SUCCESS;
Expand Down
2 changes: 1 addition & 1 deletion src/window_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ void window_manager_purify_window(struct window_manager *wm, struct window *wind
socket_close(sockfd);
}

static struct window *window_manager_find_window_on_space_by_rank(struct window_manager *wm, uint64_t sid, int rank)
struct window *window_manager_find_window_on_space_by_rank(struct window_manager *wm, uint64_t sid, int rank)
{
int count;
uint32_t *window_list = space_window_list(sid, &count, false);
Expand Down
1 change: 1 addition & 0 deletions src/window_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ void window_manager_move_window_cgs(struct window *window, float x, float y);
void window_manager_resize_window(struct window *window, float width, float height);
enum window_op_error window_manager_adjust_window_ratio(struct window_manager *wm, struct window *window, int action, float ratio);
void window_manager_set_window_frame(struct window *window, float x, float y, float width, float height);
struct window *window_manager_find_window_on_space_by_rank(struct window_manager *wm, uint64_t sid, int rank);
struct window *window_manager_find_window_at_point_filtering_window(struct window_manager *wm, CGPoint point, uint32_t filter_wid);
struct window *window_manager_find_window_at_point(struct window_manager *wm, CGPoint point);
struct window *window_manager_find_window_below_cursor(struct window_manager *wm);
Expand Down

0 comments on commit 20bef34

Please sign in to comment.