X11: Add support for startup notifications

Prevents busy cursor in i3 root window after launching and quitting
kitty immediately.
This commit is contained in:
Kovid Goyal 2017-11-07 23:19:15 +05:30
parent 3a81b186b0
commit ba1883c1de
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
2 changed files with 70 additions and 2 deletions

View file

@ -28,7 +28,10 @@
install_sigchld_handler, set_logical_dpi, set_options
)
from .layout import all_layouts
from .utils import color_as_int, detach, get_logical_dpi, safe_print
from .utils import (
color_as_int, detach, end_startup_notification, get_logical_dpi,
init_startup_notification, safe_print
)
try:
from .fast_data_types import GLFW_X11_WM_CLASS_NAME, GLFW_X11_WM_CLASS_CLASS
@ -188,6 +191,7 @@ def run_app(opts, args):
viewport_size.width = 640
viewport_size.height = 400
window = GLFWWindow(viewport_size.width, viewport_size.height, args.cls)
startup_ctx = init_startup_notification(window)
window.make_context_current()
if isosx:
from .fast_data_types import cocoa_make_window_resizable, cocoa_create_global_menu, cocoa_init
@ -202,6 +206,7 @@ def run_app(opts, args):
initialize_window(window, opts)
boss = Boss(window, opts, args)
boss.start()
end_startup_notification(startup_ctx)
try:
boss.child_monitor.main_loop()
finally:

View file

@ -2,17 +2,20 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
import ctypes
import math
import os
import re
import shlex
import string
import subprocess
import sys
from contextlib import contextmanager
from ctypes.util import find_library
from functools import lru_cache
from time import monotonic
from .constants import isosx, iswayland, selection_clipboard_funcs, x11_display
from .constants import isosx, iswayland, selection_clipboard_funcs, x11_display, x11_window_id
from .fast_data_types import (
GLSL_VERSION, glfw_get_physical_dpi, glfw_primary_monitor_content_scale,
redirect_std_streams, wcwidth as wcwidth_impl
@ -225,3 +228,63 @@ def adjust_line_height(cell_height, val):
if isinstance(val, int):
return cell_height + val
return int(cell_height * val)
def init_startup_notification_x11(window):
# https://specifications.freedesktop.org/startup-notification-spec/startup-notification-latest.txt
display = x11_display()
if not display:
return
lib = find_library('startup-notification-1')
if not lib:
safe_print('libstartup-notification-1.so not found, disabling startup notification', file=sys.stderr)
return
lib = init_startup_notification_x11.lib = ctypes.CDLL(lib)
f = lib.sn_display_new
f.restype = ctypes.c_void_p
f.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
display = f(x11_display(), None, None)
f = lib.sn_launchee_context_new_from_environment
f.restype = ctypes.c_void_p
f.argtypes = [ctypes.c_void_p, ctypes.c_int]
ctx = f(display, 0)
os.environ.pop('DESKTOP_STARTUP_ID', None) # ensure child processes dont get this env var
if ctx:
f = lib.sn_launchee_context_setup_window
f.argtypes = [ctypes.c_void_p, ctypes.c_int32]
f(ctx, x11_window_id(window))
return ctx
def end_startup_notification_x11(ctx):
lib = init_startup_notification_x11.lib
f = lib.sn_launchee_context_complete
f.restype = None
f.argtypes = [ctypes.c_void_p]
f(ctx)
f = lib.sn_launchee_context_unref
f.restype = None
f.argtypes = [ctypes.c_void_p]
f(ctx)
def init_startup_notification(window):
if isosx or iswayland:
return
try:
return init_startup_notification_x11(window)
except Exception:
import traceback
traceback.print_exc()
def end_startup_notification(ctx):
if not ctx:
return
if isosx or iswayland:
return
try:
end_startup_notification_x11(ctx)
except Exception:
import traceback
traceback.print_exc()