diff options
Diffstat (limited to 'alacritty/src/window_context.rs')
-rw-r--r-- | alacritty/src/window_context.rs | 128 |
1 files changed, 106 insertions, 22 deletions
diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index 45adf8b8..833586ea 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -12,13 +12,19 @@ use std::sync::atomic::Ordering; use std::sync::Arc; use crossfont::Size; -use glutin::event::{Event as GlutinEvent, ModifiersState, WindowEvent}; -use glutin::event_loop::{EventLoopProxy, EventLoopWindowTarget}; -use glutin::window::WindowId; +use glutin::config::GetGlConfig; +use glutin::context::NotCurrentContext; +use glutin::display::GetGlDisplay; +#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] +use glutin::platform::x11::X11GlConfigExt; use log::{error, info}; +use raw_window_handle::HasRawDisplayHandle; use serde_json as json; #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use wayland_client::EventQueue; +use winit::event::{Event as WinitEvent, ModifiersState, WindowEvent}; +use winit::event_loop::{EventLoopProxy, EventLoopWindowTarget}; +use winit::window::WindowId; use alacritty_config::SerdeReplace; use alacritty_terminal::event::Event as TerminalEvent; @@ -35,18 +41,19 @@ use crate::cli::IpcConfig; use crate::cli::WindowOptions; use crate::clipboard::Clipboard; use crate::config::UiConfig; +use crate::display::window::Window; use crate::display::Display; use crate::event::{ActionContext, Event, EventProxy, EventType, Mouse, SearchState}; -use crate::input; use crate::logging::LOG_TARGET_IPC_CONFIG; use crate::message_bar::MessageBuffer; use crate::scheduler::Scheduler; +use crate::{input, renderer}; /// Event context for one individual Alacritty window. pub struct WindowContext { pub message_buffer: MessageBuffer, pub display: Display, - event_queue: Vec<GlutinEvent<'static, Event>>, + event_queue: Vec<WinitEvent<'static, Event>>, terminal: Arc<FairMutex<Term<EventProxy>>>, cursor_blink_timed_out: bool, modifiers: ModifiersState, @@ -68,33 +75,110 @@ pub struct WindowContext { } impl WindowContext { - /// Create a new terminal window context. - pub fn new( + /// Create initial window context that dous bootstrapping the graphics Api we're going to use. + pub fn initial( + event_loop: &EventLoopWindowTarget<Event>, + proxy: EventLoopProxy<Event>, config: Rc<UiConfig>, - options: &WindowOptions, - window_event_loop: &EventLoopWindowTarget<Event>, + options: WindowOptions, + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] + wayland_event_queue: Option<&EventQueue>, + ) -> Result<Self, Box<dyn Error>> { + let raw_display_handle = event_loop.raw_display_handle(); + + let mut identity = config.window.identity.clone(); + options.window_identity.override_identity_config(&mut identity); + + // Windows has different order of GL platform initialization compared to any other platform; + // it requires the window first. + #[cfg(windows)] + let window = Window::new(event_loop, &config, &identity)?; + #[cfg(windows)] + let raw_window_handle = Some(window.raw_window_handle()); + + #[cfg(not(windows))] + let raw_window_handle = None; + + let gl_display = + renderer::platform::create_gl_display(raw_display_handle, raw_window_handle)?; + let gl_config = renderer::platform::pick_gl_config(&gl_display, raw_window_handle)?; + + #[cfg(not(windows))] + let window = Window::new( + event_loop, + &config, + &identity, + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] + wayland_event_queue, + #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] + gl_config.x11_visual(), + )?; + + // Create context. + let gl_context = + renderer::platform::create_gl_context(&gl_display, &gl_config, raw_window_handle)?; + + Self::new(window, gl_context, config, options, proxy) + } + + /// Create additional context with the graphics platform other windows are using. + pub fn additional( + &self, + event_loop: &EventLoopWindowTarget<Event>, proxy: EventLoopProxy<Event>, + config: Rc<UiConfig>, + options: WindowOptions, #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] wayland_event_queue: Option<&EventQueue>, ) -> Result<Self, Box<dyn Error>> { - let mut pty_config = config.terminal_config.pty_config.clone(); - options.terminal_options.override_pty_config(&mut pty_config); + // Get any window and take its GL config and display to build a new context. + let (gl_display, gl_config) = { + let gl_context = self.display.gl_context(); + (gl_context.display(), gl_context.config()) + }; let mut identity = config.window.identity.clone(); - let preserve_title = options.window_identity.title.is_some(); options.window_identity.override_identity_config(&mut identity); - // Create a display. - // - // The display manages a window and can draw the terminal. - let display = Display::new( + let window = Window::new( + event_loop, &config, - window_event_loop, &identity, #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] wayland_event_queue, + #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] + gl_config.x11_visual(), + )?; + + // Create context. + let raw_window_handle = window.raw_window_handle(); + let gl_context = renderer::platform::create_gl_context( + &gl_display, + &gl_config, + Some(raw_window_handle), )?; + Self::new(window, gl_context, config, options, proxy) + } + + /// Create a new terminal window context. + fn new( + window: Window, + context: NotCurrentContext, + config: Rc<UiConfig>, + options: WindowOptions, + proxy: EventLoopProxy<Event>, + ) -> Result<Self, Box<dyn Error>> { + let mut pty_config = config.terminal_config.pty_config.clone(); + options.terminal_options.override_pty_config(&mut pty_config); + + let preserve_title = options.window_identity.title.is_some(); + + // Create a display. + // + // The display manages a window and can draw the terminal. + let display = Display::new(window, context, &config)?; + info!( "PTY dimensions: {:?} x {:?}", display.size_info.screen_lines(), @@ -307,17 +391,17 @@ impl WindowContext { event_proxy: &EventLoopProxy<Event>, clipboard: &mut Clipboard, scheduler: &mut Scheduler, - event: GlutinEvent<'_, Event>, + event: WinitEvent<'_, Event>, ) { match event { // Skip further event handling with no staged updates. - GlutinEvent::RedrawEventsCleared if self.event_queue.is_empty() && !self.dirty => { + WinitEvent::RedrawEventsCleared if self.event_queue.is_empty() && !self.dirty => { return; }, // Continue to process all pending events. - GlutinEvent::RedrawEventsCleared => (), + WinitEvent::RedrawEventsCleared => (), // Remap scale_factor change event to remove the lifetime. - GlutinEvent::WindowEvent { + WinitEvent::WindowEvent { event: WindowEvent::ScaleFactorChanged { scale_factor, new_inner_size }, window_id, } => { @@ -396,7 +480,7 @@ impl WindowContext { // Skip rendering on Wayland until we get frame event from compositor. #[cfg(not(any(target_os = "macos", windows)))] - if !self.display.is_x11 && !self.display.window.should_draw.load(Ordering::Relaxed) { + if self.display.is_wayland && !self.display.window.should_draw.load(Ordering::Relaxed) { return; } |