From f3319b3e01270f3cd6c45654b94687511d149e96 Mon Sep 17 00:00:00 2001 From: koekeishiya Date: Wed, 10 Jul 2019 15:12:24 +0200 Subject: [PATCH] #103 dragging a tiled window across display boundaries using the mouse will trigger a warp upon release --- CHANGELOG.md | 2 ++ src/display_manager.c | 19 ++++++++++++++++ src/display_manager.h | 3 +++ src/event.c | 53 +++++++++++++++++++++++++++++++------------ 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7d31fc5..39d49e96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 +- Dragging a tiled window to another display using the mouse will cause the window to be warped to that display upon release [#103](https://github.com/koekeishiya/yabai/issues/103) ## [1.0.6] - 2019-07-09 ### Changed diff --git a/src/display_manager.c b/src/display_manager.c index af125596..0b94b8df 100644 --- a/src/display_manager.c +++ b/src/display_manager.c @@ -67,6 +67,25 @@ uint32_t display_manager_dock_display_id(void) return result; } +CFStringRef display_manager_cursor_display_uuid(void) +{ + CGPoint cursor; + SLSGetCurrentCursorLocation(g_connection, &cursor); + return SLSCopyBestManagedDisplayForPoint(g_connection, cursor); +} + +uint32_t display_manager_cursor_display_id(void) +{ + CFStringRef uuid = display_manager_cursor_display_uuid(); + if (!uuid) return 0; + + CFUUIDRef uuid_ref = CFUUIDCreateFromString(NULL, uuid); + uint32_t result = CGDisplayGetDisplayIDFromUUID(uuid_ref); + CFRelease(uuid_ref); + CFRelease(uuid); + return result; +} + CFStringRef display_manager_arrangement_display_uuid(int arrangement) { CFStringRef result = NULL; diff --git a/src/display_manager.h b/src/display_manager.h index 9f98604c..13692c86 100644 --- a/src/display_manager.h +++ b/src/display_manager.h @@ -2,6 +2,7 @@ #define DISPLAY_MANAGER_H extern CFStringRef SLSCopyActiveMenuBarDisplayIdentifier(int cid); +extern CFStringRef SLSCopyBestManagedDisplayForPoint(int cid, CGPoint point); extern bool SLSManagedDisplayIsAnimating(int cid, CFStringRef uuid); extern CGError SLSGetMenuBarAutohideEnabled(int cid, int *enabled); extern CGError SLSGetRevealedMenuBarBounds(CGRect *rect, int cid, uint64_t sid); @@ -26,6 +27,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_arrangement_display_uuid(int arrangement); uint32_t display_manager_arrangement_display_id(int arrangement); uint32_t display_manager_prev_display_id(uint32_t did); diff --git a/src/event.c b/src/event.c index f7de486e..730cb43d 100644 --- a/src/event.c +++ b/src/event.c @@ -583,6 +583,10 @@ static EVENT_CALLBACK(EVENT_HANDLER_WINDOW_RESIZED) debug("%s: %s %d\n", __FUNCTION__, window->application->name, window->id); + if (g_mouse_state.current_action == MOUSE_MODE_MOVE && g_mouse_state.window == window) { + g_mouse_state.window_frame.size = window_ax_frame(g_mouse_state.window).size; + } + #if 0 struct view *view = window_manager_find_managed_window(&g_window_manager, window); if (view) view_flush(view); @@ -828,8 +832,8 @@ static EVENT_CALLBACK(EVENT_HANDLER_MOUSE_UP) CGPoint point = CGEventGetLocation(context); debug("%s: %.2f, %.2f\n", __FUNCTION__, point.x, point.y); - struct view *view = window_manager_find_managed_window(&g_window_manager, g_mouse_state.window); - if ((g_mouse_state.current_action != MOUSE_MODE_RESIZE) && (view && view->layout == VIEW_BSP)) { + struct view *src_view = window_manager_find_managed_window(&g_window_manager, g_mouse_state.window); + if ((g_mouse_state.current_action != MOUSE_MODE_RESIZE) && (src_view && src_view->layout == VIEW_BSP)) { CGRect frame = window_ax_frame(g_mouse_state.window); float dx = frame.origin.x - g_mouse_state.window_frame.origin.x; float dy = frame.origin.y - g_mouse_state.window_frame.origin.y; @@ -844,21 +848,40 @@ 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()); + 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); if (!window) window = window_manager_find_window_at_point(&g_window_manager, point); - struct window_node *a_node = view_find_window_node(view->root, g_mouse_state.window->id); - struct window_node *b_node = window ? view_find_window_node(view->root, window->id) : NULL; - - if (a_node && b_node) { - a_node->window_id = window->id; - b_node->window_id = g_mouse_state.window->id; - window_node_flush(a_node); - window_node_flush(b_node); - a_node->zoom = NULL; - b_node->zoom = NULL; - } else if (a_node) { - window_node_flush(a_node); - a_node->zoom = NULL; + if (window == g_mouse_state.window) window = NULL; + + struct window_node *a_node = view_find_window_node(src_view->root, g_mouse_state.window->id); + struct window_node *b_node = window ? view_find_window_node(dst_view->root, window->id) : NULL; + + if (src_view->sid == dst_view->sid) { + if (a_node && b_node) { + a_node->window_id = window->id; + b_node->window_id = g_mouse_state.window->id; + window_node_flush(a_node); + window_node_flush(b_node); + a_node->zoom = NULL; + b_node->zoom = NULL; + } else { + window_node_flush(a_node); + a_node->zoom = NULL; + } + } else { + space_manager_untile_window(&g_space_manager, src_view, g_mouse_state.window); + window_manager_remove_managed_window(&g_window_manager, g_mouse_state.window->id); + window_manager_purify_window(&g_window_manager, g_mouse_state.window); + + if (a_node && b_node) { + struct view *view = space_manager_tile_window_on_space_with_insertion_point(&g_space_manager, g_mouse_state.window, dst_view->sid, window->id); + window_manager_add_managed_window(&g_window_manager, g_mouse_state.window, view); + } else { + struct view *view = space_manager_tile_window_on_space(&g_space_manager, g_mouse_state.window, dst_view->sid); + window_manager_add_managed_window(&g_window_manager, g_mouse_state.window, view); + } } } else { if (did_change_p) {