Avoid flicker when starting kittens such as the hints kitten

Fixes #4674
This commit is contained in:
Kovid Goyal
2022-03-23 15:55:11 +05:30
parent 1837168b0b
commit 6dc1617429
14 changed files with 86 additions and 18 deletions
+2 -1
View File
@@ -1427,7 +1427,8 @@ class Boss:
'OVERLAID_WINDOW_COLS': str(w.screen.columns),
},
cwd=w.cwd_of_child,
overlay_for=w.id
overlay_for=w.id,
overlay_behind=end_kitten.has_ready_notification,
),
copy_colors_from=w
)
+5 -2
View File
@@ -271,9 +271,12 @@ class Layout:
def move_window_to_group(self, all_windows: WindowList, group: int) -> bool:
return all_windows.move_window_group(to_group=group)
def add_window(self, all_windows: WindowList, window: WindowType, location: Optional[str] = None, overlay_for: Optional[int] = None) -> None:
def add_window(
self, all_windows: WindowList, window: WindowType, location: Optional[str] = None,
overlay_for: Optional[int] = None, put_overlay_behind: bool = False
) -> None:
if overlay_for is not None and overlay_for in all_windows:
all_windows.add_window(window, group_of=overlay_for)
all_windows.add_window(window, group_of=overlay_for, head_of_group=put_overlay_behind)
return
if location == 'neighbor':
location = 'after'
+1
View File
@@ -1080,6 +1080,7 @@ dispatch_dcs(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
Py_DECREF(msg); \
} else PyErr_Clear();
} else IF_SIMPLE_PREFIX("overlay-ready|", screen_handle_overlay_ready)
} else IF_SIMPLE_PREFIX("kitten-result|", screen_handle_kitten_result)
} else IF_SIMPLE_PREFIX("print|", screen_handle_print)
} else IF_SIMPLE_PREFIX("echo|", screen_handle_echo)
+5
View File
@@ -2134,6 +2134,11 @@ screen_handle_kitten_result(Screen *self, PyObject *msg) {
CALLBACK("handle_kitten_result", "O", msg);
}
void
screen_handle_overlay_ready(Screen *self, PyObject *msg) {
CALLBACK("handle_overlay_ready", "O", msg);
}
void
screen_request_capabilities(Screen *self, char c, PyObject *q) {
static char buf[128];
+1
View File
@@ -213,6 +213,7 @@ void screen_handle_echo(Screen *, PyObject *cmd);
void screen_handle_ssh(Screen *, PyObject *cmd);
void screen_handle_askpass(Screen *, PyObject *cmd);
void screen_handle_kitten_result(Screen *, PyObject *cmd);
void screen_handle_overlay_ready(Screen *, PyObject *cmd);
void screen_designate_charset(Screen *, uint32_t which, uint32_t as);
void screen_use_latin1(Screen *, bool);
void set_title(Screen *self, PyObject*);
+13 -7
View File
@@ -63,6 +63,7 @@ class SpecialWindowInstance(NamedTuple):
overlay_for: Optional[int]
env: Optional[Dict[str, str]]
watchers: Optional[Watchers]
overlay_behind: bool
def SpecialWindow(
@@ -73,9 +74,10 @@ def SpecialWindow(
cwd: Optional[str] = None,
overlay_for: Optional[int] = None,
env: Optional[Dict[str, str]] = None,
watchers: Optional[Watchers] = None
watchers: Optional[Watchers] = None,
overlay_behind: bool = False
) -> SpecialWindowInstance:
return SpecialWindowInstance(cmd, stdin, override_title, cwd_from, cwd, overlay_for, env, watchers)
return SpecialWindowInstance(cmd, stdin, override_title, cwd_from, cwd, overlay_for, env, watchers, overlay_behind)
def add_active_id_to_history(items: Deque[int], item_id: int, maxlen: int = 64) -> None:
@@ -403,8 +405,8 @@ class Tab: # {{{
ans.fork()
return ans
def _add_window(self, window: Window, location: Optional[str] = None, overlay_for: Optional[int] = None) -> None:
self.current_layout.add_window(self.windows, window, location, overlay_for)
def _add_window(self, window: Window, location: Optional[str] = None, overlay_for: Optional[int] = None, overlay_behind: bool = False) -> None:
self.current_layout.add_window(self.windows, window, location, overlay_for, put_overlay_behind=overlay_behind)
self.mark_tab_bar_dirty()
self.relayout()
@@ -422,7 +424,8 @@ class Tab: # {{{
copy_colors_from: Optional[Window] = None,
allow_remote_control: bool = False,
marker: Optional[str] = None,
watchers: Optional[Watchers] = None
watchers: Optional[Watchers] = None,
overlay_behind: bool = False
) -> Window:
child = self.launch_child(
use_shell=use_shell, cmd=cmd, stdin=stdin, cwd_from=cwd_from, cwd=cwd, env=env, allow_remote_control=allow_remote_control)
@@ -432,7 +435,7 @@ class Tab: # {{{
)
# Must add child before laying out so that resize_pty succeeds
get_boss().add_child(window)
self._add_window(window, location=location, overlay_for=overlay_for)
self._add_window(window, location=location, overlay_for=overlay_for, overlay_behind=overlay_behind)
if marker:
try:
window.set_marker(marker)
@@ -453,7 +456,7 @@ class Tab: # {{{
override_title=special_window.override_title,
cwd_from=special_window.cwd_from, cwd=special_window.cwd, overlay_for=special_window.overlay_for,
env=special_window.env, location=location, copy_colors_from=copy_colors_from,
allow_remote_control=allow_remote_control, watchers=special_window.watchers
allow_remote_control=allow_remote_control, watchers=special_window.watchers, overlay_behind=special_window.overlay_behind
)
@ac('win', 'Close all windows in the tab other than the currently active window')
@@ -464,6 +467,9 @@ class Tab: # {{{
if window is not active_window:
self.remove_window(window)
def move_window_to_top_of_group(self, window: Window) -> bool:
return self.windows.move_window_to_top_of_group(window)
def remove_window(self, window: Window, destroy: bool = True) -> None:
self.windows.remove_window(window)
if destroy:
+7
View File
@@ -940,6 +940,13 @@ class Window:
import base64
self.kitten_result: Dict[str, Any] = json.loads(base64.b85decode(msg))
def handle_overlay_ready(self, msg: str) -> None:
boss = get_boss()
tab = boss.tab_for_window(self)
if tab is None:
return
tab.move_window_to_top_of_group(self)
def handle_remote_askpass(self, msg: str) -> None:
from .shm import SharedMemory
with SharedMemory(name=msg, readonly=True) as shm:
+32 -3
View File
@@ -61,8 +61,23 @@ class WindowGroup:
def active_window_id(self) -> int:
return self.windows[-1].id if self.windows else 0
def add_window(self, window: WindowType) -> None:
def add_window(self, window: WindowType, head_of_group: bool = False) -> None:
if head_of_group:
self.windows.insert(0, window)
else:
self.windows.append(window)
def move_window_to_top_of_group(self, window: WindowType) -> bool:
id
try:
idx = self.windows.index(window)
except ValueError:
return False
if idx == len(self.windows) - 1:
return False
del self.windows[idx]
self.windows.append(window)
return True
def remove_window(self, window: WindowType) -> None:
with suppress(ValueError):
@@ -252,6 +267,19 @@ class WindowList:
return i
return None
def move_window_to_top_of_group(self, window: WindowType) -> bool:
g = self.group_for_window(window)
if g is None:
return False
before = self.active_window
if not g.move_window_to_top_of_group(window):
return False
after = self.active_window
changed = before is not after
if changed:
self.notify_on_active_window_change(before, after)
return changed
def windows_in_group_of(self, x: WindowOrId) -> Iterator[WindowType]:
g = self.group_for_window(x)
if g is not None:
@@ -292,7 +320,8 @@ class WindowList:
group_of: Optional[WindowOrId] = None,
next_to: Optional[WindowOrId] = None,
before: bool = False,
make_active: bool = True
make_active: bool = True,
head_of_group: bool = False,
) -> WindowGroup:
self.all_windows.append(window)
self.id_map[window.id] = window
@@ -318,7 +347,7 @@ class WindowList:
self.groups.append(target_group)
old_active_window = self.active_window
target_group.add_window(window)
target_group.add_window(window, head_of_group=head_of_group)
if make_active:
for i, g in enumerate(self.groups):
if g is target_group: