From a921180224eff1c7b5cd96145ef99f6e96636404 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 14 Sep 2017 08:59:41 +0530 Subject: [PATCH] Port middle-click-to-paste to C --- kitty/boss.py | 16 ++++++++++------ kitty/glfw.c | 2 +- kitty/mouse.c | 34 ++++++++++++++++++++++++++++++---- kitty/state.c | 1 + kitty/state.h | 1 + kitty/utils.py | 6 +++++- kitty/window.py | 11 ++--------- 7 files changed, 50 insertions(+), 21 deletions(-) diff --git a/kitty/boss.py b/kitty/boss.py index ba4ac13c0..00999f5fa 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -21,7 +21,7 @@ from .keys import ( ) from .session import create_session from .tabs import SpecialWindow, TabManager -from .utils import safe_print +from .utils import safe_print, get_primary_selection from .window import load_shader_programs @@ -75,9 +75,6 @@ class Boss: glfw_window.framebuffer_size_callback = self.on_window_resize glfw_window.char_mods_callback = self.on_text_input glfw_window.key_callback = self.on_key - glfw_window.mouse_button_callback = self.on_mouse_button - glfw_window.scroll_callback = self.on_mouse_scroll - glfw_window.cursor_pos_callback = self.on_mouse_move glfw_window.window_focus_callback = self.on_focus load_shader_programs() self.tab_manager = TabManager(opts, args) @@ -277,13 +274,20 @@ class Boss: destroy_global_data() del self.glfw_window - def paste_from_clipboard(self): - text = self.glfw_window.get_clipboard_string() + def paste_to_active_window(self, text): if text: w = self.active_window if w is not None: w.paste(text) + def paste_from_clipboard(self): + text = self.glfw_window.get_clipboard_string() + self.paste_to_active_window(text) + + def paste_from_selection(self): + text = get_primary_selection() + self.paste_to_active_window(text) + def next_tab(self): self.tab_manager.next_tab() diff --git a/kitty/glfw.c b/kitty/glfw.c index 3a4570ced..ada3920ca 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -69,7 +69,7 @@ mouse_button_callback(GLFWwindow *w, int button, int action, int mods) { if (!global_state.mouse_visible) { glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL); global_state.mouse_visible = true; } double now = monotonic(); global_state.last_mouse_activity_at = now; - if (button >= 0 && (unsigned int)button < sizeof(global_state.mouse_button_pressed)/sizeof(global_state.mouse_button_pressed)) { + if (button >= 0 && (unsigned int)button < sizeof(global_state.mouse_button_pressed)/sizeof(global_state.mouse_button_pressed[0])) { global_state.mouse_button_pressed[button] = action == GLFW_PRESS ? true : false; mouse_event(button, mods); } diff --git a/kitty/mouse.c b/kitty/mouse.c index 3ae0b3809..7994c40b5 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -51,11 +51,37 @@ handle_move_event(Window *w, int UNUSED button, int UNUSED modifiers, unsigned i } void -handle_button_event(Window UNUSED *w, int button, int UNUSED modifiers, unsigned int window_idx) { +handle_button_event(Window *w, int button, int modifiers, unsigned int window_idx) { Tab *t = global_state.tabs + global_state.active_tab; - if (window_idx != t->active_window && button == GLFW_MOUSE_BUTTON_LEFT) { - call_boss(switch_focus_to, "I", window_idx); - return; + bool is_release = !global_state.mouse_button_pressed[button]; + if (window_idx != t->active_window) { + if (is_release) call_boss(switch_focus_to, "I", window_idx); + } + Screen *screen = w->render_data.screen; + if (!screen) return; + bool handle_in_kitty = ( + modifiers == GLFW_MOD_SHIFT || + screen->modes.mouse_tracking_mode == 0 || + button == GLFW_MOUSE_BUTTON_MIDDLE || + (modifiers == (int)OPT(open_url_modifiers) && button == GLFW_MOUSE_BUTTON_LEFT) + ) ? true : false; + if (handle_in_kitty) { + switch(button) { + case GLFW_MOUSE_BUTTON_LEFT: + // TODO: update_drag + if (is_release) { + if (modifiers == (int)OPT(open_url_modifiers)) { + // TODO: click_url + } else if (!modifiers) { + // TODO: handle multi click + } + } + break; + case GLFW_MOUSE_BUTTON_MIDDLE: + if (is_release && !modifiers) { call_boss(paste_from_selection, NULL); return; } + break; + } + } else { } } diff --git a/kitty/state.c b/kitty/state.c index 2101ba54c..4ef58283c 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -127,6 +127,7 @@ PYWRAP1(set_options) { S(cursor_shape, PyLong_AsLong); S(cursor_opacity, PyFloat_AsDouble); S(mouse_hide_wait, PyFloat_AsDouble); + S(open_url_modifiers, PyLong_AsUnsignedLong); #undef S Py_RETURN_NONE; } diff --git a/kitty/state.h b/kitty/state.h index 584beaf5a..69fb156cc 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -14,6 +14,7 @@ typedef struct { bool enable_audio_bell; CursorShape cursor_shape; double cursor_opacity; + unsigned int open_url_modifiers; } Options; typedef struct { diff --git a/kitty/utils.py b/kitty/utils.py index bbed88e26..e9cfa6385 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -165,7 +165,11 @@ def get_primary_selection(): return '' # There is no primary selection on OS X # glfw has no way to get the primary selection # https://github.com/glfw/glfw/issues/894 - return subprocess.check_output(['xsel', '-p'], stderr=open(os.devnull, 'wb'), stdin=open(os.devnull, 'rb')).decode('utf-8') + ans = subprocess.check_output(['xsel', '-p'], stderr=open(os.devnull, 'wb'), stdin=open(os.devnull, 'rb')).decode('utf-8') + if ans: + # Without this for some reason repeated pastes dont work + set_primary_selection(ans) + return ans def base64_encode( diff --git a/kitty/window.py b/kitty/window.py index 2bcc61c9c..8cdcac4af 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -30,8 +30,8 @@ from .mouse import DRAG, MOVE, PRESS, RELEASE, encode_mouse_event from .rgb import to_color from .terminfo import get_capabilities from .utils import ( - color_as_int, get_primary_selection, load_shaders, open_url, - parse_color_set, sanitize_title, set_primary_selection + color_as_int, load_shaders, open_url, parse_color_set, sanitize_title, + set_primary_selection ) @@ -425,13 +425,6 @@ class Window: text = BRACKETED_PASTE_START.encode('ascii') + text + BRACKETED_PASTE_END.encode('ascii') self.write_to_child(text) - def paste_from_selection(self): - text = get_primary_selection() - if text: - if isinstance(text, bytes): - text = text.decode('utf-8') - self.paste(text) - def copy_to_clipboard(self): text = self.text_for_selection() if text: