mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-11-10 03:01:14 +03:00
Wayland: Generate a XDG_ACTIVATION_TOKEN when opening URLs or running programs in the background via the launch action
This commit is contained in:
parent
58a3baaf0f
commit
dcf2152a7a
@ -53,6 +53,8 @@ Detailed list of changes
|
||||
|
||||
- Wayland: Fix for a bug preventing kitty from starting on Hyprland when using a non-unit scale (:iss:`5467`)
|
||||
|
||||
- Wayland: Generate a XDG_ACTIVATION_TOKEN when opening URLs or running programs in the background via the launch action
|
||||
|
||||
|
||||
0.26.2 [2022-09-05]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -246,6 +246,7 @@ def generate_wrappers(glfw_header: str) -> None:
|
||||
int glfwGetNativeKeyForName(const char* key_name, int case_sensitive)
|
||||
void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long id, GLFWwaylandframecallbackfunc callback)
|
||||
void glfwWaylandActivateWindow(GLFWwindow *handle, const char *activation_token)
|
||||
void glfwWaylandRunWithActivationToken(GLFWwindow *handle, GLFWactivationcallback cb, void *cb_data)
|
||||
bool glfwWaylandSetTitlebarColor(GLFWwindow *handle, uint32_t color, bool use_system_color)
|
||||
unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \
|
||||
const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data)
|
||||
|
6
glfw/wl_window.c
vendored
6
glfw/wl_window.c
vendored
@ -2223,6 +2223,12 @@ GLFWAPI void glfwWaylandActivateWindow(GLFWwindow* handle, const char *activatio
|
||||
if (activation_token && activation_token[0]) xdg_activation_v1_activate(_glfw.wl.xdg_activation_v1, activation_token, window->wl.surface);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwWaylandRunWithActivationToken(GLFWwindow *handle, GLFWactivationcallback cb, void *cb_data) {
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFW_REQUIRE_INIT();
|
||||
get_activation_token(window, _glfw.wl.input_serial, cb, cb_data);
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetNativeKeyForName(const char* keyName, bool caseSensitive) {
|
||||
return glfw_xkb_keysym_from_name(keyName, caseSensitive);
|
||||
}
|
||||
|
@ -20,7 +20,10 @@ from weakref import WeakValueDictionary
|
||||
from .child import cached_process_data, default_env, set_default_env
|
||||
from .cli import create_opts, parse_args
|
||||
from .cli_stub import CLIOptions
|
||||
from .clipboard import Clipboard, get_primary_selection, set_primary_selection, get_clipboard_string, set_clipboard_string
|
||||
from .clipboard import (
|
||||
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 (
|
||||
@ -38,11 +41,11 @@ from .fast_data_types import (
|
||||
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, 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
|
||||
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
|
||||
@ -1751,7 +1754,16 @@ class Boss:
|
||||
extra_env = {}
|
||||
if self.listening_on:
|
||||
extra_env['KITTY_LISTEN_ON'] = self.listening_on
|
||||
open_url(url, program or get_options().open_url_with, cwd=cwd, extra_env=extra_env)
|
||||
|
||||
def doit(activation_token: str = '') -> None:
|
||||
if activation_token:
|
||||
extra_env['XDG_ACTIVATION_TOKEN'] = activation_token
|
||||
open_url(url, program or get_options().open_url_with, cwd=cwd, extra_env=extra_env)
|
||||
|
||||
if is_wayland():
|
||||
run_with_activation_token(doit)
|
||||
else:
|
||||
doit()
|
||||
|
||||
@ac('misc', 'Click a URL using the keyboard')
|
||||
def open_url_with_hints(self) -> None:
|
||||
@ -1945,18 +1957,28 @@ class Boss:
|
||||
with suppress(Exception):
|
||||
cwd = cwd_from.cwd_of_child
|
||||
|
||||
if stdin:
|
||||
r, w = safe_pipe(False)
|
||||
try:
|
||||
subprocess.Popen(cmd, env=env, stdin=r, cwd=cwd, preexec_fn=clear_handled_signals)
|
||||
except Exception:
|
||||
os.close(w)
|
||||
def doit(activation_token: str = '') -> None:
|
||||
nonlocal env
|
||||
if activation_token:
|
||||
if env is None:
|
||||
env = default_env().copy()
|
||||
env['XDG_ACTIVATION_TOKEN'] = activation_token
|
||||
if stdin:
|
||||
r, w = safe_pipe(False)
|
||||
try:
|
||||
subprocess.Popen(cmd, env=env, stdin=r, cwd=cwd, preexec_fn=clear_handled_signals)
|
||||
except Exception:
|
||||
os.close(w)
|
||||
else:
|
||||
thread_write(w, stdin)
|
||||
finally:
|
||||
os.close(r)
|
||||
else:
|
||||
thread_write(w, stdin)
|
||||
finally:
|
||||
os.close(r)
|
||||
subprocess.Popen(cmd, env=env, cwd=cwd, preexec_fn=clear_handled_signals)
|
||||
if is_wayland():
|
||||
run_with_activation_token(doit)
|
||||
else:
|
||||
subprocess.Popen(cmd, env=env, cwd=cwd, preexec_fn=clear_handled_signals)
|
||||
doit()
|
||||
|
||||
def pipe(self, source: str, dest: str, exe: str, *args: str) -> Optional[Window]:
|
||||
cmd = [exe] + list(args)
|
||||
|
@ -1474,3 +1474,4 @@ def get_docs_ref_map() -> bytes: ...
|
||||
def clearenv() -> None: ...
|
||||
def set_clipboard_data_types(ct: int, mime_types: Tuple[str, ...]) -> None: ...
|
||||
def get_clipboard_mime(ct: int, mime: Optional[str], callback: Callable[[bytes], None]) -> None: ...
|
||||
def run_with_activation_token(func: Callable[[str], None]) -> None: ...
|
||||
|
3
kitty/glfw-wrapper.c
generated
3
kitty/glfw-wrapper.c
generated
@ -452,6 +452,9 @@ load_glfw(const char* path) {
|
||||
*(void **) (&glfwWaylandActivateWindow_impl) = dlsym(handle, "glfwWaylandActivateWindow");
|
||||
if (glfwWaylandActivateWindow_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwWaylandRunWithActivationToken_impl) = dlsym(handle, "glfwWaylandRunWithActivationToken");
|
||||
if (glfwWaylandRunWithActivationToken_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
*(void **) (&glfwWaylandSetTitlebarColor_impl) = dlsym(handle, "glfwWaylandSetTitlebarColor");
|
||||
if (glfwWaylandSetTitlebarColor_impl == NULL) dlerror(); // clear error indicator
|
||||
|
||||
|
4
kitty/glfw-wrapper.h
generated
4
kitty/glfw-wrapper.h
generated
@ -2210,6 +2210,10 @@ typedef void (*glfwWaylandActivateWindow_func)(GLFWwindow*, const char*);
|
||||
GFW_EXTERN glfwWaylandActivateWindow_func glfwWaylandActivateWindow_impl;
|
||||
#define glfwWaylandActivateWindow glfwWaylandActivateWindow_impl
|
||||
|
||||
typedef void (*glfwWaylandRunWithActivationToken_func)(GLFWwindow*, GLFWactivationcallback, void*);
|
||||
GFW_EXTERN glfwWaylandRunWithActivationToken_func glfwWaylandRunWithActivationToken_impl;
|
||||
#define glfwWaylandRunWithActivationToken glfwWaylandRunWithActivationToken_impl
|
||||
|
||||
typedef bool (*glfwWaylandSetTitlebarColor_func)(GLFWwindow*, uint32_t, bool);
|
||||
GFW_EXTERN glfwWaylandSetTitlebarColor_func glfwWaylandSetTitlebarColor_impl;
|
||||
#define glfwWaylandSetTitlebarColor glfwWaylandSetTitlebarColor_impl
|
||||
|
20
kitty/glfw.c
20
kitty/glfw.c
@ -1317,6 +1317,26 @@ find_os_window(id_type os_window_id) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
activation_token_callback(GLFWwindow *window UNUSED, const char *token, void *data) {
|
||||
if (!token || !token[0]) {
|
||||
token = "";
|
||||
log_error("Wayland: Did not get activation token from compositor. Use a better compositor.");
|
||||
}
|
||||
PyObject *ret = PyObject_CallFunction(data, "s", token);
|
||||
if (ret == NULL) PyErr_Print();
|
||||
else Py_DECREF(ret);
|
||||
Py_CLEAR(data);
|
||||
}
|
||||
|
||||
void
|
||||
run_with_activation_token_in_os_window(OSWindow *w, PyObject *callback) {
|
||||
if (global_state.is_wayland) {
|
||||
Py_INCREF(callback);
|
||||
glfwWaylandRunWithActivationToken(w->handle, activation_token_callback, callback);
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
toggle_fullscreen(PyObject UNUSED *self, PyObject *args) {
|
||||
id_type os_window_id = 0;
|
||||
|
@ -831,6 +831,17 @@ PYWRAP1(focus_os_window) {
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
PYWRAP1(run_with_activation_token) {
|
||||
for (size_t o = 0; o < global_state.num_os_windows; o++) {
|
||||
OSWindow *os_window = global_state.os_windows + o;
|
||||
if (os_window->is_focused) {
|
||||
run_with_activation_token_in_os_window(os_window, args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PYWRAP1(set_titlebar_color) {
|
||||
id_type os_window_id;
|
||||
unsigned int color;
|
||||
@ -1292,6 +1303,7 @@ static PyMethodDef module_methods[] = {
|
||||
MW(set_titlebar_color, METH_VARARGS),
|
||||
MW(focus_os_window, METH_VARARGS),
|
||||
MW(mark_tab_bar_dirty, METH_O),
|
||||
MW(run_with_activation_token, METH_O),
|
||||
MW(change_background_opacity, METH_VARARGS),
|
||||
MW(background_opacity_of, METH_O),
|
||||
MW(update_window_visibility, METH_VARARGS),
|
||||
|
@ -271,6 +271,7 @@ void hide_mouse(OSWindow *w);
|
||||
bool is_mouse_hidden(OSWindow *w);
|
||||
void destroy_os_window(OSWindow *w);
|
||||
void focus_os_window(OSWindow *w, bool also_raise, const char *activation_token);
|
||||
void run_with_activation_token_in_os_window(OSWindow *w, PyObject *callback);
|
||||
void set_os_window_title(OSWindow *w, const char *title);
|
||||
OSWindow* os_window_for_kitty_window(id_type);
|
||||
OSWindow* add_os_window(void);
|
||||
|
Loading…
Reference in New Issue
Block a user