aboutsummaryrefslogtreecommitdiff
path: root/alacritty_terminal/src
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty_terminal/src')
-rw-r--r--alacritty_terminal/src/clipboard.rs90
-rw-r--r--alacritty_terminal/src/display.rs6
-rw-r--r--alacritty_terminal/src/event.rs11
-rw-r--r--alacritty_terminal/src/input.rs26
-rw-r--r--alacritty_terminal/src/lib.rs1
-rw-r--r--alacritty_terminal/src/term/mod.rs56
-rw-r--r--alacritty_terminal/src/url.rs4
-rw-r--r--alacritty_terminal/src/window.rs15
8 files changed, 161 insertions, 48 deletions
diff --git a/alacritty_terminal/src/clipboard.rs b/alacritty_terminal/src/clipboard.rs
new file mode 100644
index 00000000..ca70c3bf
--- /dev/null
+++ b/alacritty_terminal/src/clipboard.rs
@@ -0,0 +1,90 @@
+// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+use std::ffi::c_void;
+
+use clipboard::nop_clipboard::NopClipboardContext;
+#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+use clipboard::wayland_clipboard::WaylandClipboardContext;
+#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+use clipboard::x11_clipboard::{Primary as X11SecondaryClipboard, X11ClipboardContext};
+use clipboard::{ClipboardContext, ClipboardProvider};
+
+pub struct Clipboard {
+ primary: Box<ClipboardProvider>,
+ secondary: Option<Box<ClipboardProvider>>,
+}
+
+impl Clipboard {
+ #[cfg(any(target_os = "macos", target_os = "windows"))]
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ #[cfg(not(any(target_os = "macos", target_os = "windows")))]
+ pub fn new(display: Option<*mut c_void>) -> Self {
+ if let Some(display) = display {
+ return Self {
+ primary: unsafe { Box::new(WaylandClipboardContext::new_from_external(display)) },
+ secondary: None,
+ };
+ }
+
+ Self {
+ primary: Box::new(ClipboardContext::new().unwrap()),
+ secondary: Some(Box::new(X11ClipboardContext::<X11SecondaryClipboard>::new().unwrap())),
+ }
+ }
+
+ // Use for tests and ref-tests
+ pub fn new_nop() -> Self {
+ Self { primary: Box::new(NopClipboardContext::new().unwrap()), secondary: None }
+ }
+}
+
+impl Default for Clipboard {
+ fn default() -> Self {
+ Self { primary: Box::new(ClipboardContext::new().unwrap()), secondary: None }
+ }
+}
+
+#[derive(Debug)]
+pub enum ClipboardType {
+ Primary,
+ Secondary,
+}
+
+impl Clipboard {
+ pub fn store(&mut self, ty: ClipboardType, text: impl Into<String>) {
+ let clipboard = match (ty, &mut self.secondary) {
+ (ClipboardType::Secondary, Some(provider)) => provider,
+ (ClipboardType::Secondary, None) => return,
+ _ => &mut self.primary,
+ };
+
+ clipboard.set_contents(text.into()).unwrap_or_else(|err| {
+ warn!("Error storing selection to clipboard. {}", err);
+ });
+ }
+
+ pub fn load(&mut self, ty: ClipboardType) -> Result<String, Box<std::error::Error>> {
+ let clipboard = match (ty, &mut self.secondary) {
+ (ClipboardType::Secondary, Some(provider)) => provider,
+ _ => &mut self.primary,
+ };
+
+ clipboard.get_contents()
+ }
+}
diff --git a/alacritty_terminal/src/display.rs b/alacritty_terminal/src/display.rs
index 1d5799f6..4cb023af 100644
--- a/alacritty_terminal/src/display.rs
+++ b/alacritty_terminal/src/display.rs
@@ -15,6 +15,7 @@
//! The display subsystem including window management, font rasterization, and
//! GPU drawing.
use std::f64;
+use std::ffi::c_void;
use std::sync::mpsc;
use glutin::dpi::{PhysicalPosition, PhysicalSize};
@@ -557,4 +558,9 @@ impl Display {
self.window().set_ime_spot(PhysicalPosition::from((nspot_x, nspot_y)).to_logical(dpr));
}
+
+ #[cfg(not(any(target_os = "macos", target_os = "windows")))]
+ pub fn get_wayland_display(&self) -> Option<*mut c_void> {
+ self.window.get_wayland_display()
+ }
}
diff --git a/alacritty_terminal/src/event.rs b/alacritty_terminal/src/event.rs
index 1f3e9ca5..f27a6caa 100644
--- a/alacritty_terminal/src/event.rs
+++ b/alacritty_terminal/src/event.rs
@@ -8,13 +8,13 @@ use std::io::Write;
use std::sync::mpsc;
use std::time::Instant;
-use copypasta::{Buffer as ClipboardBuffer, Clipboard, Load, Store};
use glutin::dpi::PhysicalSize;
use glutin::{self, ElementState, Event, ModifiersState, MouseButton};
use parking_lot::MutexGuard;
use serde_json as json;
use crate::cli::Options;
+use crate::clipboard::ClipboardType;
use crate::config::{self, Config};
use crate::display::OnResize;
use crate::grid::Scroll;
@@ -26,7 +26,6 @@ use crate::term::cell::Cell;
use crate::term::{SizeInfo, Term};
#[cfg(unix)]
use crate::tty;
-use crate::util::fmt::Red;
use crate::util::{limit, start_daemon};
use crate::window::Window;
@@ -70,14 +69,10 @@ impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> {
}
}
- fn copy_selection(&self, buffer: ClipboardBuffer) {
+ fn copy_selection(&mut self, ty: ClipboardType) {
if let Some(selected) = self.terminal.selection_to_string() {
if !selected.is_empty() {
- Clipboard::new()
- .and_then(|mut clipboard| clipboard.store(selected, buffer))
- .unwrap_or_else(|err| {
- warn!("Error storing selection to clipboard. {}", Red(err));
- });
+ self.terminal.clipboard().store(ty, selected);
}
}
}
diff --git a/alacritty_terminal/src/input.rs b/alacritty_terminal/src/input.rs
index fc79b398..0a5cd42b 100644
--- a/alacritty_terminal/src/input.rs
+++ b/alacritty_terminal/src/input.rs
@@ -23,7 +23,6 @@ use std::mem;
use std::ops::RangeInclusive;
use std::time::Instant;
-use copypasta::{Buffer as ClipboardBuffer, Clipboard, Load};
use glutin::{
ElementState, KeyboardInput, ModifiersState, MouseButton, MouseCursor, MouseScrollDelta,
TouchPhase,
@@ -31,6 +30,7 @@ use glutin::{
use unicode_width::UnicodeWidthStr;
use crate::ansi::{ClearMode, Handler};
+use crate::clipboard::ClipboardType;
use crate::config::{self, Key};
use crate::event::{ClickState, Mouse};
use crate::grid::Scroll;
@@ -63,7 +63,7 @@ pub struct Processor<'a, A: 'a> {
pub trait ActionContext {
fn write_to_pty<B: Into<Cow<'static, [u8]>>>(&mut self, _: B);
fn size_info(&self) -> SizeInfo;
- fn copy_selection(&self, _: ClipboardBuffer);
+ fn copy_selection(&mut self, _: ClipboardType);
fn clear_selection(&mut self);
fn update_selection(&mut self, point: Point, side: Side);
fn simple_selection(&mut self, point: Point, side: Side);
@@ -279,11 +279,12 @@ impl Action {
ctx.write_to_pty(s.clone().into_bytes())
},
Action::Copy => {
- ctx.copy_selection(ClipboardBuffer::Primary);
+ ctx.copy_selection(ClipboardType::Primary);
},
Action::Paste => {
- Clipboard::new()
- .and_then(|clipboard| clipboard.load_primary())
+ ctx.terminal_mut()
+ .clipboard()
+ .load(ClipboardType::Primary)
.map(|contents| self.paste(ctx, &contents))
.unwrap_or_else(|err| {
error!("Error loading data from clipboard: {}", Red(err));
@@ -292,8 +293,9 @@ impl Action {
Action::PasteSelection => {
// Only paste if mouse events are not captured by an application
if !mouse_mode {
- Clipboard::new()
- .and_then(|clipboard| clipboard.load_selection())
+ ctx.terminal_mut()
+ .clipboard()
+ .load(ClipboardType::Secondary)
.map(|contents| self.paste(ctx, &contents))
.unwrap_or_else(|err| {
error!("Error loading data from clipboard: {}", Red(err));
@@ -952,9 +954,9 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> {
/// Copy text selection.
fn copy_selection(&mut self) {
if self.save_to_clipboard {
- self.ctx.copy_selection(ClipboardBuffer::Primary);
+ self.ctx.copy_selection(ClipboardType::Primary);
}
- self.ctx.copy_selection(ClipboardBuffer::Selection);
+ self.ctx.copy_selection(ClipboardType::Secondary);
}
}
@@ -965,6 +967,7 @@ mod tests {
use glutin::{ElementState, Event, ModifiersState, MouseButton, VirtualKeyCode, WindowEvent};
+ use crate::clipboard::{Clipboard, ClipboardType};
use crate::config::{self, ClickHandler, Config};
use crate::event::{ClickState, Mouse, WindowChanges};
use crate::grid::Scroll;
@@ -974,7 +977,6 @@ mod tests {
use crate::term::{SizeInfo, Term, TermMode};
use super::{Action, Binding, Processor};
- use copypasta::Buffer as ClipboardBuffer;
const KEY: VirtualKeyCode = VirtualKeyCode::Key0;
@@ -1004,7 +1006,7 @@ mod tests {
fn simple_selection(&mut self, _point: Point, _side: Side) {}
- fn copy_selection(&self, _buffer: ClipboardBuffer) {}
+ fn copy_selection(&mut self, _: ClipboardType) {}
fn clear_selection(&mut self) {}
@@ -1095,7 +1097,7 @@ mod tests {
dpr: 1.0,
};
- let mut terminal = Term::new(&config, size, MessageBuffer::new());
+ let mut terminal = Term::new(&config, size, MessageBuffer::new(), Clipboard::new_nop());
let mut mouse = Mouse::default();
mouse.click_state = $initial_state;
diff --git a/alacritty_terminal/src/lib.rs b/alacritty_terminal/src/lib.rs
index ab1ba35e..182d7811 100644
--- a/alacritty_terminal/src/lib.rs
+++ b/alacritty_terminal/src/lib.rs
@@ -30,6 +30,7 @@ extern crate objc;
pub mod macros;
pub mod ansi;
pub mod cli;
+pub mod clipboard;
pub mod config;
mod cursor;
pub mod display;
diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs
index 84a23eca..cca6d2de 100644
--- a/alacritty_terminal/src/term/mod.rs
+++ b/alacritty_terminal/src/term/mod.rs
@@ -18,7 +18,6 @@ use std::ops::{Index, IndexMut, Range, RangeInclusive};
use std::time::{Duration, Instant};
use std::{io, mem, ptr};
-use copypasta::{Clipboard, Load, Store};
use font::{self, RasterizedGlyph, Size};
use glutin::MouseCursor;
use unicode_width::UnicodeWidthChar;
@@ -26,6 +25,7 @@ use unicode_width::UnicodeWidthChar;
use crate::ansi::{
self, Attr, CharsetIndex, Color, CursorStyle, Handler, NamedColor, StandardCharset,
};
+use crate::clipboard::{Clipboard, ClipboardType};
use crate::config::{Config, VisualBellAnimation};
use crate::cursor;
use crate::grid::{
@@ -756,6 +756,9 @@ pub struct Term {
/// Hint that Alacritty should be closed
should_exit: bool,
+
+ /// Clipboard access coupled to the active window
+ clipboard: Clipboard,
}
/// Terminal size info
@@ -843,7 +846,12 @@ impl Term {
self.next_mouse_cursor.take()
}
- pub fn new(config: &Config, size: SizeInfo, message_buffer: MessageBuffer) -> Term {
+ pub fn new(
+ config: &Config,
+ size: SizeInfo,
+ message_buffer: MessageBuffer,
+ clipboard: Clipboard,
+ ) -> Term {
let num_cols = size.cols();
let num_lines = size.lines();
@@ -889,6 +897,7 @@ impl Term {
auto_scroll: config.scrolling().auto_scroll,
message_buffer,
should_exit: false,
+ clipboard,
}
}
@@ -1317,6 +1326,10 @@ impl Term {
self.grid.url_highlight = None;
self.dirty = true;
}
+
+ pub fn clipboard(&mut self) -> &mut Clipboard {
+ &mut self.clipboard
+ }
}
impl ansi::TermInfo for Term {
@@ -1835,11 +1848,7 @@ impl ansi::Handler for Term {
/// Set the clipboard
#[inline]
fn set_clipboard(&mut self, string: &str) {
- Clipboard::new().and_then(|mut clipboard| clipboard.store_primary(string)).unwrap_or_else(
- |err| {
- warn!("Error storing selection to clipboard: {}", err);
- },
- );
+ self.clipboard.store(ClipboardType::Primary, string);
}
#[inline]
@@ -2120,20 +2129,20 @@ impl IndexMut<Column> for TabStops {
#[cfg(test)]
mod tests {
- use serde_json;
+ use std::mem;
- use super::{Cell, SizeInfo, Term};
- use crate::term::cell;
+ use font::Size;
+ use serde_json;
use crate::ansi::{self, CharsetIndex, Handler, StandardCharset};
+ use crate::clipboard::Clipboard;
use crate::config::Config;
use crate::grid::{Grid, Scroll};
use crate::index::{Column, Line, Point, Side};
use crate::input::FONT_SIZE_STEP;
use crate::message_bar::MessageBuffer;
use crate::selection::Selection;
- use font::Size;
- use std::mem;
+ use crate::term::{cell, Cell, SizeInfo, Term};
#[test]
fn semantic_selection_works() {
@@ -2146,7 +2155,8 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
- let mut term = Term::new(&Default::default(), size, MessageBuffer::new());
+ let mut term =
+ Term::new(&Default::default(), size, MessageBuffer::new(), Clipboard::new_nop());
let mut grid: Grid<Cell> = Grid::new(Line(3), Column(5), 0, Cell::default());
for i in 0..5 {
for j in 0..2 {
@@ -2190,7 +2200,8 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
- let mut term = Term::new(&Default::default(), size, MessageBuffer::new());
+ let mut term =
+ Term::new(&Default::default(), size, MessageBuffer::new(), Clipboard::new_nop());
let mut grid: Grid<Cell> = Grid::new(Line(1), Column(5), 0, Cell::default());
for i in 0..5 {
grid[Line(0)][Column(i)].c = 'a';
@@ -2215,7 +2226,8 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
- let mut term = Term::new(&Default::default(), size, MessageBuffer::new());
+ let mut term =
+ Term::new(&Default::default(), size, MessageBuffer::new(), Clipboard::new_nop());
let mut grid: Grid<Cell> = Grid::new(Line(3), Column(3), 0, Cell::default());
for l in 0..3 {
if l != 1 {
@@ -2259,7 +2271,8 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
- let mut term = Term::new(&Default::default(), size, MessageBuffer::new());
+ let mut term =
+ Term::new(&Default::default(), size, MessageBuffer::new(), Clipboard::new_nop());
let cursor = Point::new(Line(0), Column(0));
term.configure_charset(CharsetIndex::G0, StandardCharset::SpecialCharacterAndLineDrawing);
term.input('a');
@@ -2278,7 +2291,7 @@ mod tests {
dpr: 1.0,
};
let config: Config = Default::default();
- let mut term: Term = Term::new(&config, size, MessageBuffer::new());
+ let mut term: Term = Term::new(&config, size, MessageBuffer::new(), Clipboard::new_nop());
term.change_font_size(font_size);
let expected_font_size: Size = config.font().size() + Size::new(font_size);
@@ -2307,7 +2320,7 @@ mod tests {
dpr: 1.0,
};
let config: Config = Default::default();
- let mut term: Term = Term::new(&config, size, MessageBuffer::new());
+ let mut term: Term = Term::new(&config, size, MessageBuffer::new(), Clipboard::new_nop());
term.change_font_size(-100.0);
@@ -2327,7 +2340,7 @@ mod tests {
dpr: 1.0,
};
let config: Config = Default::default();
- let mut term: Term = Term::new(&config, size, MessageBuffer::new());
+ let mut term: Term = Term::new(&config, size, MessageBuffer::new(), Clipboard::new_nop());
term.change_font_size(10.0);
term.reset_font_size();
@@ -2348,7 +2361,7 @@ mod tests {
dpr: 1.0,
};
let config: Config = Default::default();
- let mut term: Term = Term::new(&config, size, MessageBuffer::new());
+ let mut term: Term = Term::new(&config, size, MessageBuffer::new(), Clipboard::new_nop());
// Add one line of scrollback
term.grid.scroll_up(&(Line(0)..Line(1)), Line(1), &Cell::default());
@@ -2373,6 +2386,7 @@ mod benches {
use std::mem;
use std::path::Path;
+ use crate::clipboard::Clipboard;
use crate::config::Config;
use crate::grid::Grid;
use crate::message_bar::MessageBuffer;
@@ -2416,7 +2430,7 @@ mod benches {
let config = Config::default();
- let mut terminal = Term::new(&config, size, MessageBuffer::new());
+ let mut terminal = Term::new(&config, size, MessageBuffer::new(), Clipboard::new_nop());
mem::swap(&mut terminal.grid, &mut grid);
let metrics = font::Metrics {
diff --git a/alacritty_terminal/src/url.rs b/alacritty_terminal/src/url.rs
index d3caf9fc..088cf657 100644
--- a/alacritty_terminal/src/url.rs
+++ b/alacritty_terminal/src/url.rs
@@ -148,6 +148,7 @@ mod tests {
use unicode_width::UnicodeWidthChar;
+ use crate::clipboard::Clipboard;
use crate::grid::Grid;
use crate::index::{Column, Line, Point};
use crate::message_bar::MessageBuffer;
@@ -166,7 +167,8 @@ mod tests {
};
let width = input.chars().map(|c| if c.width() == Some(2) { 2 } else { 1 }).sum();
- let mut term = Term::new(&Default::default(), size, MessageBuffer::new());
+ let mut term =
+ Term::new(&Default::default(), size, MessageBuffer::new(), Clipboard::new_nop());
let mut grid: Grid<Cell> = Grid::new(Line(1), Column(width), 0, Cell::default());
let mut i = 0;
diff --git a/alacritty_terminal/src/window.rs b/alacritty_terminal/src/window.rs
index a929a1b7..5c1457e5 100644
--- a/alacritty_terminal/src/window.rs
+++ b/alacritty_terminal/src/window.rs
@@ -12,12 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::convert::From;
+use std::ffi::c_void;
use std::fmt::Display;
use crate::gl;
use glutin::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize};
+#[cfg(target_os = "macos")]
+use glutin::os::macos::WindowExt;
#[cfg(not(any(target_os = "macos", windows)))]
-use glutin::os::unix::EventsLoopExt;
+use glutin::os::unix::{EventsLoopExt, WindowExt};
#[cfg(not(target_os = "macos"))]
use glutin::Icon;
use glutin::{
@@ -362,13 +365,11 @@ impl Window {
target_os = "openbsd"
))]
pub fn set_urgent(&self, is_urgent: bool) {
- use glutin::os::unix::WindowExt;
self.window().set_urgent(is_urgent);
}
#[cfg(target_os = "macos")]
pub fn set_urgent(&self, is_urgent: bool) {
- use glutin::os::macos::WindowExt;
self.window().request_user_attention(is_urgent);
}
@@ -381,8 +382,6 @@ impl Window {
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
pub fn get_window_id(&self) -> Option<usize> {
- use glutin::os::unix::WindowExt;
-
match self.window().get_xlib_window() {
Some(xlib_window) => Some(xlib_window as usize),
None => None,
@@ -416,6 +415,11 @@ impl Window {
self.window().set_simple_fullscreen(fullscreen);
}
+ #[cfg(not(any(target_os = "macos", target_os = "windows")))]
+ pub fn get_wayland_display(&self) -> Option<*mut c_void> {
+ self.window().get_wayland_display()
+ }
+
fn window(&self) -> &glutin::Window {
self.windowed_context.window()
}
@@ -441,7 +445,6 @@ impl OsExtensions for Window {}
))]
impl OsExtensions for Window {
fn run_os_extensions(&self) {
- use glutin::os::unix::WindowExt;
use libc::getpid;
use std::ffi::CStr;
use std::ptr;