diff --git a/Cargo.toml b/Cargo.toml index 162fe608..bd8d9d83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ opengl = ["uuid", "x11/glx"] [dependencies] keyboard-types = { version = "0.6.1", default-features = false } -raw-window-handle = "0.4.2" +raw-window-handle = "0.5" [target.'cfg(target_os="linux")'.dependencies] xcb = { version = "0.9", features = ["thread", "xlib_xcb", "dri2"] } diff --git a/src/gl/x11.rs b/src/gl/x11.rs index f62d318a..5e90f8de 100644 --- a/src/gl/x11.rs +++ b/src/gl/x11.rs @@ -1,8 +1,6 @@ use std::ffi::{c_void, CString}; use std::os::raw::{c_int, c_ulong}; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; - use x11::glx; use x11::xlib; @@ -80,20 +78,12 @@ impl GlContext { /// /// Use [Self::get_fb_config_and_visual] to create both of these things. pub unsafe fn create( - parent: &impl HasRawWindowHandle, config: FbConfig, + window: c_ulong, display: *mut xlib::_XDisplay, config: FbConfig, ) -> Result { - let handle = if let RawWindowHandle::Xlib(handle) = parent.raw_window_handle() { - handle - } else { - return Err(GlError::InvalidWindowHandle); - }; - - if handle.display.is_null() { + if display.is_null() { return Err(GlError::InvalidWindowHandle); } - let display = handle.display as *mut xlib::_XDisplay; - errors::XErrorHandler::handle(display, |error_handler| { #[allow(non_snake_case)] let glXCreateContextAttribsARB: GlXCreateContextAttribsARB = { @@ -144,13 +134,13 @@ impl GlContext { return Err(GlError::CreationFailed(CreationFailedError::ContextCreationFailed)); } - let res = glx::glXMakeCurrent(display, handle.window, context); + let res = glx::glXMakeCurrent(display, window, context); error_handler.check()?; if res == 0 { return Err(GlError::CreationFailed(CreationFailedError::MakeCurrentFailed)); } - glXSwapIntervalEXT(display, handle.window, config.gl_config.vsync as i32); + glXSwapIntervalEXT(display, window, config.gl_config.vsync as i32); error_handler.check()?; if glx::glXMakeCurrent(display, 0, std::ptr::null_mut()) == 0 { @@ -158,7 +148,7 @@ impl GlContext { return Err(GlError::CreationFailed(CreationFailedError::MakeCurrentFailed)); } - Ok(GlContext { window: handle.window, display, context }) + Ok(GlContext { window, display, context }) }) } diff --git a/src/macos/window.rs b/src/macos/window.rs index 67e8d201..d84de7c2 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -17,7 +17,10 @@ use keyboard_types::KeyboardEvent; use objc::{msg_send, runtime::Object, sel, sel_impl}; -use raw_window_handle::{AppKitHandle, HasRawWindowHandle, RawWindowHandle}; +use raw_window_handle::{ + AppKitDisplayHandle, AppKitWindowHandle, HasRawDisplayHandle, HasRawWindowHandle, + RawDisplayHandle, RawWindowHandle, +}; use crate::{ Event, EventStatus, Size, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, @@ -62,7 +65,7 @@ unsafe impl HasRawWindowHandle for WindowHandle { } } - RawWindowHandle::AppKit(AppKitHandle::empty()) + RawWindowHandle::AppKit(AppKitWindowHandle::empty()) } } @@ -345,7 +348,7 @@ impl Window { #[cfg(feature = "opengl")] fn create_gl_context(ns_window: Option, ns_view: id, config: GlConfig) -> GlContext { - let mut handle = AppKitHandle::empty(); + let mut handle = AppKitWindowHandle::empty(); handle.ns_window = ns_window.unwrap_or(ptr::null_mut()) as *mut c_void; handle.ns_view = ns_view as *mut c_void; let handle = RawWindowHandleWrapper { handle: RawWindowHandle::AppKit(handle) }; @@ -480,7 +483,7 @@ unsafe impl HasRawWindowHandle for Window { fn raw_window_handle(&self) -> RawWindowHandle { let ns_window = self.ns_window.unwrap_or(ptr::null_mut()) as *mut c_void; - let mut handle = AppKitHandle::empty(); + let mut handle = AppKitWindowHandle::empty(); handle.ns_window = ns_window; handle.ns_view = self.ns_view as *mut c_void; @@ -488,6 +491,12 @@ unsafe impl HasRawWindowHandle for Window { } } +unsafe impl HasRawDisplayHandle for Window { + fn raw_display_handle(&self) -> RawDisplayHandle { + RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()) + } +} + pub fn copy_to_clipboard(string: &str) { unsafe { let pb = NSPasteboard::generalPasteboard(nil); diff --git a/src/win/window.rs b/src/win/window.rs index 2c68b99c..76c2df6e 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -26,7 +26,10 @@ use std::os::windows::ffi::OsStrExt; use std::ptr::null_mut; use std::rc::Rc; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle, Win32Handle}; +use raw_window_handle::{ + HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, Win32WindowHandle, + WindowsDisplayHandle, +}; const BV_WINDOW_MUST_CLOSE: UINT = WM_USER + 1; @@ -87,12 +90,12 @@ impl WindowHandle { unsafe impl HasRawWindowHandle for WindowHandle { fn raw_window_handle(&self) -> RawWindowHandle { if let Some(hwnd) = self.hwnd { - let mut handle = Win32Handle::empty(); + let mut handle = Win32WindowHandle::empty(); handle.hwnd = hwnd as *mut c_void; RawWindowHandle::Win32(handle) } else { - RawWindowHandle::Win32(Win32Handle::empty()) + RawWindowHandle::Win32(Win32WindowHandle::empty()) } } } @@ -661,7 +664,7 @@ impl Window<'_> { #[cfg(feature = "opengl")] let gl_context: Option = options.gl_config.map(|gl_config| { - let mut handle = Win32Handle::empty(); + let mut handle = Win32WindowHandle::empty(); handle.hwnd = hwnd as *mut c_void; let handle = RawWindowHandleWrapper { handle: RawWindowHandle::Win32(handle) }; @@ -781,13 +784,19 @@ impl Window<'_> { unsafe impl HasRawWindowHandle for Window<'_> { fn raw_window_handle(&self) -> RawWindowHandle { - let mut handle = Win32Handle::empty(); + let mut handle = Win32WindowHandle::empty(); handle.hwnd = self.state.hwnd as *mut c_void; RawWindowHandle::Win32(handle) } } +unsafe impl HasRawDisplayHandle for Window<'_> { + fn raw_display_handle(&self) -> RawDisplayHandle { + RawDisplayHandle::Windows(WindowsDisplayHandle::empty()) + } +} + pub fn copy_to_clipboard(data: &str) { todo!() } diff --git a/src/window.rs b/src/window.rs index c0ef1ac8..f662990d 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,6 +1,8 @@ use std::marker::PhantomData; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; +use raw_window_handle::{ + HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, +}; use crate::event::{Event, EventStatus}; use crate::window_open_options::WindowOpenOptions; @@ -129,6 +131,12 @@ unsafe impl<'a> HasRawWindowHandle for Window<'a> { } } +unsafe impl<'a> HasRawDisplayHandle for Window<'a> { + fn raw_display_handle(&self) -> RawDisplayHandle { + self.window.raw_display_handle() + } +} + unsafe impl HasRawWindowHandle for RawWindowHandleWrapper { fn raw_window_handle(&self) -> RawWindowHandle { self.handle diff --git a/src/x11/window.rs b/src/x11/window.rs index fcd90837..00e01530 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -6,7 +6,10 @@ use std::sync::Arc; use std::thread; use std::time::*; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle, XlibHandle}; +use raw_window_handle::{ + HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, XlibDisplayHandle, + XlibWindowHandle, +}; use xcb::ffi::xcb_screen_t; use xcb::StructPtr; @@ -19,10 +22,7 @@ use crate::{ use super::keyboard::{convert_key_press_event, convert_key_release_event, key_mods}; #[cfg(feature = "opengl")] -use crate::{ - gl::{platform, GlContext}, - window::RawWindowHandleWrapper, -}; +use crate::gl::{platform, GlContext}; pub struct WindowHandle { raw_window_handle: Option, @@ -57,7 +57,7 @@ unsafe impl HasRawWindowHandle for WindowHandle { } } - RawWindowHandle::Xlib(XlibHandle::empty()) + RawWindowHandle::Xlib(XlibWindowHandle::empty()) } } @@ -96,6 +96,7 @@ pub struct Window { xcb_connection: XcbConnection, window_id: u32, window_info: WindowInfo, + visual_id: u32, // FIXME: There's all this mouse cursor logic but it's never actually used, is this correct? mouse_cursor: MouseCursor, @@ -280,10 +281,12 @@ impl Window { | xcb::EVENT_MASK_BUTTON_RELEASE | xcb::EVENT_MASK_KEY_PRESS | xcb::EVENT_MASK_KEY_RELEASE - | xcb::EVENT_MASK_STRUCTURE_NOTIFY, + | xcb::EVENT_MASK_STRUCTURE_NOTIFY + | xcb::EVENT_MASK_ENTER_WINDOW + | xcb::EVENT_MASK_LEAVE_WINDOW, ), - // As mentioend above, these two values are needed to be able to create a window - // with a dpeth of 32-bits when the parent window has a different depth + // As mentioned above, these two values are needed to be able to create a window + // with a depth of 32-bits when the parent window has a different depth (xcb::CW_COLORMAP, colormap), (xcb::CW_BORDER_PIXEL, 0), ], @@ -323,13 +326,11 @@ impl Window { // compared to when raw-gl-context was a separate crate. #[cfg(feature = "opengl")] let gl_context = fb_config.map(|fb_config| { - let mut handle = XlibHandle::empty(); - handle.window = window_id as c_ulong; - handle.display = xcb_connection.conn.get_raw_dpy() as *mut c_void; - let handle = RawWindowHandleWrapper { handle: RawWindowHandle::Xlib(handle) }; + let window = window_id as c_ulong; + let display = xcb_connection.conn.get_raw_dpy(); // Because of the visual negotation we had to take some extra steps to create this context - let context = unsafe { platform::GlContext::create(&handle, fb_config) } + let context = unsafe { platform::GlContext::create(window, display, fb_config) } .expect("Could not create OpenGL context"); GlContext::new(context) }); @@ -338,6 +339,7 @@ impl Window { xcb_connection, window_id, window_info, + visual_id: visual, mouse_cursor: MouseCursor::default(), frame_interval: Duration::from_millis(15), @@ -609,6 +611,30 @@ impl Window { } } + xcb::ENTER_NOTIFY => { + handler.on_event( + &mut crate::Window::new(self), + Event::Mouse(MouseEvent::CursorEntered), + ); + // since no `MOTION_NOTIFY` event is generated when `ENTER_NOTIFY` is generated, + // we generate a CursorMoved as well, so the mouse position from here isn't lost + let event = unsafe { xcb::cast_event::(&event) }; + let physical_pos = PhyPoint::new(event.event_x() as i32, event.event_y() as i32); + let logical_pos = physical_pos.to_logical(&self.window_info); + handler.on_event( + &mut crate::Window::new(self), + Event::Mouse(MouseEvent::CursorMoved { + position: logical_pos, + modifiers: key_mods(event.state()), + }), + ); + } + + xcb::LEAVE_NOTIFY => { + handler + .on_event(&mut crate::Window::new(self), Event::Mouse(MouseEvent::CursorLeft)); + } + xcb::BUTTON_PRESS => { let event = unsafe { xcb::cast_event::(&event) }; let detail = event.detail(); @@ -686,14 +712,27 @@ impl Window { unsafe impl HasRawWindowHandle for Window { fn raw_window_handle(&self) -> RawWindowHandle { - let mut handle = XlibHandle::empty(); - handle.window = self.window_id as c_ulong; - handle.display = self.xcb_connection.conn.get_raw_dpy() as *mut c_void; + let mut handle = XlibWindowHandle::empty(); + + handle.window = self.window_id.into(); + handle.visual_id = self.visual_id.into(); RawWindowHandle::Xlib(handle) } } +unsafe impl HasRawDisplayHandle for Window { + fn raw_display_handle(&self) -> RawDisplayHandle { + let display = self.xcb_connection.conn.get_raw_dpy(); + let mut handle = XlibDisplayHandle::empty(); + + handle.display = display as *mut c_void; + handle.screen = unsafe { x11::xlib::XDefaultScreen(display) }; + + RawDisplayHandle::Xlib(handle) + } +} + fn mouse_id(id: u8) -> MouseButton { match id { 1 => MouseButton::Left,