Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kitty for openSUSE:Factory checked 
in at 2022-11-07 13:52:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kitty (Old)
 and      /work/SRC/openSUSE:Factory/.kitty.new.1597 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kitty"

Mon Nov  7 13:52:14 2022 rev:14 rq:1034148 version:0.26.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/kitty/kitty.changes      2022-10-19 
13:18:01.449265271 +0200
+++ /work/SRC/openSUSE:Factory/.kitty.new.1597/kitty.changes    2022-11-07 
13:52:24.340042445 +0100
@@ -1,0 +2,20 @@
+Mon Nov  7 10:50:41 UTC 2022 - Michael Vetter <mvet...@suse.com>
+
+- Update to 0.26.5:
+  * Splits layout: Add a new mappable action to move the active
+    window to the screen edge (#5643)
+  * ssh kitten: Allow using absolute paths for the location of
+    transferred data (#5607)
+  * Fix a regression in the previous release that caused a
+    resize_draw_strategy of static to not work (#5601)
+  * Wayland KDE: Fix abort when pasting into Firefox (#5603)
+  * Wayland GNOME: Fix ghosting when using background_tint (#5605)
+  * Fix cursor position at x=0 changing to x=1 on resize (#5635)
+  * Wayland GNOME: Fix incorrect window size in some circumstances
+    when switching between windows with window decorations disabled (#4802)
+  * Wayland: Fix high CPU usage when using some input methods (#5369)
+  * Remote control: When matching window by state:focused and no window
+    currently has keyboard focus, match the window belonging to the OS
+    window that was last focused (#5602)
+
+-------------------------------------------------------------------

Old:
----
  kitty-0.26.4.tar.gz

New:
----
  kitty-0.26.5.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kitty.spec ++++++
--- /var/tmp/diff_new_pack.SoFNOx/_old  2022-11-07 13:52:24.948045863 +0100
+++ /var/tmp/diff_new_pack.SoFNOx/_new  2022-11-07 13:52:24.952045885 +0100
@@ -19,7 +19,7 @@
 # sphinx_copybutton not in Factory
 %bcond_with docs
 Name:           kitty
-Version:        0.26.4
+Version:        0.26.5
 Release:        0
 Summary:        A GPU-based terminal emulator
 License:        GPL-3.0-only

++++++ kitty-0.26.4.tar.gz -> kitty-0.26.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/.github/workflows/ci.yml 
new/kitty-0.26.5/.github/workflows/ci.yml
--- old/kitty-0.26.4/.github/workflows/ci.yml   2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/.github/workflows/ci.yml   2022-11-07 11:06:42.000000000 
+0100
@@ -27,11 +27,11 @@
                       sanitize: 0
 
                     - python: b
-                      pyver: "3.9"
+                      pyver: "3.11"
                       sanitize: 1
 
                     - python: c
-                      pyver: "3.10"
+                      pyver: "3.9"
                       sanitize: 1
 
 
@@ -76,7 +76,7 @@
             - name: Set up Python
               uses: actions/setup-python@v3
               with:
-                python-version: 3.9
+                python-version: "3.10"
 
             - name: Install build-only deps
               run: pip install -r docs/requirements.txt flake8 mypy 
types-requests types-docutils
@@ -128,6 +128,11 @@
               with:
                   fetch-depth: 0  # needed for :commit: docs role
 
+            - name: Set up Python
+              uses: actions/setup-python@v3
+              with:
+                python-version: "3.10"
+
             - name: Build kitty
               run: python3 .github/workflows/ci.py build
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/bypy/linux/__main__.py 
new/kitty-0.26.5/bypy/linux/__main__.py
--- old/kitty-0.26.4/bypy/linux/__main__.py     2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/bypy/linux/__main__.py     2022-11-07 11:06:42.000000000 
+0100
@@ -220,7 +220,7 @@
     print('Compressing archive...')
     ans = f'{dist.rpartition(".")[0]}.txz'
     start_time = time.time()
-    subprocess.check_call(['xz', '--threads=0', '-f', f'-{compression_level}', 
dist])
+    subprocess.check_call(['xz', '--verbose', '--threads=0', '-f', 
f'-{compression_level}', dist])
     secs = time.time() - start_time
     print('Compressed in {} minutes {} seconds'.format(secs // 60, secs % 60))
     os.rename(f'{dist}.xz', ans)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/docs/changelog.rst 
new/kitty-0.26.5/docs/changelog.rst
--- old/kitty-0.26.4/docs/changelog.rst 2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/docs/changelog.rst 2022-11-07 11:06:42.000000000 +0100
@@ -35,6 +35,27 @@
 Detailed list of changes
 -------------------------------------
 
+0.26.5 [2022-11-07]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Splits layout: Add a new mappable action to move the active window to the 
screen edge (:iss:`5643`)
+
+- ssh kitten: Allow using absolute paths for the location of transferred data 
(:iss:`5607`)
+
+- Fix a regression in the previous release that caused a 
:opt:`resize_draw_strategy` of ``static`` to not work (:iss:`5601`)
+
+- Wayland KDE: Fix abort when pasting into Firefox (:iss:`5603`)
+
+- Wayland GNOME: Fix ghosting when using :opt:`background_tint` (:iss:`5605`)
+
+- Fix cursor position at x=0 changing to x=1 on resize (:iss:`5635`)
+
+- Wayland GNOME: Fix incorrect window size in some circumstances when 
switching between windows with window decorations disabled (:iss:`4802`)
+
+- Wayland: Fix high CPU usage when using some input methods (:pull:`5369`)
+
+- Remote control: When matching window by `state:focused` and no window 
currently has keyboard focus, match the window belonging to the OS window that 
was last focused (:iss:`5602`)
+
 0.26.4 [2022-10-17]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/docs/conf.py 
new/kitty-0.26.5/docs/conf.py
--- old/kitty-0.26.4/docs/conf.py       2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/docs/conf.py       2022-11-07 11:06:42.000000000 +0100
@@ -277,7 +277,7 @@
     from kitty.rc.base import (
         RemoteCommand, all_command_names, command_for_name
     )
-    field_pat = re.compile(r'\s*([a-zA-Z0-9_+/]+)\s*:\s*(.+)')
+    field_pat = re.compile(r'\s*([^:]+?)\s*:\s*(.+)')
 
     def format_cmd(p: Callable[..., None], name: str, cmd: RemoteCommand) -> 
None:
         p(name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/docs/layouts.rst 
new/kitty-0.26.5/docs/layouts.rst
--- old/kitty-0.26.4/docs/layouts.rst   2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/docs/layouts.rst   2022-11-07 11:06:42.000000000 +0100
@@ -167,6 +167,12 @@
     map shift+right move_window right
     map shift+down move_window down
 
+    # Move the active window to the indicated screen edge
+    map ctrl+shift+up layout_action move_to_screen_edge top
+    map ctrl+shift+left layout_action move_to_screen_edge left
+    map ctrl+shift+right layout_action move_to_screen_edge right
+    map ctrl+shift+down layout_action move_to_screen_edge bottom
+
     # Switch focus to the neighboring window in the indicated direction
     map ctrl+left neighboring_window left
     map ctrl+right neighboring_window right
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/glfw/context.c 
new/kitty-0.26.5/glfw/context.c
--- old/kitty-0.26.4/glfw/context.c     2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/glfw/context.c     2022-11-07 11:06:42.000000000 +0100
@@ -478,6 +478,9 @@
     }
 
     window->context.swapBuffers(window);
+#ifdef _GLFW_WAYLAND
+    _glfwWaylandAfterBufferSwap(window);
+#endif
 }
 
 GLFWAPI void glfwSwapInterval(int interval)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/glfw/egl_context.c 
new/kitty-0.26.5/glfw/egl_context.c
--- old/kitty-0.26.4/glfw/egl_context.c 2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/glfw/egl_context.c 2022-11-07 11:06:42.000000000 +0100
@@ -326,6 +326,7 @@
     glfw_dlsym(_glfw.egl.SwapBuffers, _glfw.egl.handle, "eglSwapBuffers");
     glfw_dlsym(_glfw.egl.SwapInterval, _glfw.egl.handle, "eglSwapInterval");
     glfw_dlsym(_glfw.egl.QueryString, _glfw.egl.handle, "eglQueryString");
+    glfw_dlsym(_glfw.egl.QuerySurface, _glfw.egl.handle, "eglQuerySurface");
     glfw_dlsym(_glfw.egl.GetProcAddress, _glfw.egl.handle, 
"eglGetProcAddress");
 
     if (!_glfw.egl.GetConfigAttrib ||
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/glfw/egl_context.h 
new/kitty-0.26.5/glfw/egl_context.h
--- old/kitty-0.26.4/glfw/egl_context.h 2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/glfw/egl_context.h 2022-11-07 11:06:42.000000000 +0100
@@ -132,6 +132,7 @@
 typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
 typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
 typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
+typedef const char* (EGLAPIENTRY * 
PFN_eglQuerySurface)(EGLDisplay,EGLSurface,EGLint,EGLint*);
 typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
 #define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
 #define eglGetConfigs _glfw.egl.GetConfigs
@@ -149,6 +150,7 @@
 #define eglSwapBuffers _glfw.egl.SwapBuffers
 #define eglSwapInterval _glfw.egl.SwapInterval
 #define eglQueryString _glfw.egl.QueryString
+#define eglQuerySurface _glfw.egl.QuerySurface
 #define eglGetProcAddress _glfw.egl.GetProcAddress
 
 typedef EGLDisplay (EGLAPIENTRY * 
PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*);
@@ -211,6 +213,7 @@
     PFN_eglSwapBuffers          SwapBuffers;
     PFN_eglSwapInterval         SwapInterval;
     PFN_eglQueryString          QueryString;
+    PFN_eglQuerySurface         QuerySurface;
     PFN_eglGetProcAddress       GetProcAddress;
 
     PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/glfw/wl_platform.h 
new/kitty-0.26.5/glfw/wl_platform.h
--- old/kitty-0.26.4/glfw/wl_platform.h 2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/glfw/wl_platform.h 2022-11-07 11:06:42.000000000 +0100
@@ -152,6 +152,7 @@
     bool                        hovered;
     bool                        transparent;
     struct wl_surface*          surface;
+    bool                        waiting_for_swap_to_commit;
     struct wl_egl_window*       native;
     struct wl_callback*         callback;
 
@@ -369,6 +370,7 @@
 
 
 void _glfwAddOutputWayland(uint32_t name, uint32_t version);
+void _glfwWaylandAfterBufferSwap(_GLFWwindow *window);
 void _glfwSetupWaylandDataDevice(void);
 void _glfwSetupWaylandPrimarySelectionDevice(void);
 void animateCursorImage(id_type timer_id, void *data);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/glfw/wl_text_input.c 
new/kitty-0.26.5/glfw/wl_text_input.c
--- old/kitty-0.26.4/glfw/wl_text_input.c       2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/glfw/wl_text_input.c       2022-11-07 11:06:42.000000000 
+0100
@@ -9,12 +9,15 @@
 #include "internal.h"
 #include "wayland-text-input-unstable-v3-client-protocol.h"
 #include <stdlib.h>
+#include <string.h>
 #define debug(...) if (_glfw.hints.init.debugKeyboard) printf(__VA_ARGS__);
 
 static struct zwp_text_input_v3*                  text_input;
 static struct zwp_text_input_manager_v3*          text_input_manager;
 static char *pending_pre_edit = NULL;
+static char *current_pre_edit = NULL;
 static char *pending_commit   = NULL;
+static int last_cursor_left = 0, last_cursor_top = 0, last_cursor_width = 0, 
last_cursor_height = 0;
 uint32_t commit_serial = 0;
 
 static void commit(void) {
@@ -90,12 +93,20 @@
         if (serial > commit_serial) _glfwInputError(GLFW_PLATFORM_ERROR, 
"Wayland: text_input_done serial mismatch, expected=%u got=%u\n", 
commit_serial, serial);
         return;
     }
-    if (pending_pre_edit) {
-        send_text(pending_pre_edit, GLFW_IME_PREEDIT_CHANGED);
+
+    if ((pending_pre_edit == NULL && current_pre_edit == NULL) ||
+        (pending_pre_edit && current_pre_edit && strcmp(pending_pre_edit, 
current_pre_edit) == 0)) {
         free(pending_pre_edit); pending_pre_edit = NULL;
     } else {
-        // Clear pre-edit text
-        send_text(NULL, GLFW_IME_WAYLAND_DONE_EVENT);
+        free(current_pre_edit);
+        current_pre_edit = pending_pre_edit;
+        pending_pre_edit = NULL;
+        if (current_pre_edit) {
+            send_text(current_pre_edit, GLFW_IME_PREEDIT_CHANGED);
+        } else {
+            // Clear pre-edit text
+            send_text(NULL, GLFW_IME_WAYLAND_DONE_EVENT);
+        }
     }
     if (pending_commit) {
         send_text(pending_commit, GLFW_IME_COMMIT_TEXT);
@@ -133,6 +144,7 @@
     if (text_input_manager) 
zwp_text_input_manager_v3_destroy(text_input_manager);
     text_input = NULL; text_input_manager = NULL;
     free(pending_pre_edit); pending_pre_edit = NULL;
+    free(current_pre_edit); current_pre_edit = NULL;
     free(pending_commit); pending_commit = NULL;
 }
 
@@ -146,10 +158,11 @@
                 zwp_text_input_v3_enable(text_input);
                 zwp_text_input_v3_set_content_type(text_input, 
ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, 
ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL);
             } else {
-                if (pending_pre_edit) {
+                free(pending_pre_edit); pending_pre_edit = NULL;
+                if (current_pre_edit) {
                     // Clear pre-edit text
                     send_text(NULL, GLFW_IME_PREEDIT_CHANGED);
-                    free(pending_pre_edit); pending_pre_edit = NULL;
+                    free(current_pre_edit); current_pre_edit = NULL;
                 }
                 if (pending_commit) {
                     free(pending_commit); pending_commit = NULL;
@@ -161,9 +174,15 @@
         case GLFW_IME_UPDATE_CURSOR_POSITION: {
             const int scale = w->wl.scale;
             const int left = ev->cursor.left / scale, top = ev->cursor.top / 
scale, width = ev->cursor.width / scale, height = ev->cursor.height / scale;
-            debug("\ntext-input: updating cursor position: left=%d top=%d 
width=%d height=%d\n", left, top, width, height);
-            zwp_text_input_v3_set_cursor_rectangle(text_input, left, top, 
width, height);
-            commit();
+            if (left != last_cursor_left || top != last_cursor_top || width != 
last_cursor_width || height != last_cursor_height) {
+                last_cursor_left = left;
+                last_cursor_top = top;
+                last_cursor_width = width;
+                last_cursor_height = height;
+                debug("\ntext-input: updating cursor position: left=%d top=%d 
width=%d height=%d\n", left, top, width, height);
+                zwp_text_input_v3_set_cursor_rectangle(text_input, left, top, 
width, height);
+                commit();
+            }
         }
             break;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/glfw/wl_window.c 
new/kitty-0.26.5/glfw/wl_window.c
--- old/kitty-0.26.4/glfw/wl_window.c   2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/glfw/wl_window.c   2022-11-07 11:06:42.000000000 +0100
@@ -251,6 +251,15 @@
     return false;
 }
 
+static void
+commit_window_surface_if_safe(_GLFWwindow *window) {
+    // we only commit if the buffer attached to the surface is the correct 
size,
+    // which means that at least one frame is drawn after resizeFramebuffer()
+    if (!window->wl.waiting_for_swap_to_commit) {
+        wl_surface_commit(window->wl.surface);
+    }
+}
+
 // Makes the surface considered as XRGB instead of ARGB.
 static void setOpaqueRegion(_GLFWwindow* window, bool commit_surface)
 {
@@ -262,7 +271,7 @@
 
     wl_region_add(region, 0, 0, window->wl.width, window->wl.height);
     wl_surface_set_opaque_region(window->wl.surface, region);
-    if (commit_surface) wl_surface_commit(window->wl.surface);
+    if (commit_surface) commit_window_surface_if_safe(window);
     wl_region_destroy(region);
 }
 
@@ -287,9 +296,20 @@
     debug("Resizing framebuffer to: %dx%d at scale: %d\n", window->wl.width, 
window->wl.height, scale);
     wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
     if (!window->wl.transparent) setOpaqueRegion(window, false);
+    window->wl.waiting_for_swap_to_commit = true;
     _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
 }
 
+void
+_glfwWaylandAfterBufferSwap(_GLFWwindow* window) {
+    if (window->wl.waiting_for_swap_to_commit) {
+        debug("Waiting for swap to commit: swap has happened\n");
+        window->wl.waiting_for_swap_to_commit = false;
+        // this is not really needed, since I think eglSwapBuffers() calls 
wl_surface_commit()
+        // but lets be safe. See 
https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/egl/drivers/dri2/platform_wayland.c#L1510
+        wl_surface_commit(window->wl.surface);
+    }
+}
 
 static const char*
 clipboard_mime(void) {
@@ -301,9 +321,9 @@
 }
 
 static bool
-dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, int32_t 
height, bool *scale_changed) {
+dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, int32_t 
height) {
     bool size_changed = width != window->wl.width || height != 
window->wl.height;
-    *scale_changed = checkScaleChange(window);
+    bool scale_changed = checkScaleChange(window);
 
     if (size_changed) {
         _glfwInputWindowSize(window, width, height);
@@ -311,7 +331,7 @@
         resizeFramebuffer(window);
     }
 
-    if (*scale_changed) {
+    if (scale_changed) {
         debug("Scale changed to %d in dispatchChangesAfterConfigure\n", 
window->wl.scale);
         if (!size_changed) resizeFramebuffer(window);
         _glfwInputWindowContentScale(window, window->wl.scale, 
window->wl.scale);
@@ -319,7 +339,7 @@
 
     _glfwInputWindowDamage(window);
 
-    return size_changed || *scale_changed;
+    return size_changed || scale_changed;
 }
 
 static void
@@ -568,6 +588,15 @@
                                       struct xdg_surface* surface,
                                       uint32_t serial)
 {
+    // The poorly documented pattern Wayland requires is:
+    // 1) ack the configure,
+    // 2) set the window geometry
+    // 3) attach a new buffer of the correct size to the surface
+    // 4) only then commit the surface.
+    // buffer is attached only by eglSwapBuffers,
+    // so we set a flag to not commit the surface till the next swapbuffers. 
Note that
+    // wl_egl_window_resize() does not actually resize the buffer until the 
next draw call
+    // or buffer state query.
     _GLFWwindow* window = data;
     xdg_surface_ack_configure(surface, serial);
     if (window->wl.pending_state & PENDING_STATE_TOPLEVEL) {
@@ -600,11 +629,10 @@
     }
 
     bool resized = false;
-    bool scale_changed = false;
     if (window->wl.pending_state) {
         int width = window->wl.pending.width, height = 
window->wl.pending.height;
         set_csd_window_geometry(window, &width, &height);
-        resized = dispatchChangesAfterConfigure(window, width, height, 
&scale_changed);
+        resized = dispatchChangesAfterConfigure(window, width, height);
         if (window->wl.decorations.serverSide) {
             free_csd_surfaces(window);
         } else {
@@ -614,14 +642,7 @@
     }
 
     inform_compositor_of_window_geometry(window, "configure");
-
-    // we need to swap buffers here to ensure the buffer attached to the 
surface is a multiple
-    // of the new scale. See https://github.com/kovidgoyal/kitty/issues/5467
-    if (scale_changed) swap_buffers(window);
-
-    // if a resize happened there will be a commit at the next render frame so
-    // dont commit here, GNOME doesnt like it and its not really needed anyway
-    if (!resized) wl_surface_commit(window->wl.surface);
+    commit_window_surface_if_safe(window);
     window->wl.pending_state = 0;
 }
 
@@ -1021,7 +1042,7 @@
         window->wl.width = w; window->wl.height = h;
         resizeFramebuffer(window);
         ensure_csd_resources(window);
-        wl_surface_commit(window->wl.surface);
+        commit_window_surface_if_safe(window);
         inform_compositor_of_window_geometry(window, "SetWindowSize");
     }
 }
@@ -1038,7 +1059,7 @@
             maxwidth = maxheight = 0;
         xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, 
minheight);
         xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, 
maxheight);
-        wl_surface_commit(window->wl.surface);
+        commit_window_surface_if_safe(window);
     }
 }
 
@@ -1273,7 +1294,7 @@
     }
     else
         wl_surface_set_input_region(window->wl.surface, 0);
-    wl_surface_commit(window->wl.surface);
+    commit_window_surface_if_safe(window);
 }
 
 float _glfwPlatformGetWindowOpacity(_GLFWwindow* window UNUSED)
@@ -1337,7 +1358,7 @@
         zwp_locked_pointer_v1_set_cursor_position_hint(
             window->wl.pointerLock.lockedPointer,
             wl_fixed_from_double(x), wl_fixed_from_double(y));
-        wl_surface_commit(window->wl.surface);
+        commit_window_surface_if_safe(window);
     }
 }
 
@@ -1691,9 +1712,18 @@
     zwp_primary_selection_source_v1_destroy(primary_selection_source);
 }
 
+// KWin aborts if we don't define these even though they are not used for 
copy/paste
+static void dummy_data_source_target(void* data UNUSED, struct wl_data_source* 
wl_data_source UNUSED, const char* mime_type UNUSED) {
+}
+
+static void dummy_data_source_action(void* data UNUSED, struct wl_data_source* 
wl_data_source UNUSED, uint dnd_action UNUSED) {
+}
+
 static const struct wl_data_source_listener data_source_listener = {
     .send = _glfwSendClipboardText,
     .cancelled = data_source_canceled,
+    .target = dummy_data_source_target,
+    .action = dummy_data_source_action,
 };
 
 static const struct zwp_primary_selection_source_v1_listener 
primary_selection_source_listener = {
@@ -2232,12 +2262,19 @@
     _GLFWwindow* window = (_GLFWwindow*) handle;
     static const struct wl_callback_listener frame_listener = { .done = 
frame_handle_redraw };
     if (window->wl.frameCallbackData.current_wl_callback) 
wl_callback_destroy(window->wl.frameCallbackData.current_wl_callback);
-    window->wl.frameCallbackData.id = id;
-    window->wl.frameCallbackData.callback = callback;
-    window->wl.frameCallbackData.current_wl_callback = 
wl_surface_frame(window->wl.surface);
-    if (window->wl.frameCallbackData.current_wl_callback) {
-        
wl_callback_add_listener(window->wl.frameCallbackData.current_wl_callback, 
&frame_listener, window);
-        wl_surface_commit(window->wl.surface);
+    if (window->wl.waiting_for_swap_to_commit) {
+        callback(id);
+        window->wl.frameCallbackData.id = 0;
+        window->wl.frameCallbackData.callback = NULL;
+        window->wl.frameCallbackData.current_wl_callback = NULL;
+    } else {
+        window->wl.frameCallbackData.id = id;
+        window->wl.frameCallbackData.callback = callback;
+        window->wl.frameCallbackData.current_wl_callback = 
wl_surface_frame(window->wl.surface);
+        if (window->wl.frameCallbackData.current_wl_callback) {
+            
wl_callback_add_listener(window->wl.frameCallbackData.current_wl_callback, 
&frame_listener, window);
+            commit_window_surface_if_safe(window);
+        }
     }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kittens/ssh/options/definition.py 
new/kitty-0.26.5/kittens/ssh/options/definition.py
--- old/kitty-0.26.4/kittens/ssh/options/definition.py  2022-10-17 
04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kittens/ssh/options/definition.py  2022-11-07 
11:06:42.000000000 +0100
@@ -40,10 +40,9 @@
 available or broken, using an alternate interpreter can be useful.
 ''')
 
-opt('remote_dir', '.local/share/kitty-ssh-kitten', option_type='relative_dir', 
long_text='''
+opt('remote_dir', '.local/share/kitty-ssh-kitten', long_text='''
 The location on the remote host where the files needed for this kitten are
-installed. The location is relative to the HOME directory. Absolute paths or
-paths that resolve to a location outside the HOME are not allowed.
+installed. Relative paths are resolved with respect to :code:`$HOME`.
 ''')
 
 opt('+copy', '', option_type='copy', add_to_default=False, long_text=f'''
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kittens/ssh/options/parse.py 
new/kitty-0.26.5/kittens/ssh/options/parse.py
--- old/kitty-0.26.4/kittens/ssh/options/parse.py       2022-10-17 
04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kittens/ssh/options/parse.py       2022-11-07 
11:06:42.000000000 +0100
@@ -1,7 +1,7 @@
 # generated by gen-config.py DO NOT edit
 
 import typing
-from kittens.ssh.options.utils import copy, env, hostname, relative_dir
+from kittens.ssh.options.utils import copy, env, hostname
 from kitty.conf.utils import merge_dicts, to_bool
 
 
@@ -39,7 +39,7 @@
         ans['login_shell'] = str(val)
 
     def remote_dir(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
-        ans['remote_dir'] = relative_dir(val)
+        ans['remote_dir'] = str(val)
 
     def remote_kitty(self, val: str, ans: typing.Dict[str, typing.Any]) -> 
None:
         val = val.lower()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kittens/ssh/options/utils.py 
new/kitty-0.26.5/kittens/ssh/options/utils.py
--- old/kitty-0.26.4/kittens/ssh/options/utils.py       2022-10-17 
04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kittens/ssh/options/utils.py       2022-11-07 
11:06:42.000000000 +0100
@@ -1,7 +1,6 @@
 #!/usr/bin/env python
 # License: GPLv3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
 
-import posixpath
 from typing import Any, Dict, Iterable, Optional, Tuple
 
 from ..copy import CopyInstruction, parse_copy_instructions
@@ -9,16 +8,6 @@
 DELETE_ENV_VAR = '_delete_this_env_var_'
 
 
-def relative_dir(val: str) -> str:
-    if posixpath.isabs(val):
-        raise ValueError(f'Absolute paths not allowed. {val} is invalid.')
-    base = '/ffjdg'
-    q = posixpath.normpath(posixpath.join(base, val))
-    if q == base or not q.startswith(base):
-        raise ValueError(f'Paths that escape their parent dir are not allowed. 
{val} is not valid')
-    return posixpath.normpath(val)
-
-
 def env(val: str, current_val: Dict[str, str]) -> Iterable[Tuple[str, str]]:
     val = val.strip()
     if val:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/boss.py 
new/kitty-0.26.5/kitty/boss.py
--- old/kitty-0.26.4/kitty/boss.py      2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/boss.py      2022-11-07 11:06:42.000000000 +0100
@@ -12,8 +12,8 @@
 from gettext import gettext as _
 from time import monotonic
 from typing import (
-    TYPE_CHECKING, Any, Callable, Container, Dict, Iterable, Iterator, List,
-    Optional, Set, Tuple, Union
+    TYPE_CHECKING, Any, Callable, Container, Dict, Iterable, Iterator, List, 
Optional,
+    Set, Tuple, Union,
 )
 from weakref import WeakValueDictionary
 
@@ -21,15 +21,15 @@
 from .cli import create_opts, parse_args
 from .cli_stub import CLIOptions
 from .clipboard import (
-    Clipboard, get_clipboard_string, get_primary_selection,
-    set_clipboard_string, set_primary_selection
+    Clipboard, get_clipboard_string, get_primary_selection, 
set_clipboard_string,
+    set_primary_selection,
 )
 from .conf.utils import BadLine, KeyAction, to_cmdline
 from .config import common_opts_as_dict, prepare_config_file_for_editing
 from .constants import (
     RC_ENCRYPTION_PROTOCOL_VERSION, appname, cache_dir, clear_handled_signals,
-    config_dir, handled_signals, is_macos, is_wayland, kitty_exe,
-    logo_png_file, supports_primary_selection, website_url
+    config_dir, handled_signals, is_macos, is_wayland, kitty_exe, 
logo_png_file,
+    supports_primary_selection, website_url,
 )
 from .fast_data_types import (
     CLOSE_BEING_CONFIRMED, GLFW_MOD_ALT, GLFW_MOD_CONTROL, GLFW_MOD_SHIFT,
@@ -37,15 +37,15 @@
     IMPERATIVE_CLOSE_REQUESTED, NO_CLOSE_REQUESTED, ChildMonitor, Color,
     EllipticCurveKey, KeyEvent, SingleKey, add_timer, apply_options_update,
     background_opacity_of, change_background_opacity, change_os_window_state,
-    cocoa_set_menubar_title, create_os_window,
-    current_application_quit_request, current_os_window, destroy_global_data,
-    focus_os_window, get_boss, get_options, get_os_window_size,
-    global_font_size, mark_os_window_for_close, os_window_font_size,
-    patch_global_colors, redirect_mouse_handling, ring_bell,
-    run_with_activation_token, safe_pipe, send_data_to_peer,
-    set_application_quit_request, set_background_image, set_boss,
-    set_in_sequence_mode, set_options, set_os_window_size, set_os_window_title,
-    thread_write, toggle_fullscreen, toggle_maximized, toggle_secure_input
+    cocoa_set_menubar_title, create_os_window, 
current_application_quit_request,
+    current_focused_os_window_id, current_os_window, destroy_global_data,
+    focus_os_window, get_boss, get_options, get_os_window_size, 
global_font_size,
+    last_focused_os_window_id, mark_os_window_for_close, os_window_font_size,
+    patch_global_colors, redirect_mouse_handling, ring_bell, 
run_with_activation_token,
+    safe_pipe, send_data_to_peer, set_application_quit_request, 
set_background_image,
+    set_boss, set_in_sequence_mode, set_options, set_os_window_size,
+    set_os_window_title, thread_write, toggle_fullscreen, toggle_maximized,
+    toggle_secure_input,
 )
 from .key_encoding import get_name_to_functional_number_map
 from .keys import get_shortcut, shortcut_matches
@@ -57,16 +57,14 @@
 from .prewarm import PrewarmProcess
 from .rgb import color_from_int
 from .session import Session, create_sessions, get_os_window_sizing_data
-from .tabs import (
-    SpecialWindow, SpecialWindowInstance, Tab, TabDict, TabManager
-)
+from .tabs import SpecialWindow, SpecialWindowInstance, Tab, TabDict, 
TabManager
 from .types import _T, AsyncResponse, WindowSystemMouseEvent, ac
 from .typing import PopenType, TypedDict
 from .utils import (
     cleanup_ssh_control_masters, func_name, get_editor, get_new_os_window_size,
     is_path_in_temp_dir, less_version, log_error, macos_version, open_url,
     parse_address_spec, parse_uri_list, platform_window_id, remove_socket_file,
-    safe_print, single_instance, startup_notification_handler, which
+    safe_print, single_instance, startup_notification_handler, which,
 )
 from .window import CommandOutput, CwdRequest, Window
 
@@ -80,6 +78,8 @@
     id: int
     platform_window_id: Optional[int]
     is_focused: bool
+    is_active: bool
+    last_focused: bool
     tabs: List[TabDict]
     wm_class: str
     wm_name: str
@@ -227,7 +227,7 @@
             t = tm.tab_for_id(self.prev_tab_id)
             if t is not tm.active_tab and t is not None:
                 tm.set_active_tab(t)
-        if current_os_window() != self.prev_os_window_id and 
self.prev_os_window_id is not None:
+        if current_focused_os_window_id() != self.prev_os_window_id and 
self.prev_os_window_id is not None:
             focus_os_window(self.prev_os_window_id, True)
 
 
@@ -287,9 +287,7 @@
         self.mouse_handler: Optional[Callable[[WindowSystemMouseEvent], None]] 
= None
         self.update_keymap()
         if is_macos:
-            from .fast_data_types import (
-                cocoa_set_notification_activated_callback
-            )
+            from .fast_data_types import 
cocoa_set_notification_activated_callback
             cocoa_set_notification_activated_callback(notification_activated)
 
     def update_keymap(self) -> None:
@@ -345,14 +343,15 @@
 
     def list_os_windows(self, self_window: Optional[Window] = None) -> 
Iterator[OSWindowDict]:
         with cached_process_data():
-            active_tab, active_window = self.active_tab, self.active_window
             active_tab_manager = self.active_tab_manager
             for os_window_id, tm in self.os_window_map.items():
                 yield {
                     'id': os_window_id,
                     'platform_window_id': platform_window_id(os_window_id),
-                    'is_focused': tm is active_tab_manager,
-                    'tabs': list(tm.list_tabs(active_tab, active_window, 
self_window)),
+                    'is_active': tm is active_tab_manager,
+                    'is_focused': current_focused_os_window_id() == 
os_window_id,
+                    'last_focused': os_window_id == 
last_focused_os_window_id(),
+                    'tabs': list(tm.list_tabs(self_window)),
                     'wm_class': tm.wm_class,
                     'wm_name': tm.wm_name
                 }
@@ -377,6 +376,10 @@
             return
         from .search_query_parser import search
         tab = self.active_tab
+        if current_focused_os_window_id() <= 0:
+            tm = self.os_window_map.get(last_focused_os_window_id())
+            if tm is not None:
+                tab = tm.active_tab
 
         def get_matches(location: str, query: str, candidates: Set[int]) -> 
Set[int]:
             return {wid for wid in candidates if 
self.window_id_map[wid].matches_query(location, query, tab)}
@@ -398,6 +401,8 @@
             return self.all_tabs
         from .search_query_parser import search
         tm = self.active_tab_manager
+        if current_focused_os_window_id() <= 0:
+            tm = self.os_window_map.get(last_focused_os_window_id()) or tm
         tim = {t.id: t for t in self.all_tabs}
 
         def get_matches(location: str, query: str, candidates: Set[int]) -> 
Set[int]:
@@ -424,7 +429,7 @@
                         if tab is not self.active_tab:
                             tm.set_active_tab(tab, 
for_keep_focus=window.tabref() if for_keep_focus else None)
                         tab.set_active_window(w, for_keep_focus=window if 
for_keep_focus else None)
-                        if switch_os_window_if_needed and current_os_window() 
!= os_window_id:
+                        if switch_os_window_if_needed and 
current_focused_os_window_id() != os_window_id:
                             focus_os_window(os_window_id, True)
                         return os_window_id
         return None
@@ -534,9 +539,7 @@
         return True
 
     def remote_cmd_permission_received(self, pcmd: Dict[str, Any], window_id: 
int, peer_id: int, choice: str) -> None:
-        from .remote_control import (
-            encode_response_for_peer, set_user_password_allowed
-        )
+        from .remote_control import encode_response_for_peer, 
set_user_password_allowed
         response: RCResponse = None
         window = self.window_id_map.get(window_id)
         choice = choice or 'r'
@@ -587,9 +590,7 @@
             self.show_error(_('remote_control mapping failed'), tb)
 
     def call_remote_control(self, active_window: Optional[Window], args: 
Tuple[str, ...]) -> 'ResponseType':
-        from .rc.base import (
-            PayloadGetter, command_for_name, parse_subcommand_cli
-        )
+        from .rc.base import PayloadGetter, command_for_name, 
parse_subcommand_cli
         from .remote_control import parse_rc_args
         aa = list(args)
         silent = False
@@ -1088,8 +1089,14 @@
 
     @property
     def active_tab_manager(self) -> Optional[TabManager]:
-        os_window_id = current_os_window()
-        return None if os_window_id is None else 
self.os_window_map.get(os_window_id)
+        os_window_id = current_focused_os_window_id()
+        if os_window_id <= 0:
+            os_window_id = last_focused_os_window_id()
+        if os_window_id <= 0:
+            q = current_os_window()
+            if q is not None:
+                os_window_id = q
+        return self.os_window_map.get(os_window_id)
 
     @property
     def active_tab(self) -> Optional[Tab]:
@@ -2248,9 +2255,7 @@
                     log_error(f'Failed to process update check data {raw!r}, 
with error: {e}')
 
     def dbus_notification_callback(self, activated: bool, a: int, b: 
Union[int, str]) -> None:
-        from .notify import (
-            dbus_notification_activated, dbus_notification_created
-        )
+        from .notify import dbus_notification_activated, 
dbus_notification_created
         if activated:
             assert isinstance(b, str)
             dbus_notification_activated(a, b)
@@ -2284,9 +2289,7 @@
             map f5 set_colors --configured 
/path/to/some/config/file/colors.conf
         ''')
     def set_colors(self, *args: str) -> None:
-        from kitty.rc.base import (
-            PayloadGetter, command_for_name, parse_subcommand_cli
-        )
+        from kitty.rc.base import PayloadGetter, command_for_name, 
parse_subcommand_cli
         from kitty.remote_control import parse_rc_args
         c = command_for_name('set_colors')
         try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/child-monitor.c 
new/kitty-0.26.5/kitty/child-monitor.c
--- old/kitty-0.26.4/kitty/child-monitor.c      2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/kitty/child-monitor.c      2022-11-07 11:06:42.000000000 
+0100
@@ -690,6 +690,11 @@
     float x_ratio = 1, y_ratio = 1;
     draw_borders(br->vao_idx, br->num_border_rects, br->rect_buf, 
br->is_dirty, os_window->viewport_width, os_window->viewport_height, 
active_window_bg, num_visible_windows, all_windows_have_same_bg, os_window);
     br->is_dirty = false;
+    bool static_live_resize_in_progress = os_window->live_resize.in_progress 
&& OPT(resize_draw_strategy) == RESIZE_DRAW_STATIC;
+    if (static_live_resize_in_progress) {
+        x_ratio = (float) os_window->viewport_width / (float) 
os_window->live_resize.width;
+        y_ratio = (float) os_window->viewport_height / (float) 
os_window->live_resize.height;
+    }
     if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) 
draw_cells(TD.vao_idx, 0, &TD, x_ratio, y_ratio, os_window, true, false, NULL);
     for (unsigned int i = 0; i < tab->num_windows; i++) {
         Window *w = tab->windows + i;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/constants.py 
new/kitty-0.26.5/kitty/constants.py
--- old/kitty-0.26.4/kitty/constants.py 2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/constants.py 2022-11-07 11:06:42.000000000 +0100
@@ -6,7 +6,7 @@
 import pwd
 import sys
 from contextlib import suppress
-from typing import TYPE_CHECKING, Any, Iterable, NamedTuple, Optional, Set
+from typing import TYPE_CHECKING, Any, Iterator, NamedTuple, Optional, Set
 
 from .types import run_once
 
@@ -22,7 +22,7 @@
 
 appname: str = 'kitty'
 kitty_face = '????'
-version: Version = Version(0, 26, 4)
+version: Version = Version(0, 26, 5)
 str_version: str = '.'.join(map(str, version))
 _plat = sys.platform.lower()
 is_macos: bool = 'darwin' in _plat
@@ -219,15 +219,28 @@
     return bool(getattr(running_in_kitty, 'ans', False))
 
 
-def list_kitty_resources(package: str = 'kitty') -> Iterable[str]:
-    from importlib.resources import contents
-    return contents(package)
+def list_kitty_resources(package: str = 'kitty') -> Iterator[str]:
+    try:
+        if sys.version_info[:2] < (3, 10):
+            raise ImportError('importlib.resources.files() doesnt work with 
frozen builds on python 3.9')
+        from importlib.resources import files
+    except ImportError:
+        from importlib.resources import contents
+        return iter(contents(package))
+    else:
+        return (path.name for path in files(package).iterdir())
 
 
 def read_kitty_resource(name: str, package_name: str = 'kitty') -> bytes:
-    from importlib.resources import read_binary
-
-    return read_binary(package_name, name)
+    try:
+        if sys.version_info[:2] < (3, 10):
+            raise ImportError('importlib.resources.files() doesnt work with 
frozen builds on python 3.9')
+        from importlib.resources import files
+    except ImportError:
+        from importlib.resources import read_binary
+        return read_binary(package_name, name)
+    else:
+        return (files(package_name) / name).read_bytes()
 
 
 def website_url(doc_name: str = '', website: str = 
'https://sw.kovidgoyal.net/kitty/') -> str:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/fast_data_types.pyi 
new/kitty-0.26.5/kitty/fast_data_types.pyi
--- old/kitty-0.26.4/kitty/fast_data_types.pyi  2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/kitty/fast_data_types.pyi  2022-11-07 11:06:42.000000000 
+0100
@@ -786,6 +786,14 @@
     pass
 
 
+def last_focused_os_window_id() -> int:
+    pass
+
+
+def current_focused_os_window_id() -> int:
+    pass
+
+
 def cocoa_set_menubar_title(title: str) -> None:
     pass
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/glfw.c 
new/kitty-0.26.5/kitty/glfw.c
--- old/kitty-0.26.4/kitty/glfw.c       2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/glfw.c       2022-11-07 11:06:42.000000000 +0100
@@ -312,14 +312,6 @@
     window->live_resize.last_resize_event_at = monotonic();
     global_state.callback_os_window = NULL;
     request_tick_callback();
-    if (global_state.is_wayland) {
-        // because of the stupidity of Wayland design, the GLFW wayland backend
-        // will need to swap buffers immediately after a scale change to ensure
-        // the buffer size is a multiple of the scale. So blank the new buffer 
to
-        // ensure we dont leak any unintialized pixels to the screen. The 
OpenGL viewport
-        // will already have been resized to its new size in 
framebuffer_size_callback
-        blank_os_window(window);
-    }
 }
 
 static void
@@ -1539,8 +1531,8 @@
     // Some Wayland compositors are too fragile to handle multiple
     // render frame requests, see 
https://github.com/kovidgoyal/kitty/issues/2329
     if (w->render_state != RENDER_FRAME_REQUESTED) {
-        glfwRequestWaylandFrameEvent(w->handle, w->id, 
wayland_frame_request_callback);
         w->render_state = RENDER_FRAME_REQUESTED;
+        glfwRequestWaylandFrameEvent(w->handle, w->id, 
wayland_frame_request_callback);
     }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/layout/splits.py 
new/kitty-0.26.5/kitty/layout/splits.py
--- old/kitty-0.26.4/kitty/layout/splits.py     2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/kitty/layout/splits.py     2022-11-07 11:06:42.000000000 
+0100
@@ -414,6 +414,16 @@
     def pairs_root(self, root: Pair) -> None:
         self._pairs_root = root
 
+    def remove_windows(self, *windows_to_remove: int) -> None:
+        root = self.pairs_root
+        for pair in root.self_and_descendants():
+            pair.remove_windows(windows_to_remove)
+        root.collapse_redundant_pairs()
+        if root.one is None or root.two is None:
+            q = root.one or root.two
+            if isinstance(q, Pair):
+                self.pairs_root = q
+
     def do_layout(self, all_windows: WindowList) -> None:
         groups = tuple(all_windows.iter_all_layoutable_groups())
         window_count = len(groups)
@@ -421,15 +431,8 @@
         all_present_window_ids = frozenset(w.id for w in groups)
         already_placed_window_ids = frozenset(root.all_window_ids())
         windows_to_remove = already_placed_window_ids - all_present_window_ids
-
         if windows_to_remove:
-            for pair in root.self_and_descendants():
-                pair.remove_windows(windows_to_remove)
-            root.collapse_redundant_pairs()
-            if root.one is None or root.two is None:
-                q = root.one or root.two
-                if isinstance(q, Pair):
-                    root = self.pairs_root = q
+            self.remove_windows(*windows_to_remove)
         id_window_map = {w.id: w for w in groups}
         id_idx_map = {w.id: i for i, w in enumerate(groups)}
         windows_to_add = all_present_window_ids - already_placed_window_ids
@@ -552,6 +555,23 @@
                     if swap:
                         pair.one, pair.two = pair.two, pair.one
                     return True
+        elif action_name == 'move_to_screen_edge':
+            args = args or ('left',)
+            which = args[0]
+            horizontal = which in ('left', 'right')
+            wg = all_windows.active_group
+            if wg is not None:
+                self.remove_windows(wg.id)
+                new_root = Pair(horizontal)
+                if which in ('left', 'top'):
+                    new_root.balanced_add(wg.id)
+                    new_root.two = self.pairs_root
+                else:
+                    new_root.one = self.pairs_root
+                    new_root.two = wg.id
+                self.pairs_root = new_root
+                return True
+
         return None
 
     def layout_state(self) -> Dict[str, Any]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/multiprocessing.py 
new/kitty-0.26.5/kitty/multiprocessing.py
--- old/kitty-0.26.4/kitty/multiprocessing.py   2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/kitty/multiprocessing.py   2022-11-07 11:06:42.000000000 
+0100
@@ -81,7 +81,7 @@
         q = ctx.Queue()
         p = ctx.Process(target=q.put, args=('hello',))
         p.start()
-        x = q.get(timeout=2)
+        x = q.get(timeout=8)
         assert x == 'hello'
         p.join()
     finally:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/prewarm.py 
new/kitty-0.26.5/kitty/prewarm.py
--- old/kitty-0.26.4/kitty/prewarm.py   2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/prewarm.py   2022-11-07 11:06:42.000000000 +0100
@@ -38,7 +38,7 @@
 
 
 error_events = select.POLLERR | select.POLLNVAL | select.POLLHUP
-TIMEOUT = 15.0 if os.environ.get('CI') == 'true' else 5.0
+TIMEOUT = 5.0
 
 
 def restore_python_signal_handlers() -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/rc/base.py 
new/kitty-0.26.5/kitty/rc/base.py
--- old/kitty-0.26.4/kitty/rc/base.py   2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/rc/base.py   2022-11-07 11:06:42.000000000 +0100
@@ -100,7 +100,7 @@
 The field :code:`state` matches on the state of the window. Supported states 
are:
 :code:`active`, :code:`focused`, :code:`needs_attention`, 
:code:`parent_active` and :code:`parent_focused`.
 Active windows are the windows that are active in their parent tab. There is 
only one focused window and it is the
-window to which keyboard events are delivered.
+window to which keyboard events are delivered. If no window is focused, the 
last focused window is matched.
 
 Note that you can use the :ref:`kitty @ ls <at-ls>` command to get a list of 
windows.
 '''
@@ -134,7 +134,7 @@
 The field :code:`state` matches on the state of the tab. Supported states are:
 :code:`active`, :code:`focused`, :code:`needs_attention`, 
:code:`parent_active` and :code:`parent_focused`.
 Active tabs are the tabs that are active in their parent OS window. There is 
only one focused tab
-and it is the tab to which keyboard events are delivered.
+and it is the tab to which keyboard events are delivered. If no tab is 
focused, the last focused tab is matched.
 
 Note that you can use the :ref:`kitty @ ls <at-ls>` command to get a list of 
tabs.
 '''
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/rewrap.h 
new/kitty-0.26.5/kitty/rewrap.h
--- old/kitty-0.26.4/kitty/rewrap.h     2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/rewrap.h     2022-11-07 11:06:42.000000000 +0100
@@ -81,7 +81,7 @@
             for (TrackCursor *t = track; !t->is_sentinel; t++) {
                 if (t->is_tracked_line && src_x <= t->x && t->x < src_x + num) 
{
                     t->y = dest_y;
-                    t->x = dest_x + (t->x - src_x + 1);
+                    t->x = dest_x + (t->x - src_x + (t->x > 0));
                 }
             }
             src_x += num; dest_x += num;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/screen.c 
new/kitty-0.26.5/kitty/screen.c
--- old/kitty-0.26.4/kitty/screen.c     2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/screen.c     2022-11-07 11:06:42.000000000 +0100
@@ -368,6 +368,7 @@
     if (n == NULL) return false;
     Py_CLEAR(self->main_linebuf); self->main_linebuf = n;
     if (is_main) setup_cursor(cursor);
+    /* printf("old_cursor: (%u, %u) new_cursor: (%u, %u) beyond_content: 
%d\n", self->cursor->x, self->cursor->y, cursor.after.x, cursor.after.y, 
cursor.is_beyond_content); */
     setup_cursor(main_saved_cursor);
     grman_resize(self->main_grman, self->lines, lines, self->columns, columns);
 
@@ -396,7 +397,6 @@
     clear_selection(&self->selections);
     clear_selection(&self->url_ranges);
     self->last_visited_prompt.is_set = false;
-    /* printf("old_cursor: (%u, %u) new_cursor: (%u, %u) beyond_content: 
%d\n", self->cursor->x, self->cursor->y, cursor_x, cursor_y, 
cursor_is_beyond_content); */
 #define S(c, w) c->x = MIN(w.after.x, self->columns - 1); c->y = 
MIN(w.after.y, self->lines - 1);
     S(self->cursor, cursor);
     S((&(self->main_savepoint.cursor)), main_saved_cursor);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/shaders.c 
new/kitty-0.26.5/kitty/shaders.c
--- old/kitty-0.26.4/kitty/shaders.c    2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/shaders.c    2022-11-07 11:06:42.000000000 +0100
@@ -12,6 +12,7 @@
 #include "window_logo.h"
 
 #define BLEND_ONTO_OPAQUE  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  
// blending onto opaque colors
+#define BLEND_ONTO_OPAQUE_WITH_OPAQUE_OUTPUT  
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);  // 
blending onto opaque colors with final color having alpha 1
 #define BLEND_PREMULT glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);  // 
blending of pre-multiplied colors
 
 enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, 
BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, 
GRAPHICS_ALPHA_MASK_PROGRAM, BLIT_PROGRAM, BGIMAGE_PROGRAM, TINT_PROGRAM, 
NUM_PROGRAMS };
@@ -531,7 +532,7 @@
 
 static void
 draw_tint(bool premult, Screen *screen, const CellRenderData *crd) {
-    // On GNOME+Wayland this causes ghosting while rendering. Yet another 
GNOME bug, does not occur under KDE, Hyprland or Sway.
+    if (premult) { BLEND_PREMULT } else { BLEND_ONTO_OPAQUE_WITH_OPAQUE_OUTPUT 
}
     bind_program(TINT_PROGRAM);
     color_type window_bg = colorprofile_to_color(screen->color_profile, 
screen->color_profile->overridden.default_bg, 
screen->color_profile->configured.default_bg).rgb;
 #define C(shift) ((((GLfloat)((window_bg >> shift) & 0xFF)) / 255.0f)) * 
premult_factor
@@ -721,7 +722,6 @@
         
glUniform1ui(cell_program_layouts[CELL_BG_PROGRAM].draw_bg_bitfield_location, 
3);
         glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * 
screen->columns);
     } else if (OPT(background_tint) > 0) {
-        BLEND_ONTO_OPAQUE;
         draw_tint(false, screen, crd);
         BLEND_ONTO_OPAQUE;
     }
@@ -758,7 +758,6 @@
 draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen 
*screen, OSWindow *os_window, const CellRenderData *crd, const 
WindowLogoRenderData *wl) {
     if (OPT(background_tint) > 0.f) {
         glEnable(GL_BLEND);
-        BLEND_PREMULT;
         draw_tint(true, screen, crd);
         glDisable(GL_BLEND);
     }
@@ -982,7 +981,7 @@
         BLEND_ONTO_OPAQUE;
         background_opacity = 1.0f;
         tint_opacity = OPT(background_tint);
-        tint_premult = 1.0f;
+        tint_premult = w->is_semi_transparent ? OPT(background_tint) : 1.0f;
     }
 
     if (num_border_rects) {
@@ -1007,6 +1006,10 @@
         color_type default_bg = (num_visible_windows > 1 && 
!all_windows_have_same_bg) ? OPT(background) : active_window_bg;
         glUniform3f(border_uniform_locations[BORDER_default_bg], 
CV3(default_bg));
 #undef CV3
+        if (has_bgimage(w)) {
+            if (w->is_semi_transparent) { BLEND_PREMULT; }
+            else { BLEND_ONTO_OPAQUE_WITH_OPAQUE_OUTPUT; }
+        }
         glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, num_border_rects);
         unbind_vertex_array();
         unbind_program();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/state.c 
new/kitty-0.26.5/kitty/state.c
--- old/kitty-0.26.4/kitty/state.c      2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/state.c      2022-11-07 11:06:42.000000000 +0100
@@ -96,7 +96,7 @@
 
 
 OSWindow*
-current_os_window() {
+current_os_window(void) {
     if (global_state.callback_os_window) return 
global_state.callback_os_window;
     for (size_t i = 0; i < global_state.num_os_windows; i++) {
         if (global_state.os_windows[i].is_focused) return 
global_state.os_windows + i;
@@ -104,6 +104,29 @@
     return global_state.os_windows;
 }
 
+static id_type
+last_focused_os_window_id(void) {
+    id_type ans = 0, max_fc_count = 0;
+    for (size_t i = 0; i < global_state.num_os_windows; i++) {
+        OSWindow *w = &global_state.os_windows[i];
+        if (w->last_focused_counter > max_fc_count) {
+            ans = w->id; max_fc_count = w->last_focused_counter;
+        }
+    }
+    return ans;
+}
+
+
+static id_type
+current_focused_os_window_id(void) {
+    for (size_t i = 0; i < global_state.num_os_windows; i++) {
+        OSWindow *w = &global_state.os_windows[i];
+        if (w->is_focused) { return w->id; }
+    }
+    return 0;
+}
+
+
 OSWindow*
 os_window_for_kitty_window(id_type kitty_window_id) {
     for (size_t i = 0; i < global_state.num_os_windows; i++) {
@@ -665,6 +688,15 @@
     return PyLong_FromUnsignedLongLong(global_state.window_id_counter + 1);
 }
 
+PYWRAP0(last_focused_os_window_id) {
+    return PyLong_FromUnsignedLongLong(last_focused_os_window_id());
+}
+
+PYWRAP0(current_focused_os_window_id) {
+    return PyLong_FromUnsignedLongLong(current_focused_os_window_id());
+}
+
+
 PYWRAP1(handle_for_window_id) {
     id_type os_window_id;
     PA("K", &os_window_id);
@@ -1266,6 +1298,8 @@
 static PyMethodDef module_methods[] = {
     MW(current_os_window, METH_NOARGS),
     MW(next_window_id, METH_NOARGS),
+    MW(last_focused_os_window_id, METH_NOARGS),
+    MW(current_focused_os_window_id, METH_NOARGS),
     MW(set_options, METH_VARARGS),
     MW(get_options, METH_NOARGS),
     MW(click_mouse_url, METH_VARARGS),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/tab_bar.py 
new/kitty-0.26.5/kitty/tab_bar.py
--- old/kitty-0.26.4/kitty/tab_bar.py   2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/tab_bar.py   2022-11-07 11:06:42.000000000 +0100
@@ -2,6 +2,7 @@
 # License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
 
 import os
+import re
 from functools import lru_cache, partial, wraps
 from string import Formatter as StringFormatter
 from typing import (
@@ -189,7 +190,7 @@
 
 
 safe_builtins = {
-    'max': max, 'min': min, 'str': str, 'repr': repr, 'abs': abs, 'len': len,
+    'max': max, 'min': min, 'str': str, 'repr': repr, 'abs': abs, 'len': len, 
're': re,
 }
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/tabs.py 
new/kitty-0.26.5/kitty/tabs.py
--- old/kitty-0.26.4/kitty/tabs.py      2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/tabs.py      2022-11-07 11:06:42.000000000 +0100
@@ -10,8 +10,8 @@
 from operator import attrgetter
 from time import monotonic
 from typing import (
-    Any, Deque, Dict, Generator, Iterable, Iterator, List,
-    NamedTuple, Optional, Sequence, Set, Tuple, Union
+    Any, Deque, Dict, Generator, Iterable, Iterator, List, NamedTuple, 
Optional,
+    Sequence, Set, Tuple, Union,
 )
 
 from .borders import Border, Borders
@@ -19,11 +19,11 @@
 from .cli_stub import CLIOptions
 from .constants import appname, kitty_exe
 from .fast_data_types import (
-    GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, GLFW_RELEASE,
-    add_tab, attach_window, current_os_window, detach_window, get_boss,
-    get_click_interval, get_options, mark_tab_bar_dirty, next_window_id,
-    remove_tab, remove_window, ring_bell, set_active_tab, set_active_window,
-    swap_tabs, sync_os_window_title
+    GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, 
GLFW_RELEASE, add_tab,
+    attach_window, current_focused_os_window_id, detach_window, get_boss,
+    get_click_interval, get_options, last_focused_os_window_id, 
mark_tab_bar_dirty,
+    next_window_id, remove_tab, remove_window, ring_bell, set_active_tab,
+    set_active_window, swap_tabs, sync_os_window_title,
 )
 from .layout.base import Layout
 from .layout.interface import create_layout_object_for, evict_cached_layouts
@@ -46,6 +46,7 @@
 class TabDict(TypedDict):
     id: int
     is_focused: bool
+    is_active_tab: bool
     title: str
     layout: str
     layout_state: Dict[str, Any]
@@ -698,9 +699,13 @@
     def move_window_backward(self) -> None:
         self.move_window(-1)
 
-    def list_windows(self, active_window: Optional[Window], self_window: 
Optional[Window] = None) -> Generator[WindowDict, None, None]:
+    def list_windows(self, self_window: Optional[Window] = None) -> 
Generator[WindowDict, None, None]:
+        active_window = self.active_window
         for w in self:
-            yield w.as_dict(is_focused=w is active_window, is_self=w is 
self_window)
+            yield w.as_dict(
+                is_active_window=w is active_window,
+                is_focused=w.os_window_id == current_focused_os_window_id() 
and w is active_window,
+                is_self=w is self_window)
 
     def matches_query(self, field: str, query: str, active_tab_manager: 
Optional['TabManager'] = None) -> bool:
         if field == 'title':
@@ -724,9 +729,10 @@
             return False
         if field == 'state':
             if query == 'active':
-                return active_tab_manager is not None and self is 
active_tab_manager.active_tab
+                tm = self.tab_manager_ref()
+                return tm is not None and self is tm.active_tab
             if query == 'focused':
-                return active_tab_manager is not None and self is 
active_tab_manager.active_tab and self.os_window_id == current_os_window()
+                return active_tab_manager is not None and self is 
active_tab_manager.active_tab and self.os_window_id == 
last_focused_os_window_id()
             if query == 'needs_attention':
                 for w in self:
                     if w.needs_attention:
@@ -734,7 +740,7 @@
             if query == 'parent_active':
                 return active_tab_manager is not None and 
self.tab_manager_ref() is active_tab_manager
             if query == 'parent_focused':
-                return active_tab_manager is not None and 
self.tab_manager_ref() is active_tab_manager and self.os_window_id == 
current_os_window()
+                return active_tab_manager is not None and 
self.tab_manager_ref() is active_tab_manager and self.os_window_id == 
last_focused_os_window_id()
             return False
         return False
 
@@ -758,7 +764,7 @@
         self.windows = WindowList(self)
 
     def __repr__(self) -> str:
-        return f'Tab(title={self.effective_title}, id={hex(id(self))})'
+        return f'Tab(title={self.effective_title}, id={self.id})'
 
     def make_active(self) -> None:
         tm = self.tab_manager_ref()
@@ -934,17 +940,19 @@
     def __len__(self) -> int:
         return len(self.tabs)
 
-    def list_tabs(self, active_tab: Optional[Tab], active_window: 
Optional[Window], self_window: Optional[Window] = None) -> Generator[TabDict, 
None, None]:
+    def list_tabs(self, self_window: Optional[Window] = None) -> 
Generator[TabDict, None, None]:
+        active_tab = self.active_tab
         for tab in self:
             yield {
                 'id': tab.id,
-                'is_focused': tab is active_tab,
+                'is_focused': tab is active_tab and tab.os_window_id == 
current_focused_os_window_id(),
+                'is_active_tab': tab is active_tab,
                 'title': tab.name or tab.title,
                 'layout': str(tab.current_layout.name),
                 'layout_state': tab.current_layout.layout_state(),
                 'layout_opts': tab.current_layout.layout_opts.serialized(),
                 'enabled_layouts': tab.enabled_layouts,
-                'windows': list(tab.list_windows(active_window, self_window)),
+                'windows': list(tab.list_windows(self_window)),
                 'active_window_history': 
list(tab.windows.active_window_history),
             }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty/window.py 
new/kitty-0.26.5/kitty/window.py
--- old/kitty-0.26.4/kitty/window.py    2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty/window.py    2022-11-07 11:06:42.000000000 +0100
@@ -36,11 +36,12 @@
     NUM_UNDERLINE_STYLES, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE,
     STRIKETHROUGH, TINT_PROGRAM, Color, KeyEvent, Screen, add_timer, 
add_window,
     cell_size_for_window, click_mouse_cmd_output, click_mouse_url, 
compile_program,
-    current_os_window, encode_key_for_tty, get_boss, get_click_interval, 
get_options,
-    init_cell_program, mark_os_window_dirty, mouse_selection,
-    move_cursor_to_mouse_if_in_prompt, pt_to_px, set_titlebar_color, 
set_window_logo,
-    set_window_padding, set_window_render_data, update_ime_position_for_window,
-    update_window_title, update_window_visibility, wakeup_main_loop,
+    current_focused_os_window_id, encode_key_for_tty, get_boss, 
get_click_interval,
+    get_options, init_cell_program, last_focused_os_window_id, 
mark_os_window_dirty,
+    mouse_selection, move_cursor_to_mouse_if_in_prompt, pt_to_px, 
set_titlebar_color,
+    set_window_logo, set_window_padding, set_window_render_data,
+    update_ime_position_for_window, update_window_title, 
update_window_visibility,
+    wakeup_main_loop,
 )
 from .keys import keyboard_mode_name, mod_mask
 from .notify import (
@@ -138,6 +139,7 @@
 class WindowDict(TypedDict):
     id: int
     is_focused: bool
+    is_active_window: bool
     title: str
     pid: Optional[int]
     cwd: str
@@ -614,10 +616,11 @@
     def __repr__(self) -> str:
         return f'Window(title={self.title}, id={self.id})'
 
-    def as_dict(self, is_focused: bool = False, is_self: bool = False) -> 
WindowDict:
+    def as_dict(self, is_focused: bool = False, is_self: bool = False, 
is_active_window: bool = False) -> WindowDict:
         return dict(
             id=self.id,
             is_focused=is_focused,
+            is_active_window=is_active_window,
             title=self.title,
             pid=self.child.pid,
             cwd=self.child.current_cwd or self.child.cwd,
@@ -705,15 +708,20 @@
             return False
         if field == 'state':
             if query == 'active':
-                return active_tab is not None and self is 
active_tab.active_window
+                tab = self.tabref()
+                return tab is not None and tab.active_window is self
             if query == 'focused':
-                return active_tab is not None and self is 
active_tab.active_window and current_os_window() == self.os_window_id
+                return active_tab is not None and self is 
active_tab.active_window and last_focused_os_window_id() == self.os_window_id
             if query == 'needs_attention':
                 return self.needs_attention
             if query == 'parent_active':
-                return active_tab is not None and self.tabref() is active_tab
+                tab = self.tabref()
+                if tab is not None:
+                    tm = tab.tab_manager_ref()
+                    return tm is not None and tm.active_tab is tab
+                return False
             if query == 'parent_focused':
-                return active_tab is not None and self.tabref() is active_tab 
and current_os_window() == self.os_window_id
+                return active_tab is not None and self.tabref() is active_tab 
and last_focused_os_window_id() == self.os_window_id
             return False
         pat = compile_match_query(query, field != 'env')
         return self.matches(field, pat)
@@ -919,7 +927,7 @@
                 tab = self.tabref()
                 if tab is not None:
                     tab.relayout_borders()
-        elif self.os_window_id == current_os_window():
+        elif self.os_window_id == current_focused_os_window_id():
             # Cancel IME composition after loses focus
             update_ime_position_for_window(self.id, False, -1)
 
@@ -1354,7 +1362,7 @@
         self.destroyed = True
         del self.kitten_result_processors
         if hasattr(self, 'screen'):
-            if self.is_active and self.os_window_id == current_os_window():
+            if self.is_active and self.os_window_id == 
current_focused_os_window_id():
                 # Cancel IME composition when window is destroyed
                 update_ime_position_for_window(self.id, False, -1)
             # Remove cycles so that screen is de-allocated immediately
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty_tests/main.py 
new/kitty-0.26.5/kitty_tests/main.py
--- old/kitty-0.26.4/kitty_tests/main.py        2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/kitty_tests/main.py        2022-11-07 11:06:42.000000000 
+0100
@@ -4,9 +4,20 @@
 import importlib
 import os
 import shutil
+import sys
 import unittest
-from importlib.resources import contents
-from typing import Callable, Generator, NoReturn, Sequence, Set
+from typing import Callable, Generator, Iterator, NoReturn, Sequence, Set
+
+
+def contents(package: str) -> Iterator[str]:
+    try:
+        if sys.version_info[:2] < (3, 10):
+            raise ImportError('importlib.resources.files() doesnt work with 
frozen builds on python 3.9')
+        from importlib.resources import files
+    except ImportError:
+        from importlib.resources import contents
+        return iter(contents(package))
+    return (path.name for path in files(package).iterdir())
 
 
 def itertests(suite: unittest.TestSuite) -> Generator[unittest.TestCase, None, 
None]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty_tests/prewarm.py 
new/kitty-0.26.5/kitty_tests/prewarm.py
--- old/kitty-0.26.4/kitty_tests/prewarm.py     2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/kitty_tests/prewarm.py     2022-11-07 11:06:42.000000000 
+0100
@@ -50,7 +50,7 @@
         'pid': os.getpid(),
         'font_family': get_options().font_family,
         'stdin': sys.stdin.read(),
-        }, indent=2), "ALL_OUTPUT_PRESENT", sep="")"""], cwd=cwd, env=env, 
stdin_data=stdin_data)
+        }, indent=2), "ALL_OUTPUT_PRESENT", sep="")"""], cwd=cwd, env=env, 
stdin_data=stdin_data, timeout=15.0)
         self.assertFalse(pty.screen_contents().strip())
         p.mark_child_as_ready(child.child_id)
         pty.wait_till(lambda: 'ALL_OUTPUT_PRESENT' in pty.screen_contents())
@@ -140,7 +140,7 @@
             # macOS does not send SIGCHLD when child is continued
             # 
https://stackoverflow.com/questions/48487935/sigchld-is-sent-on-sigcont-on-linux-but-not-on-macos
             p.stdin.close()
-            p.wait(1)
+            p.wait(3)
             for fd, event in poll.poll(0):
                 read_signals(signal_read_fd, lambda si: None)
         finally:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty_tests/screen.py 
new/kitty-0.26.5/kitty_tests/screen.py
--- old/kitty-0.26.4/kitty_tests/screen.py      2022-10-17 04:48:51.000000000 
+0200
+++ new/kitty-0.26.5/kitty_tests/screen.py      2022-11-07 11:06:42.000000000 
+0100
@@ -332,6 +332,15 @@
         s.resize(s.lines - 1, s.columns)
         self.ae(x_before, s.cursor.x)
 
+        s = self.create_screen()
+        s.draw('abc')
+        b = s.cursor.x
+        s.resize(7, s.columns)
+        self.assertEqual(s.cursor.x, b)
+        s.cursor.x = 0
+        s.resize(5, s.columns)
+        self.assertEqual(s.cursor.x, 0)
+
     def test_scrollback_fill_after_resize(self):
         def prepare_screen(content=()):
             ans = 
self.create_screen(options={'scrollback_fill_enlarged_window': True})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/kitty_tests/ssh.py 
new/kitty-0.26.5/kitty_tests/ssh.py
--- old/kitty-0.26.4/kitty_tests/ssh.py 2022-10-17 04:48:51.000000000 +0200
+++ new/kitty-0.26.5/kitty_tests/ssh.py 2022-11-07 11:06:42.000000000 +0100
@@ -275,13 +275,13 @@
                 if 'bzip2' in q:
                     raise ValueError('Untarring failed with screen 
contents:\n' + q)
                 return 'UNTAR_DONE' in q
-            pty.wait_till(check_untar_or_fail)
+            pty.wait_till(check_untar_or_fail, timeout=30)
             self.assertTrue(os.path.exists(os.path.join(home_dir, 
'.terminfo/kitty.terminfo')))
             if SHELL_INTEGRATION_VALUE != 'enabled':
-                pty.wait_till(lambda: len(pty.screen_contents().splitlines()) 
> 1)
+                pty.wait_till(lambda: len(pty.screen_contents().splitlines()) 
> 1, timeout=30)
                 self.assertEqual(pty.screen.cursor.shape, 0)
             else:
-                pty.wait_till(lambda: pty.screen.cursor.shape == CURSOR_BEAM)
+                pty.wait_till(lambda: pty.screen.cursor.shape == CURSOR_BEAM, 
timeout=30)
             return pty
         finally:
             with suppress(FileNotFoundError):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/shell-integration/ssh/bootstrap.py 
new/kitty-0.26.5/shell-integration/ssh/bootstrap.py
--- old/kitty-0.26.4/shell-integration/ssh/bootstrap.py 2022-10-17 
04:48:51.000000000 +0200
+++ new/kitty-0.26.5/shell-integration/ssh/bootstrap.py 2022-11-07 
11:06:42.000000000 +0100
@@ -205,7 +205,10 @@
         with open(tdir + '/data.sh') as f:
             env_vars = f.read()
             apply_env_vars(env_vars)
-            data_dir = os.path.join(HOME, 
os.environ.pop('KITTY_SSH_KITTEN_DATA_DIR'))
+            data_dir = os.environ.pop('KITTY_SSH_KITTEN_DATA_DIR')
+            if not os.path.isabs(data_dir):
+                data_dir = os.path.join(HOME, data_dir)
+            data_dir = os.path.abspath(data_dir)
             shell_integration_dir = os.path.join(data_dir, 'shell-integration')
             compile_terminfo(tdir + '/home')
             move(tdir + '/home', HOME)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.26.4/shell-integration/ssh/bootstrap.sh 
new/kitty-0.26.5/shell-integration/ssh/bootstrap.sh
--- old/kitty-0.26.4/shell-integration/ssh/bootstrap.sh 2022-10-17 
04:48:51.000000000 +0200
+++ new/kitty-0.26.5/shell-integration/ssh/bootstrap.sh 2022-11-07 
11:06:42.000000000 +0100
@@ -103,7 +103,10 @@
     . "$tdir/bootstrap-utils.sh"
     . "$tdir/data.sh"
     [ -z "$KITTY_SSH_KITTEN_DATA_DIR" ] && die "Failed to read SSH data from 
tty"
-    data_dir="$HOME/$KITTY_SSH_KITTEN_DATA_DIR"
+    case "$KITTY_SSH_KITTEN_DATA_DIR" in
+        /*) data_dir="$KITTY_SSH_KITTEN_DATA_DIR" ;;
+        *) data_dir="$HOME/$KITTY_SSH_KITTEN_DATA_DIR"
+    esac
     shell_integration_dir="$data_dir/shell-integration"
     unset KITTY_SSH_KITTEN_DATA_DIR
     login_shell="$KITTY_LOGIN_SHELL"

Reply via email to