mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 08:26:56 +00:00
More work on floats
This commit is contained in:
parent
4e697abb34
commit
715645e69c
9 changed files with 80 additions and 19 deletions
|
|
@ -526,7 +526,7 @@ def monitor_pid(pid: int) -> None:
|
|||
pass
|
||||
|
||||
|
||||
def add_window(os_window_id: int, tab_id: int, title: str) -> int:
|
||||
def add_window(os_window_id: int, tab_id: int, title: str, is_floating: bool) -> int:
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ from .clipboard import set_clipboard_string, set_primary_selection
|
|||
from .fast_data_types import add_timer, get_boss, get_options, get_os_window_title, patch_color_profiles
|
||||
from .options.utils import env as parse_env
|
||||
from .tabs import Tab, TabManager
|
||||
from .types import LayerShellConfig, OverlayType, run_once
|
||||
from .types import FloatType, LayerShellConfig, OverlayType, run_once
|
||||
from .utils import get_editor, log_error, resolve_custom_file, which
|
||||
from .window import CwdRequest, CwdRequestType, Watchers, Window
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ of the active window in the tab is used as the tab title. The special value
|
|||
--type
|
||||
type=choices
|
||||
default=window
|
||||
choices=window,tab,os-window,os-panel,overlay,overlay-main,background,clipboard,primary
|
||||
choices=window,tab,os-window,os-panel,overlay,overlay-main,float-in-window,float-in-tab,background,clipboard,primary
|
||||
Where to launch the child process:
|
||||
|
||||
:code:`window`
|
||||
|
|
@ -105,6 +105,14 @@ Where to launch the child process:
|
|||
directory, the input text for kittens, launch commands, etc. Useful if this overlay is
|
||||
intended to run for a long time as a primary window.
|
||||
|
||||
:code:`float-in-window`
|
||||
A floating window that is drawn over a non-floating window, usually the currently
|
||||
active window.
|
||||
|
||||
:code:`float-in-tab`
|
||||
A floating window that is drawn over all windows in a tab, usually the currently
|
||||
active tab.
|
||||
|
||||
:code:`background`
|
||||
The process will be run in the :italic:`background`, without a kitty
|
||||
window. Note that if :option:`kitten @ launch --allow-remote-control` is
|
||||
|
|
@ -753,8 +761,9 @@ def _launch(
|
|||
tab = tab_for_window(boss, opts, target_tab, next_to)
|
||||
watchers = load_watch_modules(opts.watcher)
|
||||
with Window.set_ignore_focus_changes_for_new_windows(opts.keep_focus):
|
||||
float_type = {'float-in-window': FloatType.window, 'float-in-tab': FloatType.tab}.get(opts.type, FloatType.none)
|
||||
new_window: Window = tab.new_window(
|
||||
env=env or None, watchers=watchers or None, is_clone_launch=is_clone_launch, next_to=next_to, **kw)
|
||||
env=env or None, watchers=watchers or None, is_clone_launch=is_clone_launch, next_to=next_to, float_type=float_type, **kw)
|
||||
if child_death_callback is not None:
|
||||
boss.monitor_pid(new_window.child.pid or 0, child_death_callback)
|
||||
if spacing:
|
||||
|
|
|
|||
|
|
@ -341,14 +341,14 @@ class Layout:
|
|||
return False
|
||||
|
||||
def update_visibility(self, all_windows: WindowList) -> None:
|
||||
active_window = all_windows.active_window
|
||||
active_non_floating_window = all_windows.active_non_floating_window
|
||||
floating_windows = []
|
||||
vismap = {}
|
||||
for window, is_group_leader, is_floating in all_windows.iter_windows_with_visibility():
|
||||
if is_floating:
|
||||
floating_windows.append((window, is_group_leader))
|
||||
else:
|
||||
is_visible = window is active_window or (is_group_leader and not self.only_active_window_visible)
|
||||
is_visible = window is active_non_floating_window or (is_group_leader and not self.only_active_window_visible)
|
||||
window.set_visible_in_layout(is_visible)
|
||||
vismap[window.id] = is_visible
|
||||
for window, is_group_leader in sorted(floating_windows, key=lambda x: x[0].id):
|
||||
|
|
|
|||
|
|
@ -1134,7 +1134,7 @@ draw_cells(ssize_t vao_idx, const WindowRenderData *srd, OSWindow *os_window, bo
|
|||
}
|
||||
bool use_premult = false;
|
||||
has_underlying_image |= grd.num_of_below_refs > 0 || grd.num_of_negative_refs > 0;
|
||||
if (os_window->is_semi_transparent) {
|
||||
if (os_window->is_semi_transparent || srd->float_data.is_floating) {
|
||||
if (has_underlying_image) { draw_cells_interleaved_premult(vao_idx, screen, os_window, &crd, grd, wl); use_premult = true; }
|
||||
else draw_cells_simple(vao_idx, screen, &crd, grd, os_window->is_semi_transparent);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "cleanup.h"
|
||||
#include "options/to-c-generated.h"
|
||||
#include "iqsort.h"
|
||||
#include <math.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
|
@ -288,10 +289,11 @@ set_window_logo(Window *w, const char *path, const ImageAnchorPosition pos, floa
|
|||
}
|
||||
|
||||
static void
|
||||
initialize_window(Window *w, PyObject *title, bool init_gpu_resources) {
|
||||
initialize_window(Window *w, PyObject *title, bool init_gpu_resources, bool is_floating) {
|
||||
w->id = ++global_state.window_id_counter;
|
||||
w->visible = true;
|
||||
w->title = title;
|
||||
w->render_data.float_data.is_floating = is_floating;
|
||||
Py_XINCREF(title);
|
||||
if (!set_window_logo(w, OPT(default_window_logo), OPT(window_logo_position), OPT(window_logo_alpha), true, NULL, 0)) {
|
||||
log_error("Failed to load default window logo: %s", OPT(default_window_logo));
|
||||
|
|
@ -303,14 +305,23 @@ initialize_window(Window *w, PyObject *title, bool init_gpu_resources) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sort_windows_in_render_order(Window *windows, size_t count) {
|
||||
#define lt(a, b) (!a->render_data.float_data.is_floating && b->render_data.float_data.is_floating) || (a->render_data.float_data.is_floating == b->render_data.float_data.is_floating && a->id < b->id)
|
||||
QSORT(Window, windows, count, lt)
|
||||
#undef lt
|
||||
}
|
||||
|
||||
static id_type
|
||||
add_window(id_type os_window_id, id_type tab_id, PyObject *title) {
|
||||
add_window(id_type os_window_id, id_type tab_id, PyObject *title, bool is_floating) {
|
||||
WITH_TAB(os_window_id, tab_id);
|
||||
ensure_space_for(tab, windows, Window, tab->num_windows + 1, capacity, 1, true);
|
||||
make_os_window_context_current(osw);
|
||||
zero_at_i(tab->windows, tab->num_windows);
|
||||
initialize_window(tab->windows + tab->num_windows, title, true);
|
||||
return tab->windows[tab->num_windows++].id;
|
||||
initialize_window(tab->windows + tab->num_windows, title, true, is_floating);
|
||||
Window *ans = tab->windows + tab->num_windows++;
|
||||
sort_windows_in_render_order(tab->windows, tab->num_windows);
|
||||
return ans->id;
|
||||
END_WITH_TAB;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1290,13 +1301,14 @@ static PyObject*
|
|||
pycreate_mock_window(PyObject *self UNUSED, PyObject *args) {
|
||||
Screen *screen;
|
||||
PyObject *title = NULL;
|
||||
if (!PyArg_ParseTuple(args, "O|U", &screen, &title)) return NULL;
|
||||
int is_floating = 0;
|
||||
if (!PyArg_ParseTuple(args, "O|Up", &screen, &title, &is_floating)) return NULL;
|
||||
Window *w = PyMem_Calloc(sizeof(Window), 1);
|
||||
if (!w) return NULL;
|
||||
Py_INCREF(screen);
|
||||
PyObject *ans = PyCapsule_New(w, "Window", destroy_mock_window);
|
||||
if (ans != NULL) {
|
||||
initialize_window(w, title, false);
|
||||
initialize_window(w, title, false, is_floating);
|
||||
w->render_data.screen = screen;
|
||||
}
|
||||
return ans;
|
||||
|
|
@ -1404,7 +1416,11 @@ THREE_ID(remove_window)
|
|||
THREE_ID(detach_window)
|
||||
THREE_ID(attach_window)
|
||||
PYWRAP1(add_tab) { return PyLong_FromUnsignedLongLong(add_tab(PyLong_AsUnsignedLongLong(args))); }
|
||||
PYWRAP1(add_window) { PyObject *title; id_type a, b; PA("KKO", &a, &b, &title); return PyLong_FromUnsignedLongLong(add_window(a, b, title)); }
|
||||
PYWRAP1(add_window) {
|
||||
PyObject *title; id_type a, b; int is_floating;
|
||||
PA("KKOp", &a, &b, &title, &is_floating);
|
||||
return PyLong_FromUnsignedLongLong(add_window(a, b, title, is_floating));
|
||||
}
|
||||
PYWRAP0(current_os_window) { OSWindow *w = current_os_window(); if (!w) Py_RETURN_NONE; return PyLong_FromUnsignedLongLong(w->id); }
|
||||
TWO_ID(remove_tab)
|
||||
KI(set_active_tab)
|
||||
|
|
|
|||
|
|
@ -141,10 +141,15 @@ typedef struct WindowLogoRenderData {
|
|||
bool using_default;
|
||||
} WindowLogoRenderData;
|
||||
|
||||
typedef struct FloatRenderData {
|
||||
bool is_floating;
|
||||
} FloatRenderData;
|
||||
|
||||
typedef struct {
|
||||
ssize_t vao_idx;
|
||||
float xstart, ystart, dx, dy;
|
||||
Screen *screen;
|
||||
FloatRenderData float_data;
|
||||
} WindowRenderData;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ from .layout.base import Layout
|
|||
from .layout.interface import create_layout_object_for, evict_cached_layouts
|
||||
from .progress import ProgressState
|
||||
from .tab_bar import TabBar, TabBarData
|
||||
from .types import ac
|
||||
from .types import FloatType, ac
|
||||
from .typing_compat import EdgeLiteral, SessionTab, SessionType, TypedDict
|
||||
from .utils import cmdline_for_hold, log_error, platform_window_id, resolved_shell, shlex_split, which
|
||||
from .window import CwdRequest, Watchers, Window, WindowDict
|
||||
|
|
@ -568,15 +568,21 @@ class Tab: # {{{
|
|||
pass_fds: tuple[int, ...] = (),
|
||||
remote_control_fd: int = -1,
|
||||
next_to: Window | None = None,
|
||||
float_type: FloatType = FloatType.none,
|
||||
) -> Window:
|
||||
child = self.launch_child(
|
||||
use_shell=use_shell, cmd=cmd, stdin=stdin, cwd_from=cwd_from, cwd=cwd, env=env,
|
||||
is_clone_launch=is_clone_launch, add_listen_on_env_var=False if allow_remote_control and remote_control_passwords else True,
|
||||
hold=hold, pass_fds=pass_fds, remote_control_fd=remote_control_fd,
|
||||
)
|
||||
floating_in = 0
|
||||
if float_type is FloatType.window:
|
||||
w = next_to or self.active_window
|
||||
if w:
|
||||
floating_in = w.id
|
||||
window = Window(
|
||||
self, child, self.args, override_title=override_title,
|
||||
copy_colors_from=copy_colors_from, watchers=watchers,
|
||||
self, child, self.args, override_title=override_title, floating_in_window=floating_in,
|
||||
copy_colors_from=copy_colors_from, watchers=watchers, float_type=float_type,
|
||||
allow_remote_control=allow_remote_control, remote_control_passwords=remote_control_passwords
|
||||
)
|
||||
# Must add child before laying out so that resize_pty succeeds
|
||||
|
|
|
|||
|
|
@ -663,7 +663,7 @@ class Window:
|
|||
self.child_title = self.default_title
|
||||
self.title_stack: Deque[str] = deque(maxlen=10)
|
||||
self.user_vars: dict[str, str] = {}
|
||||
self.id: int = add_window(tab.os_window_id, tab.id, self.title)
|
||||
self.id: int = add_window(tab.os_window_id, tab.id, self.title, self.is_floating)
|
||||
self.clipboard_request_manager = ClipboardRequestManager(self.id)
|
||||
self.margin = EdgeWidths()
|
||||
self.padding = EdgeWidths()
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from itertools import count
|
|||
from typing import Any, Deque, Union
|
||||
|
||||
from .fast_data_types import Color, get_options
|
||||
from .types import OverlayType, WindowGeometry
|
||||
from .types import FloatType, OverlayType, WindowGeometry
|
||||
from .typing_compat import EdgeLiteral, TabType, WindowType
|
||||
|
||||
WindowOrId = Union[WindowType, int]
|
||||
|
|
@ -333,6 +333,31 @@ class WindowList:
|
|||
return self.id_map[self.groups[self.active_group_idx].active_window_id]
|
||||
return None
|
||||
|
||||
@property
|
||||
def active_non_floating_window(self) -> WindowType | None:
|
||||
w = self.active_window
|
||||
if w is None:
|
||||
return None
|
||||
if not w.is_floating:
|
||||
return w
|
||||
if w.float_type is FloatType.window:
|
||||
parent = self.id_map.get(w.floating_in_window)
|
||||
if parent is not None:
|
||||
g = self.group_for_window(parent)
|
||||
if g is not None:
|
||||
ans = self.id_map.get(g.active_window_id)
|
||||
if ans is not None:
|
||||
return ans
|
||||
# tab or os window float or parent window closed
|
||||
gid_map = {g.id: g for g in self.groups}
|
||||
for gid in reversed(self.active_group_history):
|
||||
g = gid_map.get(gid)
|
||||
if g is not None:
|
||||
w = self.id_map.get(g.active_window_id)
|
||||
if w is not None and not w.is_floating:
|
||||
return w
|
||||
return None
|
||||
|
||||
@property
|
||||
def active_group_main(self) -> WindowType | None:
|
||||
with suppress(Exception):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue