mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 22:28:24 +02:00
@@ -109,6 +109,8 @@ Detailed list of changes
|
||||
- Remote control: Allow modifying desktop panels and showing/hiding OS Windows
|
||||
using the `kitten @ resize-os-window` command (:iss:`8550`)
|
||||
|
||||
- Allow starting kitty with the OS window hidden via :option:`kitty --start-as`=hidden useful for single instance mode (:iss:`3466`)
|
||||
|
||||
- Allow configuring the mouse unhide behavior when using :opt:`mouse_hide_wait` (:pull:`8508`)
|
||||
|
||||
- diff kitten: Add half page and full page scroll vim-like bindings (:pull:`8514`)
|
||||
|
||||
@@ -88,6 +88,11 @@ position of the quick access panel. In particular, the :option:`kitty +kitten pa
|
||||
:option:`kitty +kitten panel --override` options can be used to theme the terminal appropriately,
|
||||
making it look different from regular kitty terminal instances.
|
||||
|
||||
.. note::
|
||||
If you want to start the quake terminal hidden, use
|
||||
:option:`kitty +kitten panel --start-as-hidden`, useful if you are starting it in the background
|
||||
during computer startup.
|
||||
|
||||
|
||||
Controlling panels via remote control
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
2
glfw/wl_platform.h
vendored
2
glfw/wl_platform.h
vendored
@@ -165,7 +165,7 @@ enum _GLFWWaylandAxisEvent {
|
||||
typedef struct _GLFWwindowWayland
|
||||
{
|
||||
int width, height;
|
||||
bool visible;
|
||||
bool visible, created;
|
||||
bool hovered;
|
||||
bool transparent;
|
||||
struct wl_surface* surface;
|
||||
|
||||
22
glfw/wl_window.c
vendored
22
glfw/wl_window.c
vendored
@@ -1143,6 +1143,7 @@ create_layer_shell_surface(_GLFWwindow *window) {
|
||||
layer_set_properties(window);
|
||||
commit_window_surface(window);
|
||||
wl_display_roundtrip(_glfw.wl.display);
|
||||
window->wl.created = true;
|
||||
#undef ls
|
||||
return true;
|
||||
}
|
||||
@@ -1214,6 +1215,7 @@ create_window_desktop_surface(_GLFWwindow* window)
|
||||
|
||||
commit_window_surface(window);
|
||||
wl_display_roundtrip(_glfw.wl.display);
|
||||
window->wl.created = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1413,22 +1415,17 @@ int _glfwPlatformCreateWindow(
|
||||
if (!createSurface(window, wndconfig)) return false;
|
||||
if (wndconfig->title) window->wl.title = _glfw_strdup(wndconfig->title);
|
||||
if (wndconfig->maximized) window->wl.maximize_on_first_show = true;
|
||||
|
||||
if (wndconfig->visible)
|
||||
{
|
||||
if (!create_window_desktop_surface(window))
|
||||
return false;
|
||||
|
||||
if (wndconfig->visible) {
|
||||
if (!create_window_desktop_surface(window)) return false;
|
||||
window->wl.visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
window->wl.visible = false;
|
||||
window->wl.xdg.surface = NULL;
|
||||
window->wl.xdg.toplevel = NULL;
|
||||
window->wl.layer_shell.zwlr_layer_surface_v1 = NULL;
|
||||
window->wl.visible = false;
|
||||
}
|
||||
|
||||
|
||||
window->wl.currentCursor = NULL;
|
||||
// Don't set window->wl.cursorTheme to NULL here.
|
||||
|
||||
@@ -1722,10 +1719,15 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->wl.visible) {
|
||||
if (!window->wl.created) {
|
||||
create_window_desktop_surface(window);
|
||||
window->wl.visible = true;
|
||||
} else {
|
||||
// workaround for kwin layer shell bug: https://bugs.kde.org/show_bug.cgi?id=503121
|
||||
if (is_layer_shell(window)) layer_set_properties(window);
|
||||
window->wl.visible = true;
|
||||
commit_window_surface(window);
|
||||
}
|
||||
debug("Window %llu mapped waiting for configure event from compositor\n", window->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +172,11 @@ When set and using :option:`--single-instance` will toggle the visibility of the
|
||||
existing panel rather than creating a new one.
|
||||
|
||||
|
||||
--start-as-hidden
|
||||
type=bool-set
|
||||
Start in hidden mode, useful with :option:`--toggle-visibility`.
|
||||
|
||||
|
||||
--debug-rendering
|
||||
type=bool-set
|
||||
For internal debugging use.
|
||||
@@ -338,6 +343,8 @@ def main(sys_args: list[str]) -> None:
|
||||
sys.argv.extend(('--class', args.cls))
|
||||
if args.name:
|
||||
sys.argv.extend(('--name', args.name))
|
||||
if args.start_as_hidden:
|
||||
sys.argv.append('--start-as=hidden')
|
||||
for override in args.override:
|
||||
sys.argv.extend(('--override', override))
|
||||
sys.argv.append('--override=linux_display_server=auto')
|
||||
|
||||
@@ -959,13 +959,14 @@ previous instance is found, then :italic:`{appname}` will wait anyway,
|
||||
regardless of this option.
|
||||
|
||||
|
||||
{listen_on_defn}
|
||||
{listen_on_defn} To start in headless mode,
|
||||
without an actual window, use :option:`{appname} --start-as`=hidden.
|
||||
|
||||
|
||||
--start-as
|
||||
type=choices
|
||||
default=normal
|
||||
choices=normal,fullscreen,maximized,minimized
|
||||
choices=normal,fullscreen,maximized,minimized,hidden
|
||||
Control how the initial kitty window is created.
|
||||
|
||||
|
||||
|
||||
@@ -311,6 +311,7 @@ WINDOW_NORMAL: int = 0
|
||||
WINDOW_FULLSCREEN: int
|
||||
WINDOW_MAXIMIZED: int
|
||||
WINDOW_MINIMIZED: int
|
||||
WINDOW_HIDDEN: int
|
||||
TEXT_SIZE_CODE: int
|
||||
TOP_EDGE: int
|
||||
BOTTOM_EDGE: int
|
||||
|
||||
20
kitty/glfw.c
20
kitty/glfw.c
@@ -989,6 +989,8 @@ change_state_for_os_window(OSWindow *w, int state) {
|
||||
if (is_os_window_fullscreen(w)) toggle_fullscreen_for_os_window(w);
|
||||
else glfwRestoreWindow(w->handle);
|
||||
break;
|
||||
case WINDOW_HIDDEN:
|
||||
glfwHideWindow(w->handle); break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1229,8 +1231,12 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "OOsss|OOOOpO", (char**)kwlist,
|
||||
&get_window_size, &pre_show_callback, &title, &wm_class_name, &wm_class_class, &optional_window_state, &load_programs, &optional_x, &optional_y, &disallow_override_title, &layer_shell_config)) return NULL;
|
||||
GLFWLayerShellConfig *lsc = NULL, lsc_stack = {0};
|
||||
|
||||
if (optional_window_state && optional_window_state != Py_None) {
|
||||
if (!PyLong_Check(optional_window_state)) { PyErr_SetString(PyExc_TypeError, "window_state must be an int"); return NULL; }
|
||||
window_state = (int) PyLong_AsLong(optional_window_state);
|
||||
}
|
||||
if (layer_shell_config && layer_shell_config != Py_None ) {
|
||||
if (window_state != WINDOW_HIDDEN) window_state = WINDOW_NORMAL;
|
||||
#ifdef __APPLE__
|
||||
lsc = &lsc_stack;
|
||||
#else
|
||||
@@ -1243,10 +1249,9 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (optional_window_state && optional_window_state != Py_None) { if (!PyLong_Check(optional_window_state)) { PyErr_SetString(PyExc_TypeError, "window_state must be an int"); return NULL; } window_state = (int) PyLong_AsLong(optional_window_state); }
|
||||
if (optional_x && optional_x != Py_None) { if (!PyLong_Check(optional_x)) { PyErr_SetString(PyExc_TypeError, "x must be an int"); return NULL;} x = (int)PyLong_AsLong(optional_x); }
|
||||
if (optional_y && optional_y != Py_None) { if (!PyLong_Check(optional_y)) { PyErr_SetString(PyExc_TypeError, "y must be an int"); return NULL;} y = (int)PyLong_AsLong(optional_y); }
|
||||
if (window_state < WINDOW_NORMAL || window_state > WINDOW_MINIMIZED) window_state = WINDOW_NORMAL;
|
||||
if (window_state < WINDOW_NORMAL || window_state > WINDOW_HIDDEN) window_state = WINDOW_NORMAL;
|
||||
}
|
||||
if (PyErr_Occurred()) return NULL;
|
||||
|
||||
@@ -1301,8 +1306,9 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
||||
glfwWindowHint(GLFW_WAYLAND_BGCOLOR, ((bgalpha & 0xff) << 24) | bgcolor);
|
||||
// We use a temp window to avoid the need to set the window size after
|
||||
// creation, which causes a resize event and all the associated processing.
|
||||
// The temp window is used to get the DPI.
|
||||
if (!global_state.is_wayland) glfwWindowHint(GLFW_VISIBLE, false);
|
||||
// The temp window is used to get the DPI. On Wayland no temp window can be
|
||||
// used, so start with window visible unless hidden window requested.
|
||||
glfwWindowHint(GLFW_VISIBLE, window_state != WINDOW_HIDDEN && global_state.is_wayland);
|
||||
GLFWwindow *common_context = global_state.num_os_windows ? global_state.os_windows[0].handle : NULL;
|
||||
GLFWwindow *temp_window = NULL;
|
||||
#ifdef __APPLE__
|
||||
@@ -1356,7 +1362,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) glfwShowWindow(glfw_window);
|
||||
if (!global_state.is_apple && !global_state.is_wayland && window_state != WINDOW_HIDDEN) glfwShowWindow(glfw_window);
|
||||
if (global_state.is_wayland || global_state.is_apple) {
|
||||
float n_xscale, n_yscale;
|
||||
double n_xdpi, n_ydpi;
|
||||
@@ -1447,7 +1453,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
|
||||
glfwShowWindow(glfw_window);
|
||||
if (window_state != WINDOW_HIDDEN) glfwShowWindow(glfw_window);
|
||||
#endif
|
||||
w->redraw_count = 1;
|
||||
debug("OS Window created\n");
|
||||
|
||||
@@ -1556,6 +1556,7 @@ init_state(PyObject *module) {
|
||||
PyModule_AddIntMacro(module, WINDOW_NORMAL);
|
||||
PyModule_AddIntMacro(module, WINDOW_FULLSCREEN);
|
||||
PyModule_AddIntMacro(module, WINDOW_MAXIMIZED);
|
||||
PyModule_AddIntMacro(module, WINDOW_HIDDEN);
|
||||
PyModule_AddIntMacro(module, WINDOW_MINIMIZED);
|
||||
PyModule_AddIntMacro(module, TOP_EDGE);
|
||||
PyModule_AddIntMacro(module, BOTTOM_EDGE);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
typedef enum { LEFT_EDGE = 1, TOP_EDGE = 2, RIGHT_EDGE = 4, BOTTOM_EDGE = 8 } Edge;
|
||||
typedef enum { REPEAT_MIRROR, REPEAT_CLAMP, REPEAT_DEFAULT } RepeatStrategy;
|
||||
typedef enum { WINDOW_NORMAL, WINDOW_FULLSCREEN, WINDOW_MAXIMIZED, WINDOW_MINIMIZED } WindowState;
|
||||
typedef enum { WINDOW_NORMAL, WINDOW_FULLSCREEN, WINDOW_MAXIMIZED, WINDOW_MINIMIZED, WINDOW_HIDDEN } WindowState;
|
||||
|
||||
typedef struct {
|
||||
char_type string[16];
|
||||
|
||||
@@ -30,7 +30,7 @@ from .constants import (
|
||||
shell_path,
|
||||
ssh_control_master_template,
|
||||
)
|
||||
from .fast_data_types import WINDOW_FULLSCREEN, WINDOW_MAXIMIZED, WINDOW_MINIMIZED, WINDOW_NORMAL, Color, Shlex, get_options, monotonic, open_tty
|
||||
from .fast_data_types import WINDOW_FULLSCREEN, WINDOW_HIDDEN, WINDOW_MAXIMIZED, WINDOW_MINIMIZED, WINDOW_NORMAL, Color, Shlex, get_options, monotonic, open_tty
|
||||
from .fast_data_types import timed_debug_print as _timed_debug_print
|
||||
from .types import run_once
|
||||
from .typing import AddressFamily, PopenType, StartupCtx
|
||||
@@ -401,10 +401,19 @@ def parse_address_spec(spec: str) -> tuple[AddressFamily, tuple[str, int] | str,
|
||||
|
||||
|
||||
def parse_os_window_state(state: str) -> int:
|
||||
return {
|
||||
'normal': WINDOW_NORMAL, 'maximized': WINDOW_MAXIMIZED, 'minimized': WINDOW_MINIMIZED,
|
||||
'fullscreen': WINDOW_FULLSCREEN, 'fullscreened':WINDOW_FULLSCREEN
|
||||
}[state]
|
||||
match state:
|
||||
case 'normal':
|
||||
return WINDOW_NORMAL
|
||||
case 'maximized':
|
||||
return WINDOW_MAXIMIZED
|
||||
case 'minimized':
|
||||
return WINDOW_MINIMIZED
|
||||
case 'fullscreen' | 'fullscreened':
|
||||
return WINDOW_FULLSCREEN
|
||||
case 'hidden':
|
||||
return WINDOW_HIDDEN
|
||||
case _:
|
||||
return WINDOW_NORMAL
|
||||
|
||||
|
||||
def write_all(fd: int, data: str | bytes, block_until_written: bool = True) -> None:
|
||||
|
||||
Reference in New Issue
Block a user