mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 08:26:56 +00:00
macOS: When toggling in the quick access terminal move it to the currently active screen
Fixes #9003
This commit is contained in:
parent
9a6cf492aa
commit
982b5156e1
11 changed files with 69 additions and 22 deletions
|
|
@ -155,6 +155,9 @@ Detailed list of changes
|
|||
it was last active on, after full screening some application causes the quick
|
||||
access terminal to appear on the old space (:iss:`8740`)
|
||||
|
||||
- macOS: When toggling open the quick access terminal move it to the currently
|
||||
active monitor (the monitor with the mouse pointer on it) (:iss:`9003`)
|
||||
|
||||
- macOS: Fix closing an OS Window when another OS Window is minimized causing
|
||||
the minimized window to be un-minimized (:iss:`8913`)
|
||||
|
||||
|
|
|
|||
|
|
@ -1971,6 +1971,40 @@ screen_for_window_center(_GLFWwindow *window) {
|
|||
return NSScreen.mainScreen;
|
||||
}
|
||||
|
||||
static NSScreen*
|
||||
active_screen(void) {
|
||||
NSPoint mouseLocation = [NSEvent mouseLocation];
|
||||
NSArray<NSScreen *> *screens = [NSScreen screens];
|
||||
for (NSScreen *screen in screens) {
|
||||
if (NSPointInRect(mouseLocation, [screen frame])) {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
// As a fallback, return the main screen
|
||||
return [NSScreen mainScreen];
|
||||
}
|
||||
|
||||
static bool
|
||||
is_same_screen(NSScreen *screenA, NSScreen * screenB) {
|
||||
if (screenA == screenB) return true;
|
||||
NSDictionary<NSDeviceDescriptionKey, id> *deviceDescriptionA = [screenA deviceDescription];
|
||||
NSDictionary<NSDeviceDescriptionKey, id> *deviceDescriptionB = [screenB deviceDescription];
|
||||
NSNumber *screenNumberA = deviceDescriptionA[@"NSScreenNumber"];
|
||||
NSNumber *screenNumberB = deviceDescriptionB[@"NSScreenNumber"];
|
||||
return [screenNumberA isEqualToNumber:screenNumberB];
|
||||
}
|
||||
|
||||
static void
|
||||
move_window_to_screen(_GLFWwindow *window, NSScreen *target) {
|
||||
NSRect screenFrame = [target visibleFrame];
|
||||
NSRect windowFrame = [window->ns.object frame];
|
||||
CGFloat newX = NSMidX(screenFrame) - (windowFrame.size.width / 2.0);
|
||||
CGFloat newY = NSMidY(screenFrame) - (windowFrame.size.height / 2.0);
|
||||
NSRect newWindowFrame = NSMakeRect(newX, newY, windowFrame.size.width, windowFrame.size.height);
|
||||
[window->ns.object setFrame:newWindowFrame display:NO animate:NO];
|
||||
if (window->ns.layer_shell.is_active) _glfwPlatformSetLayerShellConfig(window, NULL);
|
||||
}
|
||||
|
||||
const GLFWLayerShellConfig*
|
||||
_glfwPlatformGetLayerShellConfig(_GLFWwindow *window) {
|
||||
return &window->ns.layer_shell.config;
|
||||
|
|
@ -2257,10 +2291,18 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
|||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window, bool move_to_active_screen)
|
||||
{
|
||||
const bool is_background = window->ns.layer_shell.is_active && window->ns.layer_shell.config.type == GLFW_LAYER_SHELL_BACKGROUND;
|
||||
NSWindow *nw = window->ns.object;
|
||||
if (move_to_active_screen) {
|
||||
NSScreen *current_screen = screen_for_window_center(window);
|
||||
NSScreen *target_screen = active_screen();
|
||||
if (!is_same_screen(current_screen, target_screen)) {
|
||||
debug_rendering("Moving OS window %llu to active screen\n", window->id);
|
||||
move_window_to_screen(window, target_screen);
|
||||
}
|
||||
}
|
||||
if (is_background) {
|
||||
[nw orderBack:nil];
|
||||
} else {
|
||||
|
|
|
|||
2
glfw/glfw3.h
vendored
2
glfw/glfw3.h
vendored
|
|
@ -3579,7 +3579,7 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
|
|||
*
|
||||
* @ingroup window
|
||||
*/
|
||||
GLFWAPI void glfwShowWindow(GLFWwindow* window);
|
||||
GLFWAPI void glfwShowWindow(GLFWwindow* window, bool move_to_active_screen);
|
||||
|
||||
/*! @brief Hides the specified window.
|
||||
*
|
||||
|
|
|
|||
2
glfw/internal.h
vendored
2
glfw/internal.h
vendored
|
|
@ -740,7 +740,7 @@ monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window);
|
|||
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window, bool move_to_active_screen);
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
|
||||
int _glfwPlatformWindowBell(_GLFWwindow* window);
|
||||
|
|
|
|||
6
glfw/window.c
vendored
6
glfw/window.c
vendored
|
|
@ -279,7 +279,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, G
|
|||
{
|
||||
if (wndconfig.visible)
|
||||
{
|
||||
_glfwPlatformShowWindow(window);
|
||||
_glfwPlatformShowWindow(window, false);
|
||||
#ifndef _GLFW_WAYLAND
|
||||
if (wndconfig.focused)
|
||||
_glfwPlatformFocusWindow(window);
|
||||
|
|
@ -855,7 +855,7 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
|
|||
_glfwPlatformMaximizeWindow(window);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwShowWindow(GLFWwindow* handle)
|
||||
GLFWAPI void glfwShowWindow(GLFWwindow* handle, bool move_to_active_screen)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
|
@ -865,7 +865,7 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
|
|||
if (window->monitor)
|
||||
return;
|
||||
|
||||
_glfwPlatformShowWindow(window);
|
||||
_glfwPlatformShowWindow(window, move_to_active_screen);
|
||||
|
||||
#ifndef _GLFW_WAYLAND
|
||||
if (window->focusOnShow)
|
||||
|
|
|
|||
2
glfw/wl_window.c
vendored
2
glfw/wl_window.c
vendored
|
|
@ -1756,7 +1756,7 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
|||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window, bool move_to_active_screen UNUSED)
|
||||
{
|
||||
if (!window->wl.visible) {
|
||||
if (!window->wl.created) {
|
||||
|
|
|
|||
4
glfw/x11_window.c
vendored
4
glfw/x11_window.c
vendored
|
|
@ -2061,7 +2061,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconf
|
|||
|
||||
if (window->monitor)
|
||||
{
|
||||
_glfwPlatformShowWindow(window);
|
||||
_glfwPlatformShowWindow(window, false);
|
||||
updateWindowMode(window);
|
||||
acquireMonitor(window);
|
||||
}
|
||||
|
|
@ -2458,7 +2458,7 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
|||
XFlush(_glfw.x11.display);
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window, bool move_to_active_screen UNUSED)
|
||||
{
|
||||
if (_glfwPlatformWindowVisible(window))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -957,7 +957,7 @@ class Boss:
|
|||
|
||||
def quick_access_terminal_invoked(self) -> None:
|
||||
for os_window_id in self.os_window_map:
|
||||
toggle_os_window_visibility(os_window_id)
|
||||
toggle_os_window_visibility(os_window_id, move_to_active_screen=True)
|
||||
|
||||
def handle_remote_cmd(self, cmd: memoryview, window: Window | None = None) -> None:
|
||||
response = self._handle_remote_command(cmd, window)
|
||||
|
|
|
|||
|
|
@ -1719,7 +1719,7 @@ def get_docs_ref_map() -> bytes: ...
|
|||
def set_clipboard_data_types(ct: int, mime_types: Tuple[str, ...]) -> None: ...
|
||||
def get_clipboard_mime(ct: int, mime: Optional[str], callback: Callable[[bytes], None]) -> None: ...
|
||||
def run_with_activation_token(func: Callable[[str], None]) -> bool: ...
|
||||
def toggle_os_window_visibility(os_window_id: int, visible: Literal[True, False] = ...) -> bool: ...
|
||||
def toggle_os_window_visibility(os_window_id: int, visible: bool | Literal[-1] = -1, move_to_active_screen: bool = False) -> bool: ...
|
||||
def parse_cli_from_spec(args: list[str], names_map: dict[str, OptionDict], defval_map: dict[str, Any]) -> tuple[dict[str, tuple[Any, bool]], list[str]]: ...
|
||||
def layer_shell_config_for_os_window(os_window_id: int) -> dict[str, Any] | None: ...
|
||||
def set_layer_shell_config(os_window_id: int, cfg: LayerShellConfig) -> bool: ...
|
||||
|
|
|
|||
2
kitty/glfw-wrapper.h
generated
2
kitty/glfw-wrapper.h
generated
|
|
@ -1974,7 +1974,7 @@ typedef void (*glfwMaximizeWindow_func)(GLFWwindow*);
|
|||
GFW_EXTERN glfwMaximizeWindow_func glfwMaximizeWindow_impl;
|
||||
#define glfwMaximizeWindow glfwMaximizeWindow_impl
|
||||
|
||||
typedef void (*glfwShowWindow_func)(GLFWwindow*);
|
||||
typedef void (*glfwShowWindow_func)(GLFWwindow*, bool);
|
||||
GFW_EXTERN glfwShowWindow_func glfwShowWindow_impl;
|
||||
#define glfwShowWindow glfwShowWindow_impl
|
||||
|
||||
|
|
|
|||
22
kitty/glfw.c
22
kitty/glfw.c
|
|
@ -586,9 +586,9 @@ scroll_callback(GLFWwindow *w, double xoffset, double yoffset, int flags, int mo
|
|||
static id_type focus_counter = 0;
|
||||
|
||||
static void
|
||||
set_os_window_visibility(OSWindow *w, int set_visible) {
|
||||
set_os_window_visibility(OSWindow *w, int set_visible, bool move_to_active_screen) {
|
||||
if (set_visible) {
|
||||
glfwShowWindow(w->handle);
|
||||
glfwShowWindow(w->handle, move_to_active_screen);
|
||||
w->needs_render = true;
|
||||
w->keep_rendering_till_swap = 256; // try this many times
|
||||
request_tick_callback();
|
||||
|
|
@ -598,7 +598,7 @@ set_os_window_visibility(OSWindow *w, int set_visible) {
|
|||
static void
|
||||
update_os_window_visibility_based_on_focus(id_type timer_id UNUSED, void*d) {
|
||||
OSWindow * osw = os_window_for_id((uintptr_t)d);
|
||||
if (osw && osw->hide_on_focus_loss && !osw->is_focused) set_os_window_visibility(osw, 0);
|
||||
if (osw && osw->hide_on_focus_loss && !osw->is_focused) set_os_window_visibility(osw, 0, false);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1458,7 +1458,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
if (pret == NULL) return NULL;
|
||||
Py_DECREF(pret);
|
||||
if (x != INT_MIN && y != INT_MIN) glfwSetWindowPos(glfw_window, x, y);
|
||||
if (!global_state.is_apple && !global_state.is_wayland && window_state != WINDOW_HIDDEN) glfwShowWindow(glfw_window);
|
||||
if (!global_state.is_apple && !global_state.is_wayland && window_state != WINDOW_HIDDEN) glfwShowWindow(glfw_window, false);
|
||||
if (global_state.is_wayland || global_state.is_apple) {
|
||||
float n_xscale, n_yscale;
|
||||
double n_xdpi, n_ydpi;
|
||||
|
|
@ -1551,7 +1551,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
if (window_state != WINDOW_NORMAL) change_state_for_os_window(w, window_state);
|
||||
#ifdef __APPLE__
|
||||
// macOS: Show the window after it is ready
|
||||
if (window_state != WINDOW_HIDDEN) glfwShowWindow(glfw_window);
|
||||
if (window_state != WINDOW_HIDDEN) glfwShowWindow(glfw_window, false);
|
||||
#endif
|
||||
w->redraw_count = 1;
|
||||
debug("OS Window created\n");
|
||||
|
|
@ -2550,16 +2550,18 @@ is_layer_shell_supported(PyObject *self UNUSED, PyObject *args UNUSED) {
|
|||
}
|
||||
|
||||
static PyObject*
|
||||
toggle_os_window_visibility(PyObject *self UNUSED, PyObject *args) {
|
||||
toggle_os_window_visibility(PyObject *self UNUSED, PyObject *args, PyObject *kw) {
|
||||
unsigned long long wid;
|
||||
int set_visible = -1;
|
||||
if (!PyArg_ParseTuple(args, "K|p", &wid, &set_visible)) return NULL;
|
||||
int set_visible = -1, move_to_active_screen = 0;
|
||||
static const char* kwlist[] = {"os_window_id", "visible", "move_to_active_screen", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(
|
||||
args, kw, "K|pp", (char**)kwlist, &wid, &set_visible, &move_to_active_screen)) return NULL;
|
||||
OSWindow *w = os_window_for_id(wid);
|
||||
if (!w || !w->handle) Py_RETURN_FALSE;
|
||||
bool is_visible = glfwGetWindowAttrib(w->handle, GLFW_VISIBLE) != 0;
|
||||
if (set_visible == -1) set_visible = !is_visible;
|
||||
else if (set_visible == is_visible) Py_RETURN_FALSE;
|
||||
set_os_window_visibility(w, set_visible);
|
||||
set_os_window_visibility(w, set_visible, move_to_active_screen);
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -2595,7 +2597,7 @@ grab_keyboard(PyObject *self UNUSED, PyObject *action) {
|
|||
static PyMethodDef module_methods[] = {
|
||||
METHODB(set_custom_cursor, METH_VARARGS),
|
||||
METHODB(is_css_pointer_name_valid, METH_O),
|
||||
METHODB(toggle_os_window_visibility, METH_VARARGS),
|
||||
{"toggle_os_window_visibility", (PyCFunction)(void (*) (void))(toggle_os_window_visibility), METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
METHODB(layer_shell_config_for_os_window, METH_O),
|
||||
METHODB(set_layer_shell_config, METH_VARARGS),
|
||||
METHODB(grab_keyboard, METH_O),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue