Hello community,

here is the log from the commit of package kitty for openSUSE:Factory checked 
in at 2020-05-11 13:43:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kitty (Old)
 and      /work/SRC/openSUSE:Factory/.kitty.new.2738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kitty"

Mon May 11 13:43:44 2020 rev:11 rq:802605 version:0.17.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/kitty/kitty.changes      2020-04-23 
18:35:01.596614485 +0200
+++ /work/SRC/openSUSE:Factory/.kitty.new.2738/kitty.changes    2020-05-11 
13:43:55.189446190 +0200
@@ -1,0 +2,19 @@
+Mon May 11 06:51:36 UTC 2020 - Michael Vetter <mvet...@suse.com>
+
+- Update to 0.17.4:
+  * Allow showing the name of the current layout and the number of
+    windows in tab titles (#2634)
+  * By default, double clicking no longer considers the : as part
+    of words, see select_by_word_characters (#2602)
+  * Fix a regression that caused clicking in the padding/margins
+    of windows in the stack layout to switch the window to the
+    first window (#2604)
+  * Report modifier key state when sending wheel events to the
+    terminal program
+  * Fix kitty @ send-text not working with text larger than 1024
+    bytes when using kitty --listen-on (#2607)
+  * Wayland: Fix OS window title not updating for hidden
+    windows (#2629)
+  * Fix background_tint making the window semi-transparent (#2618)
+
+-------------------------------------------------------------------

Old:
----
  kitty-0.17.3.tar.gz

New:
----
  kitty-0.17.4.tar.gz

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

Other differences:
------------------
++++++ kitty.spec ++++++
--- /var/tmp/diff_new_pack.uEljG3/_old  2020-05-11 13:43:56.521449015 +0200
+++ /var/tmp/diff_new_pack.uEljG3/_new  2020-05-11 13:43:56.525449024 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           kitty
-Version:        0.17.3
+Version:        0.17.4
 Release:        0
 Summary:        A GPU-based terminal emulator
 License:        GPL-3.0-only

++++++ kitty-0.17.3.tar.gz -> kitty-0.17.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/docs/changelog.rst 
new/kitty-0.17.4/docs/changelog.rst
--- old/kitty-0.17.3/docs/changelog.rst 2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/docs/changelog.rst 2020-05-09 07:18:21.000000000 +0200
@@ -4,6 +4,34 @@
 |kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
 To update |kitty|, :doc:`follow the instructions <binary>`.
 
+
+0.17.4 [2020-05-09]
+--------------------
+
+- Allow showing the name of the current layout and the number of windows
+  in tab titles (:iss:`2634`)
+
+- macOS: Fix a regression in the previous release that caused ligatures to be
+  not be centered horizontally (:iss:`2591`)
+
+- By default, double clicking no longer considers the : as part of words, see
+  :opt:`select_by_word_characters` (:iss:`2602`)
+
+- Fix a regression that caused clicking in the padding/margins of windows in
+  the stack layout to switch the window to the first window (:iss:`2604`)
+
+- macOS: Fix a regression that broke drag and drop (:iss:`2605`)
+
+- Report modifier key state when sending wheel events to the terminal program
+
+- Fix kitty @ send-text not working with text larger than 1024 bytes when using
+  :option:`kitty --listen-on` (:iss:`2607`)
+
+- Wayland: Fix OS window title not updating for hidden windows (:iss:`2629`)
+
+- Fix :opt:`background_tint` making the window semi-transparent (:iss:`2618`)
+
+
 0.17.3 [2020-04-23]
 --------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/docs/kittens/icat.rst 
new/kitty-0.17.4/docs/kittens/icat.rst
--- old/kitty-0.17.3/docs/kittens/icat.rst      2020-04-23 05:09:07.000000000 
+0200
+++ new/kitty-0.17.4/docs/kittens/icat.rst      2020-05-09 07:18:21.000000000 
+0200
@@ -21,6 +21,12 @@
     `ImageMagick <https://www.imagemagick.org>`_ must be installed for 
``icat`` to
     work.
 
+.. note::
+
+    kitty's image display protocol may not work when used within a terminal
+    multiplexer such as ``screen`` or ``tmux``, depending on whether the
+    multiplexer has added support for it or not.
+
 
 .. program:: kitty +kitten icat
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/glfw/cocoa_window.m 
new/kitty-0.17.4/glfw/cocoa_window.m
--- old/kitty-0.17.3/glfw/cocoa_window.m        2020-04-23 05:09:07.000000000 
+0200
+++ new/kitty-0.17.4/glfw/cocoa_window.m        2020-05-09 07:18:21.000000000 
+0200
@@ -1133,7 +1133,7 @@
             break;
     }
 
-    _glfwInputScroll(window, deltaX, deltaY, flags);
+    _glfwInputScroll(window, deltaX, deltaY, flags, translateFlags([event 
modifierFlags]));
 }
 
 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/glfw/glfw.py 
new/kitty-0.17.4/glfw/glfw.py
--- old/kitty-0.17.3/glfw/glfw.py       2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/glfw/glfw.py       2020-05-09 07:18:21.000000000 +0200
@@ -55,7 +55,7 @@
 
 def init_env(env: Env, pkg_config: Callable, at_least_version: Callable, 
test_compile: Callable, module: str = 'x11') -> Env:
     ans = env.copy()
-    ans.cflags.append('-fpic')
+    ans.cflags.append('-fPIC')
     ans.cppflags.append('-D_GLFW_' + module.upper())
     ans.cppflags.append('-D_GLFW_BUILD_DLL')
 
@@ -95,7 +95,7 @@
         for p in ans.wayland_protocols:
             ans.sources.append(wayland_protocol_file_name(p))
             ans.all_headers.append(wayland_protocol_file_name(p, 'h'))
-        for dep in 'wayland-egl wayland-client wayland-cursor xkbcommon 
dbus-1'.split():
+        for dep in 'wayland-client wayland-cursor xkbcommon dbus-1'.split():
             ans.cflags.extend(pkg_config(dep, '--cflags-only-I'))
             ans.ldpaths.extend(pkg_config(dep, '--libs'))
         has_memfd_create = test_compile(env.cc, '-Werror', src='''#define 
_GNU_SOURCE
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/glfw/glfw3.h 
new/kitty-0.17.4/glfw/glfw3.h
--- old/kitty-0.17.3/glfw/glfw3.h       2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/glfw/glfw3.h       2020-05-09 07:18:21.000000000 +0200
@@ -1550,6 +1550,7 @@
  *  value 2 for stationary momentum scrolling, value 3 for momentum scrolling
  *  in progress, value 4 for momentum scrolling ended, value 5 for momentum
  *  scrolling cancelled and value 6 if scrolling may begin soon.
+ *  @param[int] mods The keyboard modifiers
  *
  *  @sa @ref scrolling
  *  @sa @ref glfwSetScrollCallback
@@ -1559,7 +1560,7 @@
  *
  *  @ingroup input
  */
-typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
+typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int,int);
 
 /*! @brief The function pointer type for key callbacks.
  *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/glfw/input.c 
new/kitty-0.17.4/glfw/input.c
--- old/kitty-0.17.3/glfw/input.c       2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/glfw/input.c       2020-05-09 07:18:21.000000000 +0200
@@ -300,10 +300,10 @@
 
 // Notifies shared code of a scroll event
 //
-void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int 
flags)
+void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int 
flags, int mods)
 {
     if (window->callbacks.scroll)
-        window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset, 
flags);
+        window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset, 
flags, mods);
 }
 
 // Notifies shared code of a mouse button click event
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/glfw/internal.h 
new/kitty-0.17.4/glfw/internal.h
--- old/kitty-0.17.3/glfw/internal.h    2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/glfw/internal.h    2020-05-09 07:18:21.000000000 +0200
@@ -755,7 +755,7 @@
 
 void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int native_key, int 
action, int mods);
 void _glfwInputKeyboard(_GLFWwindow *window, GLFWkeyevent *ev);
-void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int 
flags);
+void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int 
flags, int mods);
 void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int 
mods);
 void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
 void _glfwInputCursorEnter(_GLFWwindow* window, bool entered);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/glfw/wl_init.c 
new/kitty-0.17.4/glfw/wl_init.c
--- old/kitty-0.17.3/glfw/wl_init.c     2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/glfw/wl_init.c     2020-05-09 07:18:21.000000000 +0200
@@ -334,7 +334,7 @@
     else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
         y = wl_fixed_to_double(value) * -1;
 
-    _glfwInputScroll(window, x, y, 1);
+    _glfwInputScroll(window, x, y, 1, _glfw.wl.xkb.states.modifiers);
 }
 
 static const struct wl_pointer_listener pointerListener = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/glfw/x11_init.c 
new/kitty-0.17.4/glfw/x11_init.c
--- old/kitty-0.17.3/glfw/x11_init.c    2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/glfw/x11_init.c    2020-05-09 07:18:21.000000000 +0200
@@ -502,8 +502,10 @@
 
 // X error handler
 //
-static int errorHandler(Display *display UNUSED, XErrorEvent* event)
+static int errorHandler(Display *display, XErrorEvent* event)
 {
+    if (_glfw.x11.display != display)
+        return 0;
     _glfw.x11.errorCode = event->error_code;
     return 0;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/glfw/x11_window.c 
new/kitty-0.17.4/glfw/x11_window.c
--- old/kitty-0.17.3/glfw/x11_window.c  2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/glfw/x11_window.c  2020-05-09 07:18:21.000000000 +0200
@@ -1265,13 +1265,13 @@
 
             // Modern X provides scroll events as mouse button presses
             else if (event->xbutton.button == Button4)
-                _glfwInputScroll(window, 0.0, 1.0, 0);
+                _glfwInputScroll(window, 0.0, 1.0, 0, mods);
             else if (event->xbutton.button == Button5)
-                _glfwInputScroll(window, 0.0, -1.0, 0);
+                _glfwInputScroll(window, 0.0, -1.0, 0, mods);
             else if (event->xbutton.button == Button6)
-                _glfwInputScroll(window, 1.0, 0.0, 0);
+                _glfwInputScroll(window, 1.0, 0.0, 0, mods);
             else if (event->xbutton.button == Button7)
-                _glfwInputScroll(window, -1.0, 0.0, 0);
+                _glfwInputScroll(window, -1.0, 0.0, 0, mods);
 
             else
             {
@@ -1408,12 +1408,18 @@
             if (!event->xany.send_event && window->x11.parent != 
_glfw.x11.root)
             {
                 Window dummy;
+                _glfwGrabErrorHandlerX11();
                 XTranslateCoordinates(_glfw.x11.display,
                                       window->x11.parent,
                                       _glfw.x11.root,
                                       xpos, ypos,
                                       &xpos, &ypos,
                                       &dummy);
+                _glfwReleaseErrorHandlerX11();
+                if (_glfw.x11.errorCode != Success) {
+                    _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to 
translate ConfigureNotiy co-ords for reparented window");
+                    return;
+                }
             }
 
             if (xpos != window->x11.xpos || ypos != window->x11.ypos)
@@ -1550,17 +1556,21 @@
                 const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff;
                 const int yabs = (event->xclient.data.l[2]) & 0xffff;
                 Window dummy;
-                int xpos, ypos;
+                int xpos = 0, ypos = 0;
 
                 if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
                     return;
 
+                _glfwGrabErrorHandlerX11();
                 XTranslateCoordinates(_glfw.x11.display,
                                       _glfw.x11.root,
                                       window->x11.handle,
                                       xabs, yabs,
                                       &xpos, &ypos,
                                       &dummy);
+                _glfwReleaseErrorHandlerX11();
+                if (_glfw.x11.errorCode != Success)
+                    _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to get 
DND event position");
 
                 _glfwInputCursorPos(window, xpos, ypos);
 
@@ -1988,10 +1998,14 @@
 void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
 {
     Window dummy;
-    int x, y;
+    int x = 0, y = 0;
 
+    _glfwGrabErrorHandlerX11();
     XTranslateCoordinates(_glfw.x11.display, window->x11.handle, 
_glfw.x11.root,
                           0, 0, &x, &y, &dummy);
+    _glfwReleaseErrorHandlerX11();
+    if (_glfw.x11.errorCode != Success)
+        _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to get window 
position");
 
     if (xpos)
         *xpos = x;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/boss.py 
new/kitty-0.17.4/kitty/boss.py
--- old/kitty-0.17.3/kitty/boss.py      2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/boss.py      2020-05-09 07:18:21.000000000 +0200
@@ -336,7 +336,13 @@
                 if not getattr(err, 'hide_traceback', False):
                     response['tb'] = traceback.format_exc()
         else:
-            response = {'ok': False, 'error': 'Remote control is disabled. Add 
allow_remote_control to your kitty.conf'}
+            no_response = False
+            try:
+                no_response = json.loads(cmd).get('no_response')
+            except Exception:
+                pass
+            if not no_response:
+                response = {'ok': False, 'error': 'Remote control is disabled. 
Add allow_remote_control to your kitty.conf'}
         return response
 
     def remote_control(self, *args: str) -> None:
@@ -355,15 +361,16 @@
             self.show_error(_('remote_control mapping failed'), str(e))
 
     def peer_message_received(self, msg_bytes: bytes) -> Optional[bytes]:
-        msg = msg_bytes.decode('utf-8')
-        cmd_prefix = '\x1bP@kitty-cmd'
-        if msg.startswith(cmd_prefix):
-            cmd = msg[len(cmd_prefix):-2]
+        cmd_prefix = b'\x1bP@kitty-cmd'
+        terminator = b'\x1b\\'
+        if msg_bytes.startswith(cmd_prefix) and msg_bytes.endswith(terminator):
+            cmd = msg_bytes[len(cmd_prefix):-len(terminator)].decode('utf-8')
             response = self._handle_remote_command(cmd, from_peer=True)
             if response is None:
                 return None
-            return (cmd_prefix + json.dumps(response) + 
'\x1b\\').encode('utf-8')
-        data = json.loads(msg)
+            return cmd_prefix + json.dumps(response).encode('utf-8') + 
terminator
+
+        data = json.loads(msg_bytes.decode('utf-8'))
         if isinstance(data, dict) and data.get('cmd') == 'new_instance':
             from .cli_stub import CLIOptions
             startup_id = data.get('startup_id')
@@ -717,6 +724,9 @@
                     text = '\n'.join(parse_uri_list(text))
                 w.paste(text)
 
+    def confirm_os_window_close(self, os_window_id: int) -> None:
+        mark_os_window_for_close(os_window_id)
+
     def on_os_window_closed(self, os_window_id: int, viewport_width: int, 
viewport_height: int) -> None:
         self.cached_values['window-size'] = viewport_width, viewport_height
         tm = self.os_window_map.pop(os_window_id, None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/child-monitor.c 
new/kitty-0.17.4/kitty/child-monitor.c
--- old/kitty-0.17.3/kitty/child-monitor.c      2020-04-23 05:09:07.000000000 
+0200
+++ new/kitty-0.17.4/kitty/child-monitor.c      2020-05-09 07:18:21.000000000 
+0200
@@ -524,17 +524,6 @@
 }
 
 static inline bool
-update_window_title(Window *w, OSWindow *os_window) {
-    if (w->title && w->title != os_window->window_title) {
-        os_window->window_title = w->title;
-        Py_INCREF(os_window->window_title);
-        set_os_window_title(os_window, PyUnicode_AsUTF8(w->title));
-        return true;
-    }
-    return false;
-}
-
-static inline bool
 prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int 
*active_window_id, color_type *active_window_bg, unsigned int 
*num_visible_windows, bool *all_windows_have_same_bg) {
 #define TD os_window->tab_bar_render_data
     bool needs_render = os_window->needs_render;
@@ -577,7 +566,7 @@
                 *active_window_id = w->id;
                 collect_cursor_info(&WD.screen->cursor_render_info, w, now, 
os_window);
                 if (w->cursor_visible_at_last_render != 
WD.screen->cursor_render_info.is_visible || w->last_cursor_x != 
WD.screen->cursor_render_info.x || w->last_cursor_y != 
WD.screen->cursor_render_info.y || w->last_cursor_shape != 
WD.screen->cursor_render_info.shape) needs_render = true;
-                update_window_title(w, os_window);
+                set_os_window_title_from_window(w, os_window);
                 *active_window_bg = window_bg;
             } else WD.screen->cursor_render_info.is_visible = false;
             if (send_cell_data_to_gpu(WD.vao_idx, WD.gvao_idx, WD.xstart, 
WD.ystart, WD.dx, WD.dy, WD.screen, os_window)) needs_render = true;
@@ -625,15 +614,6 @@
 #undef TD
 }
 
-static inline void
-update_os_window_title(OSWindow *os_window) {
-    Tab *tab = os_window->tabs + os_window->active_tab;
-    if (tab->num_windows) {
-        Window *w = tab->windows + tab->active_window;
-        update_window_title(w, os_window);
-    }
-}
-
 static void
 draw_resizing_text(OSWindow *w) {
     char text[32] = {0};
@@ -865,25 +845,42 @@
 
 static inline void
 close_all_windows(void) {
-    for (size_t w = 0; w < global_state.num_os_windows; w++) 
mark_os_window_for_close(&global_state.os_windows[w], true);
+    for (size_t w = 0; w < global_state.num_os_windows; w++) 
mark_os_window_for_close(&global_state.os_windows[w], 
IMPERATIVE_CLOSE_REQUESTED);
+}
+
+static inline void
+close_os_window(ChildMonitor *self, OSWindow *os_window) {
+    destroy_os_window(os_window);
+    call_boss(on_os_window_closed, "Kii", os_window->id, 
os_window->window_width, os_window->window_height);
+    for (size_t t=0; t < os_window->num_tabs; t++) {
+        Tab *tab = os_window->tabs + t;
+        for (size_t w = 0; w < tab->num_windows; w++) 
mark_child_for_close(self, tab->windows[w].id);
+    }
+    remove_os_window(os_window->id);
 }
 
 static inline bool
 process_pending_closes(ChildMonitor *self) {
-    global_state.has_pending_closes = false;
     bool has_open_windows = false;
     for (size_t w = global_state.num_os_windows; w > 0; w--) {
         OSWindow *os_window = global_state.os_windows + w - 1;
-        if (should_os_window_close(os_window)) {
-            destroy_os_window(os_window);
-            call_boss(on_os_window_closed, "Kii", os_window->id, 
os_window->window_width, os_window->window_height);
-            for (size_t t=0; t < os_window->num_tabs; t++) {
-                Tab *tab = os_window->tabs + t;
-                for (size_t w = 0; w < tab->num_windows; w++) 
mark_child_for_close(self, tab->windows[w].id);
-            }
-            remove_os_window(os_window->id);
-        } else has_open_windows = true;
+        switch(os_window->close_request) {
+            case NO_CLOSE_REQUESTED:
+                has_open_windows = true;
+                break;
+            case CONFIRMABLE_CLOSE_REQUESTED:
+                os_window->close_request = NO_CLOSE_REQUESTED;
+                call_boss(confirm_os_window_close, "K", os_window->id);
+                if (os_window->close_request == IMPERATIVE_CLOSE_REQUESTED) {
+                    close_os_window(self, os_window);
+                } else has_open_windows = true;
+                break;
+            case IMPERATIVE_CLOSE_REQUESTED:
+                close_os_window(self, os_window);
+                break;
+        }
     }
+    global_state.has_pending_closes = false;
 #ifdef __APPLE__
     if (!OPT(macos_quit_when_last_window_closed)) {
         if (!has_open_windows && !application_quit_requested()) 
has_open_windows = true;
@@ -1279,7 +1276,7 @@
     char *data;
     size_t capacity, used;
     int fd;
-    bool finished, close_socket;
+    bool finished, close_socket, is_peer_command;
 } PeerReadData;
 static PeerReadData empty_prd = {.fd = -1, 0};
 
@@ -1329,6 +1326,41 @@
     return true;
 }
 
+#define KITTY_CMD_PREFIX "\x1bP@kitty-cmd{"
+
+static inline void
+queue_peer_message(ChildMonitor *self, char *buf, size_t sz, int fd) {
+    children_mutex(lock);
+    ensure_space_for(self, messages, Message, self->messages_count + 1, 
messages_capacity, 16, true);
+    Message *m = self->messages + self->messages_count++;
+    m->data = buf; m->sz = sz; m->fd = fd;
+    children_mutex(unlock);
+    wakeup_main_loop();
+}
+
+static inline void
+dispatch_peer_command(ChildMonitor *self, PeerReadData *rd, int fd) {
+    size_t end = 0;
+    for (size_t i = 0; i < rd->used - 1; i++) {
+        if (rd->data[i] == 0x1b && rd->data[i+1] == '\\') {
+            end = i + 2;
+            break;
+        }
+    }
+    if (!end) return;
+    char *buf = malloc(end + 8);
+    if (buf) {
+        memcpy(buf, rd->data, end);
+        queue_peer_message(self, buf, end, fd);
+    }
+    rd->is_peer_command = false;
+    if (rd->used > end) {
+        rd->used -= end;
+        memmove(rd->data, rd->data + end, rd->used);
+        if (rd->used >= sizeof(KITTY_CMD_PREFIX) - 1 && memcmp(rd->data, 
KITTY_CMD_PREFIX, sizeof(KITTY_CMD_PREFIX)-1) == 0) rd->is_peer_command = true;
+    } else rd->used = 0;
+}
+
 static inline bool
 read_from_peer(ChildMonitor *self, int s) {
     bool read_finished = false;
@@ -1337,26 +1369,28 @@
 #define failed(msg) { read_finished = true; log_error("%s", msg); rd->finished 
= true; rd->close_socket = true; break; }
         if (rd->fd == s) {
             if (rd->used >= rd->capacity) {
-                if (rd->capacity >= 1024 * 1024) failed("Ignoring too large 
message from peer");
+                if (rd->capacity >= 64 * 1024) failed("Ignoring too large 
message from peer");
                 rd->capacity = MAX(8192u, rd->capacity * 2);
                 rd->data = realloc(rd->data, rd->capacity);
                 if (!rd->data) failed("Out of memory");
             }
             ssize_t n = recv(s, rd->data + rd->used, rd->capacity - rd->used, 
0);
             if (n == 0) {
+                while (rd->is_peer_command) dispatch_peer_command(self, rd, s);
                 read_finished = true; rd->finished = true;
-                children_mutex(lock);
-                ensure_space_for(self, messages, Message, self->messages_count 
+ 1, messages_capacity, 16, true);
-                Message *m = self->messages + self->messages_count++;
-                m->data = rd->data; rd->data = NULL; m->sz = rd->used; m->fd = 
s;
-                children_mutex(unlock);
-                wakeup_main_loop();
+                if (rd->used) queue_peer_message(self, rd->data, rd->used, s);
+                else free(rd->data);
+                rd->data = NULL;
             } else if (n < 0) {
                 if (errno != EINTR) {
                     perror("Error reading from talk peer");
                     failed("");
                 }
-            } else rd->used += n;
+            } else {
+                if (!rd->used && memcmp(rd->data, KITTY_CMD_PREFIX, 
sizeof(KITTY_CMD_PREFIX)-1) == 0) rd->is_peer_command = true;
+                rd->used += n;
+                while (rd->is_peer_command) dispatch_peer_command(self, rd, s);
+            }
             break;
         }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/cli.py 
new/kitty-0.17.4/kitty/cli.py
--- old/kitty-0.17.3/kitty/cli.py       2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/cli.py       2020-05-09 07:18:21.000000000 +0200
@@ -409,7 +409,10 @@
         elif otype == 'list':
             t = 'typing.Sequence[str]'
         elif otype in ('choice', 'choices'):
-            t = 'str'
+            if opt['choices']:
+                t = 'typing.Literal[{}]'.format(','.join(f'{x!r}' for x in 
opt['choices']))
+            else:
+                t = 'str'
         elif otype.startswith('bool-'):
             t = 'bool'
         else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/conf/definition.py 
new/kitty-0.17.4/kitty/conf/definition.py
--- old/kitty-0.17.3/kitty/conf/definition.py   2020-04-23 05:09:07.000000000 
+0200
+++ new/kitty-0.17.4/kitty/conf/definition.py   2020-05-09 07:18:21.000000000 
+0200
@@ -9,7 +9,7 @@
     Set, Tuple, Union, get_type_hints
 )
 
-from .utils import to_bool
+from .utils import Choice, to_bool
 
 
 def to_string(x: str) -> str:
@@ -56,6 +56,8 @@
 
         if type(self.option_type) is type:
             return type_name(self.option_type)
+        if isinstance(self.option_type, Choice):
+            return 'typing.Literal[{}]'.format(','.join(f'{x!r}' for x in 
self.option_type.all_choices))
         th = get_type_hints(self.option_type)
         try:
             rettype = th['return']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/conf/utils.py 
new/kitty-0.17.4/kitty/conf/utils.py
--- old/kitty-0.17.3/kitty/conf/utils.py        2020-04-23 05:09:07.000000000 
+0200
+++ new/kitty-0.17.4/kitty/conf/utils.py        2020-05-09 07:18:21.000000000 
+0200
@@ -68,17 +68,21 @@
     return ans
 
 
-def choices(*choices: str) -> Callable[[str], str]:
-    defval = choices[0]
-    uc = frozenset(choices)
+class Choice:
 
-    def choice(x: str) -> str:
+    def __init__(self, choices: Sequence[str]):
+        self.defval = choices[0]
+        self.all_choices = frozenset(choices)
+
+    def __call__(self, x: str) -> str:
         x = x.lower()
-        if x not in uc:
-            x = defval
+        if x not in self.all_choices:
+            x = self.defval
         return x
 
-    return choice
+
+def choices(*choices: str) -> Choice:
+    return Choice(choices)
 
 
 def parse_line(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/config.py 
new/kitty-0.17.4/kitty/config.py
--- old/kitty-0.17.3/kitty/config.py    2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/config.py    2020-05-09 07:18:21.000000000 +0200
@@ -9,8 +9,8 @@
 from contextlib import contextmanager, suppress
 from functools import partial
 from typing import (
-    Any, Callable, Dict, Generator, Iterable, List, Match, NamedTuple,
-    Optional, Sequence, Set, Tuple, Type, Union
+    Any, Callable, Dict, Generator, Iterable, List, NamedTuple, Optional,
+    Sequence, Set, Tuple, Type, Union
 )
 
 from . import fast_data_types as defines
@@ -24,7 +24,7 @@
 from .key_names import get_key_name_lookup, key_name_aliases
 from .options_stub import Options as OptionsStub
 from .typing import EdgeLiteral, TypedDict
-from .utils import log_error
+from .utils import expandvars, log_error
 
 KeySpec = Tuple[int, bool, int]
 KeyMap = Dict[KeySpec, 'KeyAction']
@@ -585,20 +585,6 @@
     ans['macos_show_window_title_in'] = macos_show_window_title_in
 
 
-def expandvars(val: str, env: Dict[str, str] = {}) -> str:
-
-    def sub(m: Match) -> str:
-        key = m.group(1)
-        result = env.get(key)
-        if result is None:
-            result = os.environ.get(key)
-        if result is None:
-            result = m.group()
-        return result
-
-    return re.sub(r'\$\{(\S+?)\}', sub, val)
-
-
 @special_handler
 def handle_env(key: str, val: str, ans: Dict[str, Any]) -> None:
     key, val = val.partition('=')[::2]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/config_data.py 
new/kitty-0.17.4/kitty/config_data.py
--- old/kitty-0.17.3/kitty/config_data.py       2020-04-23 05:09:07.000000000 
+0200
+++ new/kitty-0.17.4/kitty/config_data.py       2020-05-09 07:18:21.000000000 
+0200
@@ -548,7 +548,7 @@
 o('terminal_select_modifiers', 'shift', option_type=to_modifiers, 
long_text=_('''
 The modifiers to override mouse selection even when a terminal application has 
grabbed the mouse'''))
 
-o('select_by_word_characters', ':@-./_~?&=%+#', long_text=_('''
+o('select_by_word_characters', '@-./_~?&=%+#', long_text=_('''
 Characters considered part of a word when double clicking. In addition to 
these characters
 any character that is marked as an alphanumeric character in the unicode
 database will be matched.'''))
@@ -870,6 +870,11 @@
 the title. If you wish to include the tab-index as well,
 use something like: :code:`{index}: {title}`. Useful
 if you have shortcuts mapped for :code:`goto_tab N`.
+In addition you can use :code:`{layout_name}` for the current
+layout name and :code:`{num_windows}` for the number of windows
+in the tab. Note that formatting is done by Python's string formatting
+machinery, so you can use, for instance, :code:`{layout_name[:2].upper()}` to
+show only the first two letters of the layout name, upper-cased.
 '''))
 o('active_tab_title_template', 'none', option_type=active_tab_title_template, 
long_text=_('''
 Template to use for active tabs, if not specified falls back
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/constants.py 
new/kitty-0.17.4/kitty/constants.py
--- old/kitty-0.17.3/kitty/constants.py 2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/constants.py 2020-05-09 07:18:21.000000000 +0200
@@ -20,7 +20,7 @@
 
 
 appname: str = 'kitty'
-version: Version = Version(0, 17, 3)
+version: Version = Version(0, 17, 4)
 str_version: str = '.'.join(map(str, version))
 _plat = sys.platform.lower()
 is_macos: bool = 'darwin' in _plat
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/core_text.m 
new/kitty-0.17.4/kitty/core_text.m
--- old/kitty-0.17.3/kitty/core_text.m  2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/core_text.m  2020-05-09 07:18:21.000000000 +0200
@@ -506,8 +506,10 @@
         render_alpha_mask(render_buf, canvas, &src, &dest, canvas_width, 
canvas_width);
     }
     if (num_cells && (center_glyph || (num_cells == 2 && *was_colored))) {
-        // center glyphs (two cell emoji and PUA glyphs)
-        CGFloat delta = (((CGFloat)canvas_width - br.size.width) / 2.f) - 
br.origin.x;
+        // center glyphs (two cell emoji, PUA glyphs, ligatures, etc)
+        CGFloat delta = (((CGFloat)canvas_width - br.size.width) / 2.f);
+        // FiraCode ligatures result in negative origins
+        if (br.origin.x > 0) delta -= br.origin.x;
         if (delta >= 1.f) right_shift_canvas(canvas, canvas_width, 
cell_height, (unsigned)(delta));
     }
     return true;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/data-types.h 
new/kitty-0.17.4/kitty/data-types.h
--- old/kitty-0.17.3/kitty/data-types.h 2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/data-types.h 2020-05-09 07:18:21.000000000 +0200
@@ -313,7 +313,7 @@
 void enter_event(void);
 void mouse_event(int, int, int);
 void focus_in_event(void);
-void scroll_event(double, double, int);
+void scroll_event(double, double, int, int);
 void fake_scroll(int, bool);
 void set_special_key_combo(int glfw_key, int mods, bool is_native);
 void on_key_input(GLFWkeyevent *ev);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/desktop.c 
new/kitty-0.17.4/kitty/desktop.c
--- old/kitty-0.17.3/kitty/desktop.c    2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/desktop.c    2020-05-09 07:18:21.000000000 +0200
@@ -30,18 +30,22 @@
 static PyObject*
 init_x11_startup_notification(PyObject UNUSED *self, PyObject *args) {
     static bool done = false;
-    static const char* libname = "libstartup-notification-1.so";
-    // some installs are missing the .so symlink, so try the full name
-    static const char* libname2 = "libstartup-notification-1.so.0";
-    static const char* libname3 = "libstartup-notification-1.so.0.0.0";
     if (!done) {
         done = true;
 
-        libsn_handle = dlopen(libname, RTLD_LAZY);
-        if (libsn_handle == NULL) libsn_handle = dlopen(libname2, RTLD_LAZY);
-        if (libsn_handle == NULL) libsn_handle = dlopen(libname3, RTLD_LAZY);
+        const char* libnames[] = {
+            "libstartup-notification-1.so",
+            // some installs are missing the .so symlink, so try the full name
+            "libstartup-notification-1.so.0",
+            "libstartup-notification-1.so.0.0.0",
+            NULL
+        };
+        for (int i = 0; libnames[i]; i++) {
+            libsn_handle = dlopen(libnames[i], RTLD_LAZY);
+            if (libsn_handle) break;
+        }
         if (libsn_handle == NULL) {
-            PyErr_Format(PyExc_OSError, "Failed to load %s with error: %s", 
libname, dlerror());
+            PyErr_Format(PyExc_OSError, "Failed to load %s with error: %s", 
libnames[0], dlerror());
             return NULL;
         }
         dlerror();    /* Clear any existing error */
@@ -105,18 +109,22 @@
 
 static void
 load_libcanberra(void) {
-    static const char* libname = "libcanberra.so";
-    // some installs are missing the .so symlink, so try the full name
-    static const char* libname2 = "libcanberra.so.0";
-    static const char* libname3 = "libcanberra.so.0.2.5";
     static bool done = false;
     if (done) return;
     done = true;
-    libcanberra_handle = dlopen(libname, RTLD_LAZY);
-    if (libcanberra_handle == NULL) libcanberra_handle = dlopen(libname2, 
RTLD_LAZY);
-    if (libcanberra_handle == NULL) libcanberra_handle = dlopen(libname3, 
RTLD_LAZY);
+    const char* libnames[] = {
+        "libcanberra.so",
+        // some installs are missing the .so symlink, so try the full name
+        "libcanberra.so.0",
+        "libcanberra.so.0.2.5",
+        NULL
+    };
+    for (int i = 0; libnames[i]; i++) {
+        libcanberra_handle = dlopen(libnames[i], RTLD_LAZY);
+        if (libcanberra_handle) break;
+    }
     if (libcanberra_handle == NULL) {
-        fprintf(stderr, "Failed to load %s, cannot play beep sound, with 
error: %s\n", libname, dlerror());
+        fprintf(stderr, "Failed to load %s, cannot play beep sound, with 
error: %s\n", libnames[0], dlerror());
         return;
     }
     load_libcanberra_functions();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/fast_data_types.pyi 
new/kitty-0.17.4/kitty/fast_data_types.pyi
--- old/kitty-0.17.3/kitty/fast_data_types.pyi  2020-04-23 05:09:07.000000000 
+0200
+++ new/kitty-0.17.4/kitty/fast_data_types.pyi  2020-05-09 07:18:21.000000000 
+0200
@@ -550,6 +550,10 @@
     pass
 
 
+def sync_os_window_title(os_window_id: int) -> None:
+    pass
+
+
 def set_options(
     opts: Options,
     is_wayland: bool = False,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/fonts.c 
new/kitty-0.17.4/kitty/fonts.c
--- old/kitty-0.17.3/kitty/fonts.c      2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/fonts.c      2020-05-09 07:18:21.000000000 +0200
@@ -1004,14 +1004,20 @@
     G(groups)->is_space_ligature = true;
 }
 
+static inline bool
+is_group_calt_ligature(const Group *group) {
+    GPUCell *first_cell = G(first_gpu_cell) + group->first_cell_idx;
+    return group->num_cells > 1 && group->has_special_glyph && 
(first_cell->attrs & WIDTH_MASK) == 1;
+}
+
+
 static inline void
 split_run_at_offset(index_type cursor_offset, index_type *left, index_type 
*right) {
     *left = 0; *right = 0;
     for (unsigned idx = 0; idx < G(group_idx) + 1; idx++) {
         Group *group = G(groups) + idx;
         if (group->first_cell_idx <= cursor_offset && cursor_offset < 
group->first_cell_idx + group->num_cells) {
-            GPUCell *first_cell = G(first_gpu_cell) + group->first_cell_idx;
-            if (group->num_cells > 1 && group->has_special_glyph && 
(first_cell->attrs & WIDTH_MASK) == 1) {
+            if (is_group_calt_ligature(group)) {
                 // likely a calt ligature
                 *left = group->first_cell_idx; *right = group->first_cell_idx 
+ group->num_cells;
             }
@@ -1039,6 +1045,11 @@
         // there exist stupid fonts like Powerline that have no space glyph,
         // so special case it: https://github.com/kovidgoyal/kitty/issues/1225
         unsigned int num_glyphs = group->is_space_ligature ? 1 : 
group->num_glyphs;
+#ifdef __APPLE__
+        // FiraCode ligatures need to be centered on macOS
+        // see https://github.com/kovidgoyal/kitty/issues/2591
+        if (is_group_calt_ligature(group)) center_glyph = true;
+#endif
         render_group(fg, group->num_cells, num_glyphs, G(first_cpu_cell) + 
group->first_cell_idx, G(first_gpu_cell) + group->first_cell_idx, G(info) + 
group->first_glyph_idx, G(positions) + group->first_glyph_idx, font, primary, 
&ed, center_glyph);
         idx++;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/glfw-wrapper.h 
new/kitty-0.17.4/kitty/glfw-wrapper.h
--- old/kitty-0.17.3/kitty/glfw-wrapper.h       2020-04-23 05:09:07.000000000 
+0200
+++ new/kitty-0.17.4/kitty/glfw-wrapper.h       2020-05-09 07:18:21.000000000 
+0200
@@ -1313,6 +1313,7 @@
  *  value 2 for stationary momentum scrolling, value 3 for momentum scrolling
  *  in progress, value 4 for momentum scrolling ended, value 5 for momentum
  *  scrolling cancelled and value 6 if scrolling may begin soon.
+ *  @param[int] mods The keyboard modifiers
  *
  *  @sa @ref scrolling
  *  @sa @ref glfwSetScrollCallback
@@ -1322,7 +1323,7 @@
  *
  *  @ingroup input
  */
-typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
+typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int,int);
 
 /*! @brief The function pointer type for key callbacks.
  *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/glfw.c 
new/kitty-0.17.4/kitty/glfw.c
--- old/kitty-0.17.3/kitty/glfw.c       2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/glfw.c       2020-05-09 07:18:21.000000000 +0200
@@ -153,6 +153,10 @@
 window_close_callback(GLFWwindow* window) {
     if (!set_callback_window(window)) return;
     global_state.has_pending_closes = true;
+    if (global_state.callback_os_window->close_request < 
CONFIRMABLE_CLOSE_REQUESTED) {
+        global_state.callback_os_window->close_request = 
CONFIRMABLE_CLOSE_REQUESTED;
+    }
+    glfwSetWindowShouldClose(window, false);
     request_tick_callback();
     global_state.callback_os_window = NULL;
 }
@@ -287,12 +291,12 @@
 }
 
 static void
-scroll_callback(GLFWwindow *w, double xoffset, double yoffset, int flags) {
+scroll_callback(GLFWwindow *w, double xoffset, double yoffset, int flags, int 
mods) {
     if (!set_callback_window(w)) return;
     show_mouse_cursor(w);
     monotonic_t now = monotonic();
     global_state.callback_os_window->last_mouse_activity_at = now;
-    if (is_window_ready_for_callbacks()) scroll_event(xoffset, yoffset, flags);
+    if (is_window_ready_for_callbacks()) scroll_event(xoffset, yoffset, flags, 
mods);
     request_tick_callback();
     global_state.callback_os_window = NULL;
 }
@@ -323,23 +327,17 @@
 static int
 drop_callback(GLFWwindow *w, const char *mime, const char *data, size_t sz) {
     if (!set_callback_window(w)) return 0;
+#define RETURN(x) { global_state.callback_os_window = NULL; return x; }
     if (!data) {
-        if (strcmp(mime, "text/uri-list") == 0) return 3;
-        if (strcmp(mime, "text/plain;charset=utf-8") == 0) return 2;
-        if (strcmp(mime, "text/plain") == 0) return 1;
-        return 0;
-    }
-    WINDOW_CALLBACK(on_drop, "sy#", mime, data, (int)sz);
-    request_tick_callback();
-    /* PyObject *s = PyTuple_New(count); */
-    /* if (s) { */
-    /*     for (int i = 0; i < count; i++) PyTuple_SET_ITEM(s, i, 
PyUnicode_FromString(strings[i])); */
-    /*     WINDOW_CALLBACK(on_drop, "O", s); */
-    /*     Py_CLEAR(s); */
-    /*     request_tick_callback(); */
-    /* } */
-    global_state.callback_os_window = NULL;
-    return 0;
+        if (strcmp(mime, "text/uri-list") == 0) RETURN(3);
+        if (strcmp(mime, "text/plain;charset=utf-8") == 0) RETURN(2);
+        if (strcmp(mime, "text/plain") == 0) RETURN(1);
+        RETURN(0);
+    }
+    WINDOW_CALLBACK(on_drop, "sy#", mime, data, (Py_ssize_t)sz);
+    request_tick_callback();
+    RETURN(0);
+#undef RETURN
 }
 
 // }}}
@@ -979,12 +977,6 @@
     glfwPostEmptyEvent();
 }
 
-void
-mark_os_window_for_close(OSWindow* w, bool yes) {
-    global_state.has_pending_closes = true;
-    glfwSetWindowShouldClose(w->handle, yes);
-}
-
 bool
 should_os_window_be_rendered(OSWindow* w) {
     return (
@@ -994,11 +986,6 @@
        ) ? false : true;
 }
 
-bool
-should_os_window_close(OSWindow* w) {
-    return glfwWindowShouldClose(w->handle) ? true : false;
-}
-
 static PyObject*
 primary_monitor_size(PYNOARG) {
     GLFWmonitor* monitor = glfwGetPrimaryMonitor();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/graphics.c 
new/kitty-0.17.4/kitty/graphics.c
--- old/kitty-0.17.3/kitty/graphics.c   2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/graphics.c   2020-05-09 07:18:21.000000000 +0200
@@ -939,7 +939,7 @@
 };
 
 static PyMemberDef members[] = {
-    {"image_count", T_UINT, offsetof(GraphicsManager, image_count), 0, 
"image_count"},
+    {"image_count", T_PYSSIZET, offsetof(GraphicsManager, image_count), 0, 
"image_count"},
     {NULL},
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/launch.py 
new/kitty-0.17.4/kitty/launch.py
--- old/kitty-0.17.3/kitty/launch.py    2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/launch.py    2020-05-09 07:18:21.000000000 +0200
@@ -42,7 +42,7 @@
 Where to launch the child process, in a new kitty window in the current tab,
 a new tab, or a new OS window or an overlay over the current window.
 Note that if the current window already has an overlay, then it will
-open a new window. The value of none means the process will be
+open a new window. The value of background means the process will be
 run in the background. The values clipboard and primary are meant
 to work with :option:`launch --stdin-source` to copy data to the system
 clipboard or primary selection.
@@ -275,8 +275,8 @@
         kw['cmd'] = final_cmd
     if opts.type == 'overlay' and active and not active.overlay_window_id:
         kw['overlay_for'] = active.id
-    if opts.stdin_source and opts.stdin_source != 'none':
-        q = opts.stdin_source
+    if opts.stdin_source != 'none':
+        q = str(opts.stdin_source)
         if opts.stdin_add_formatting:
             if q in ('@screen', '@screen_scrollback', '@alternate', 
'@alternate_scrollback'):
                 q = '@ansi_' + q[1:]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/main.py 
new/kitty-0.17.4/kitty/main.py
--- old/kitty-0.17.3/kitty/main.py      2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/main.py      2020-05-09 07:18:21.000000000 +0200
@@ -7,7 +7,7 @@
 import shutil
 import sys
 from contextlib import contextmanager, suppress
-from typing import Generator, List, Mapping, Optional, Tuple, Sequence
+from typing import Generator, List, Mapping, Optional, Sequence, Tuple
 
 from .borders import load_borders_program
 from .boss import Boss
@@ -15,7 +15,7 @@
 from .cli import create_opts, parse_args
 from .cli_stub import CLIOptions
 from .conf.utils import BadLine
-from .config import cached_values_for, initial_window_size_func, expandvars
+from .config import cached_values_for, initial_window_size_func
 from .constants import (
     appname, beam_cursor_data_file, config_dir, glfw_path, is_macos,
     is_wayland, kitty_exe, logo_data_file, running_in_kitty
@@ -29,7 +29,7 @@
 from .fonts.render import set_font_family
 from .options_stub import Options as OptionsStub
 from .utils import (
-    detach, log_error, read_shell_environment, single_instance,
+    detach, expandvars, log_error, read_shell_environment, single_instance,
     startup_notification_handler, unix_socket_paths
 )
 from .window import load_shader_programs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/mouse.c 
new/kitty-0.17.4/kitty/mouse.c
--- old/kitty-0.17.3/kitty/mouse.c      2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/mouse.c      2020-05-09 07:18:21.000000000 +0200
@@ -514,7 +514,8 @@
         Tab *t = global_state.callback_os_window->tabs + 
global_state.callback_os_window->active_tab;
         for (unsigned int i = 0; i < t->num_windows; i++) {
             if (contains_mouse(t->windows + i) && 
t->windows[i].render_data.screen) {
-                *window_idx = i; return t->windows + i;
+                *window_idx = i;
+                return t->windows + i;
             }
         }
     }
@@ -529,8 +530,10 @@
         Tab *t = global_state.callback_os_window->tabs + 
global_state.callback_os_window->active_tab;
         for (unsigned int i = 0; i < t->num_windows; i++) {
             Window *w = t->windows + i;
-            double d = distance_to_window(w);
-            if (d < closest_distance) { ans = w; closest_distance = d; 
*window_idx = i; }
+            if (w->visible) {
+                double d = distance_to_window(w);
+                if (d < closest_distance) { ans = w; closest_distance = d; 
*window_idx = i; }
+            }
         }
     }
     return ans;
@@ -610,7 +613,7 @@
 }
 
 void
-scroll_event(double UNUSED xoffset, double yoffset, int flags) {
+scroll_event(double UNUSED xoffset, double yoffset, int flags, int modifiers) {
     bool in_tab_bar;
     static id_type window_for_momentum_scroll = 0;
     static bool main_screen_for_momentum_scroll = false;
@@ -687,7 +690,7 @@
         screen_history_scroll(screen, abs(s), upwards);
     } else {
         if (screen->modes.mouse_tracking_mode) {
-            int sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : 
GLFW_MOUSE_BUTTON_5, PRESS, 0);
+            int sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : 
GLFW_MOUSE_BUTTON_5, PRESS, modifiers);
             if (sz > 0) {
                 mouse_event_buf[sz] = 0;
                 for (s = abs(s); s > 0; s--) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/shaders.c 
new/kitty-0.17.4/kitty/shaders.c
--- old/kitty-0.17.3/kitty/shaders.c    2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/shaders.c    2020-05-09 07:18:21.000000000 +0200
@@ -465,7 +465,11 @@
         bind_program(CELL_BG_PROGRAM);
         
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) draw_tint(false, screen, xstart, 
ystart, width, height);
+    } else if (OPT(background_tint) > 0) {
+        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, 
GL_ONE);
+        draw_tint(false, screen, xstart, ystart, width, height);
+        BLEND_ONTO_OPAQUE;
+    }
 
     if (screen->grman->num_of_below_refs || has_bgimage(w)) {
         if (screen->grman->num_of_below_refs) draw_graphics(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/state.c 
new/kitty-0.17.4/kitty/state.c
--- old/kitty-0.17.3/kitty/state.c      2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/state.c      2020-05-09 07:18:21.000000000 +0200
@@ -43,8 +43,9 @@
                 if (osw->tabs[t].id == tab_id) { \
                     Tab *tab = osw->tabs + t; \
                     for (size_t w = 0; w < tab->num_windows; w++) { \
-                        Window *window = tab->windows + w;
-#define END_WITH_WINDOW break; }}}}}
+                        if (tab->windows[w].id == window_id) { \
+                            Window *window = tab->windows + w;
+#define END_WITH_WINDOW window_found = 1; break; }}}}}}
 
 
 #define WITH_OS_WINDOW_REFS \
@@ -213,6 +214,27 @@
     END_WITH_TAB;
 }
 
+void
+set_os_window_title_from_window(Window *w, OSWindow *os_window) {
+    if (w->title && w->title != os_window->window_title) {
+        Py_XDECREF(os_window->window_title);
+        os_window->window_title = w->title;
+        Py_INCREF(os_window->window_title);
+        set_os_window_title(os_window, PyUnicode_AsUTF8(w->title));
+    }
+}
+
+void
+update_os_window_title(OSWindow *os_window) {
+    if (os_window->num_tabs) {
+        Tab *tab = os_window->tabs + os_window->active_tab;
+        if (tab->num_windows) {
+            Window *w = tab->windows + tab->active_window;
+            set_os_window_title_from_window(w, os_window);
+        }
+    }
+}
+
 static inline void
 destroy_window(Window *w) {
     Py_CLEAR(w->render_data.screen); Py_CLEAR(w->title);
@@ -422,6 +444,14 @@
     }
 }
 
+void
+mark_os_window_for_close(OSWindow* w, CloseRequest cr) {
+    global_state.has_pending_closes = true;
+    w->close_request = cr;
+}
+
+
+
 
 // Python API {{{
 #define PYWRAP0(name) static PyObject* py##name(PYNOARG)
@@ -783,10 +813,10 @@
 
 PYWRAP1(mark_os_window_for_close) {
     id_type os_window_id;
-    int yes = 1;
-    PA("K|p", &os_window_id, &yes);
+    CloseRequest cr = IMPERATIVE_CLOSE_REQUESTED;
+    PA("K|i", &os_window_id, &cr);
     WITH_OS_WINDOW(os_window_id)
-        mark_os_window_for_close(os_window, yes ? true : false);
+        mark_os_window_for_close(os_window, cr);
         Py_RETURN_TRUE;
     END_WITH_OS_WINDOW
     Py_RETURN_FALSE;
@@ -899,6 +929,17 @@
     Py_RETURN_NONE;
 }
 
+
+PYWRAP1(sync_os_window_title) {
+    id_type os_window_id;
+    PA("K", &os_window_id);
+    WITH_OS_WINDOW(os_window_id)
+        update_os_window_title(os_window);
+    END_WITH_OS_WINDOW
+    Py_RETURN_NONE;
+}
+
+
 static inline double
 dpi_for_os_window_id(id_type os_window_id) {
     double dpi = 0;
@@ -1112,6 +1153,7 @@
     MW(change_background_opacity, METH_VARARGS),
     MW(background_opacity_of, METH_O),
     MW(update_window_visibility, METH_VARARGS),
+    MW(sync_os_window_title, METH_VARARGS),
     MW(global_font_size, METH_VARARGS),
     MW(set_background_image, METH_VARARGS),
     MW(os_window_font_size, METH_VARARGS),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/state.h 
new/kitty-0.17.4/kitty/state.h
--- old/kitty-0.17.3/kitty/state.h      2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/state.h      2020-05-09 07:18:21.000000000 +0200
@@ -139,6 +139,7 @@
 } OSWindowGeometry;
 
 enum RENDER_STATE { RENDER_FRAME_NOT_REQUESTED, RENDER_FRAME_REQUESTED, 
RENDER_FRAME_READY };
+typedef enum { NO_CLOSE_REQUESTED, CONFIRMABLE_CLOSE_REQUESTED, 
IMPERATIVE_CLOSE_REQUESTED } CloseRequest;
 
 typedef struct {
     monotonic_t last_resize_event_at;
@@ -183,6 +184,7 @@
     uint64_t render_calls;
     id_type last_focused_counter;
     ssize_t gvao_idx;
+    CloseRequest close_request;
 } OSWindow;
 
 
@@ -220,9 +222,8 @@
 bool remove_os_window(id_type os_window_id);
 void make_os_window_context_current(OSWindow *w);
 void update_os_window_references(void);
-void mark_os_window_for_close(OSWindow* w, bool yes);
+void mark_os_window_for_close(OSWindow* w, CloseRequest cr);
 void update_os_window_viewport(OSWindow *window, bool);
-bool should_os_window_close(OSWindow* w);
 bool should_os_window_be_rendered(OSWindow* w);
 void wakeup_main_loop(void);
 void swap_window_buffers(OSWindow *w);
@@ -276,3 +277,5 @@
 void run_main_loop(tick_callback_fun, void*);
 void stop_main_loop(void);
 void os_window_update_size_increments(OSWindow *window);
+void set_os_window_title_from_window(Window *w, OSWindow *os_window);
+void update_os_window_title(OSWindow *os_window);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/tab_bar.py 
new/kitty-0.17.4/kitty/tab_bar.py
--- old/kitty-0.17.3/kitty/tab_bar.py   2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/tab_bar.py   2020-05-09 07:18:21.000000000 +0200
@@ -21,6 +21,8 @@
     title: str
     is_active: bool
     needs_attention: bool
+    num_windows: int
+    layout_name: str
 
 
 class DrawData(NamedTuple):
@@ -56,7 +58,7 @@
     if tab.is_active and draw_data.active_title_template is not None:
         template = draw_data.active_title_template
     try:
-        title = template.format(title=tab.title, index=index)
+        title = template.format(title=tab.title, index=index, 
layout_name=tab.layout_name, num_windows=tab.num_windows)
     except Exception as e:
         if template not in template_failures:
             template_failures.add(template)
@@ -84,7 +86,7 @@
     screen.cursor.fg = 0
     if not is_last:
         screen.cursor.bg = as_rgb(color_as_int(draw_data.inactive_bg))
-    screen.draw(draw_data.sep)
+        screen.draw(draw_data.sep)
     screen.cursor.bg = 0
     return end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/tabs.py 
new/kitty-0.17.4/kitty/tabs.py
--- old/kitty-0.17.3/kitty/tabs.py      2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/tabs.py      2020-05-09 07:18:21.000000000 +0200
@@ -18,7 +18,7 @@
 from .fast_data_types import (
     add_tab, attach_window, detach_window, get_boss, mark_tab_bar_dirty,
     next_window_id, remove_tab, remove_window, ring_bell, set_active_tab,
-    swap_tabs, x11_window_id
+    swap_tabs, sync_os_window_title, x11_window_id
 )
 from .layout import (
     Layout, Rect, create_layout_object_for, evict_cached_layouts
@@ -138,6 +138,7 @@
         self._last_used_layout = self._current_layout_name
         self.current_layout = self.create_layout_object(layout_name)
         self._current_layout_name = layout_name
+        self.mark_tab_bar_dirty()
 
     def startup(self, session_tab: 'SessionTab') -> None:
         for cmd in session_tab.windows:
@@ -183,10 +184,13 @@
                 old_active_window.focus_changed(False)
             if new_active_window is not None:
                 new_active_window.focus_changed(True)
-            tm = self.tab_manager_ref()
-            if tm is not None:
-                self.relayout_borders()
-                tm.mark_tab_bar_dirty()
+            self.relayout_borders()
+            self.mark_tab_bar_dirty()
+
+    def mark_tab_bar_dirty(self) -> None:
+        tm = self.tab_manager_ref()
+        if tm is not None:
+            tm.mark_tab_bar_dirty()
 
     @property
     def active_window(self) -> Optional[Window]:
@@ -206,7 +210,7 @@
         if window is self.active_window:
             tm = self.tab_manager_ref()
             if tm is not None:
-                tm.mark_tab_bar_dirty()
+                tm.title_changed(self)
 
     def on_bell(self, window: Window) -> None:
         tm = self.tab_manager_ref()
@@ -330,6 +334,7 @@
     def _add_window(self, window: Window, location: Optional[str] = None) -> 
None:
         self.active_window_idx = self.current_layout.add_window(self.windows, 
window, self.active_window_idx, location)
         self.relayout_borders()
+        self.mark_tab_bar_dirty()
 
     def new_window(
         self,
@@ -431,6 +436,7 @@
         else:
             self.active_window_idx = active_window_idx
         self.relayout_borders()
+        self.mark_tab_bar_dirty()
         active_window = self.active_window
         if active_window:
             self.title_changed(active_window)
@@ -639,6 +645,11 @@
     def update_tab_bar_data(self) -> None:
         self.tab_bar.update(self.tab_bar_data)
 
+    def title_changed(self, tab: Tab) -> None:
+        self.mark_tab_bar_dirty()
+        if tab is self.active_tab:
+            sync_os_window_title(self.os_window_id)
+
     def resize(self, only_tabs: bool = False) -> None:
         if not only_tabs:
             if not self.tab_bar_hidden:
@@ -799,7 +810,10 @@
                 if w.needs_attention:
                     needs_attention = True
                     break
-            ans.append(TabBarData(title, t is at, needs_attention))
+            ans.append(TabBarData(
+                title, t is at, needs_attention,
+                len(t), t.current_layout.name or ''
+            ))
         return ans
 
     def activate_tab_at(self, x: int) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/kitty/utils.py 
new/kitty-0.17.4/kitty/utils.py
--- old/kitty-0.17.3/kitty/utils.py     2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/kitty/utils.py     2020-05-09 07:18:21.000000000 +0200
@@ -14,8 +14,8 @@
 from functools import lru_cache
 from time import monotonic
 from typing import (
-    Any, Callable, Dict, Generator, Iterable, List, NamedTuple, Optional,
-    Tuple, Union, cast
+    Any, Callable, Dict, Generator, Iterable, List, Match, NamedTuple,
+    Optional, Tuple, Union, cast
 )
 
 from .constants import (
@@ -28,6 +28,20 @@
 BASE = os.path.dirname(os.path.abspath(__file__))
 
 
+def expandvars(val: str, env: Dict[str, str] = {}) -> str:
+
+    def sub(m: Match) -> str:
+        key = m.group(1)
+        result = env.get(key)
+        if result is None:
+            result = os.environ.get(key)
+        if result is None:
+            result = m.group()
+        return result
+
+    return re.sub(r'\$\{(\S+?)\}', sub, val)
+
+
 def load_shaders(name: str) -> Tuple[str, str]:
     from .fast_data_types import GLSL_VERSION
     with open(os.path.join(BASE, '{}_vertex.glsl'.format(name))) as f:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/mypy-editor-integration 
new/kitty-0.17.4/mypy-editor-integration
--- old/kitty-0.17.3/mypy-editor-integration    2020-04-23 05:09:07.000000000 
+0200
+++ new/kitty-0.17.4/mypy-editor-integration    2020-05-09 07:18:21.000000000 
+0200
@@ -1,14 +1,19 @@
 #!/usr/bin/env python
 
+import os
 import subprocess
 import sys
 
-files = [x for x in sys.argv[1:] if not x.startswith('-')]
+base = os.path.dirname(os.path.abspath(__file__))
+files = [os.path.relpath(x, base) for x in sys.argv[1:] if not 
x.startswith('-')]
 if not files:
     raise SystemExit(subprocess.Popen(['mypy'] + sys.argv[1:]).wait())
 
 output = subprocess.run('dmypy run -- --follow-imports=error 
--show-column-numbers --no-color-output'.split(), stdout=subprocess.PIPE).stdout
 q = files[0] + ':'
+rc = 0
 for line in output.decode('utf-8').splitlines():
     if line.startswith(q):
         print(line)
+        rc = 1
+raise SystemExit(rc)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/session.vim new/kitty-0.17.4/session.vim
--- old/kitty-0.17.3/session.vim        2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/session.vim        2020-05-09 07:18:21.000000000 +0200
@@ -10,7 +10,7 @@
 set shiftwidth=4
 set softtabstop=0 
 set smarttab
-python <<endpython
+python3 <<endpython
 import sys
 sys.path.insert(0, os.path.abspath('.'))
 import kitty
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kitty-0.17.3/setup.py new/kitty-0.17.4/setup.py
--- old/kitty-0.17.3/setup.py   2020-04-23 05:09:07.000000000 +0200
+++ new/kitty-0.17.4/setup.py   2020-05-09 07:18:21.000000000 +0200
@@ -349,7 +349,7 @@
         raise SystemExit(ret)
 
 
-def get_vcs_rev_defines() -> List[str]:
+def get_vcs_rev_defines(env: Env) -> List[str]:
     ans = []
     if os.path.exists('.git'):
         try:
@@ -368,7 +368,7 @@
     return ans
 
 
-SPECIAL_SOURCES: Dict[str, Tuple[str, Union[List[str], Callable[[], 
Union[List[str], Iterator[str]]]]]] = {
+SPECIAL_SOURCES: Dict[str, Tuple[str, Union[List[str], Callable[[Env], 
Union[List[str], Iterator[str]]]]]] = {
     'kitty/parser_dump.c': ('kitty/parser.c', ['DUMP_COMMANDS']),
     'kitty/data-types.c': ('kitty/data-types.c', get_vcs_rev_defines),
 }
@@ -557,7 +557,7 @@
         if is_special:
             src, defines_ = SPECIAL_SOURCES[src]
             if callable(defines_):
-                defines = defines_()
+                defines = defines_(kenv)
                 cppflags.extend(map(define, defines))
             else:
                 cppflags.extend(map(define, defines_))


Reply via email to