From 5ef2c404ced0be1185087f8c25f49d7721dec630 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 29 Nov 2016 11:29:39 +0530 Subject: [PATCH] Set primary selection when dragging with mouse --- kitty/char_grid.py | 34 +++++++++++++++++++++++++++++++++- kitty/utils.py | 14 ++++++++++++++ kitty/window.py | 19 +++++++++++-------- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/kitty/char_grid.py b/kitty/char_grid.py index 88344b531..4a01ff5df 100644 --- a/kitty/char_grid.py +++ b/kitty/char_grid.py @@ -8,7 +8,7 @@ from threading import Lock from .config import build_ansi_color_table from .constants import tab_manager, viewport_size, cell_size, ScreenGeometry, GLuint -from .utils import get_logical_dpi, to_color +from .utils import get_logical_dpi, to_color, set_primary_selection from .fast_data_types import ( glUniform2ui, glUniform4f, glUniform1i, glUniform2f, glDrawArraysInstanced, GL_TRIANGLE_FAN, glEnable, glDisable, GL_BLEND, glDrawArrays, ColorProfile, @@ -277,6 +277,38 @@ class CharGrid: self.current_selection.end_scrolled_by = self.scrolled_by if is_press is False: self.current_selection.in_progress = False + text = self.text_for_selection() + if text and text.strip(): + set_primary_selection(text) + + def screen_line(self, y): + ' Return the Line object corresponding to the yth line on the rendered screen ' + if y >= 0 and y < self.screen.lines: + if self.scrolled_by: + if y < self.scrolled_by: + return self.screen.historybuf.line(self.scrolled_by - y) + return self.screen.line(y - self.scrolled_by) + else: + return self.screen.line(y) + + def text_for_selection(self, sel=None): + start, end = (sel or self.current_selection).limits(self.scrolled_by) + lines = [] + if start != end: + for y in range(start[1], end[1] + 1): + line = self.screen_line(y) + if line is not None: + buf = [] + startx, endx = 0, self.screen.columns - 1 + if y == start[1]: + startx = max(0, min(start[0], endx)) + if y == end[1]: + endx = max(0, min(end[0], endx)) + for x in range(startx, endx + 1): + buf.append(line[x]) + line = ''.join(buf).rstrip(' ') + lines.append(line) + return '\n'.join(lines) def prepare_for_render(self, sprites): with self.buffer_lock: diff --git a/kitty/utils.py b/kitty/utils.py index de7dd92c0..1c88a5314 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -260,3 +260,17 @@ def handle_unix_signals(): signal.siginterrupt(sig, False) signal.set_wakeup_fd(write_fd) return read_fd + + +def get_primary_selection(): + # glfw has no way to get the primary selection + # https://github.com/glfw/glfw/issues/894 + return subprocess.check_output(['xsel', '-p']).decode('utf-8') + + +def set_primary_selection(text): + if isinstance(text, str): + text = text.encode('utf-8') + p = subprocess.Popen(['xsel', '-i', '-p'], stdin=subprocess.PIPE) + p.stdin.write(text), p.stdin.close() + p.wait() diff --git a/kitty/window.py b/kitty/window.py index fd0ab62c7..78e89d0ce 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -4,7 +4,6 @@ import os import weakref -import subprocess from functools import partial import glfw @@ -15,7 +14,7 @@ from .fast_data_types import ( BRACKETED_PASTE_START, BRACKETED_PASTE_END, Screen, read_bytes_dump, read_bytes ) from .terminfo import get_capabilities -from .utils import sanitize_title +from .utils import sanitize_title, get_primary_selection class Window: @@ -143,19 +142,23 @@ class Window: def paste(self, text): if text: + if isinstance(text, str): + text = text.encode('utf-8') if self.screen.in_bracketed_paste_mode(): text = BRACKETED_PASTE_START.encode('ascii') + text + BRACKETED_PASTE_END.encode('ascii') self.write_to_child(text) def paste_from_clipboard(self): - text = glfw.glfwGetClipboardString(self.window) - self.paste(text) + text = glfw.glfwGetClipboardString(tab_manager().glfw_window) + if text: + self.paste(text.decode('utf-8')) def paste_from_selection(self): - # glfw has no way to get the primary selection - # https://github.com/glfw/glfw/issues/894 - text = subprocess.check_output(['xsel']) - self.paste(text) + text = get_primary_selection() + if text: + if isinstance(text, bytes): + text = text.decode('utf-8') + self.paste(text) def scroll_line_up(self): self.char_grid.scroll('line', True)