Skip to content

Commit bcf8afb

Browse files
committed
Cleanup X11 impl
1 parent 2ce28f5 commit bcf8afb

6 files changed

Lines changed: 173 additions & 126 deletions

File tree

src/platform/x11/drag_n_drop.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ impl DragNDropState {
401401
};
402402

403403
// Ignore if this was meant for another window (?)
404-
if event.requestor != window.window_id.get() {
404+
if event.requestor != window.xcb_window.id().get() {
405405
return Ok(());
406406
}
407407

@@ -486,7 +486,7 @@ fn send_status_rejected(
486486
response_type: xproto::CLIENT_MESSAGE_EVENT,
487487
window: source_window,
488488
format: 32,
489-
data: [window.window_id.get(), 0, 0, 0, conn.atoms.None as _].into(),
489+
data: [window.xcb_window.id().get(), 0, 0, 0, conn.atoms.None as _].into(),
490490
sequence: 0,
491491
type_: conn.atoms.XdndStatus,
492492
};
@@ -508,7 +508,7 @@ fn send_status_event(
508508
response_type: xproto::CLIENT_MESSAGE_EVENT,
509509
window: source_window,
510510
format: 32,
511-
data: [window.window_id.get(), 1, 0, 0, action as _].into(),
511+
data: [window.xcb_window.id().get(), 1, 0, 0, action as _].into(),
512512
sequence: 0,
513513
type_: conn.atoms.XdndStatus,
514514
};
@@ -527,7 +527,7 @@ pub fn send_finished_rejected(
527527
response_type: xproto::CLIENT_MESSAGE_EVENT,
528528
window: source_window,
529529
format: 32,
530-
data: [window.window_id.get(), 1, window.connection.atoms.None as _, 0, 0].into(),
530+
data: [window.xcb_window.id().get(), 1, window.connection.atoms.None as _, 0, 0].into(),
531531
sequence: 0,
532532
type_: conn.atoms.XdndFinished as _,
533533
};
@@ -548,7 +548,7 @@ fn send_finished_event(
548548
response_type: xproto::CLIENT_MESSAGE_EVENT,
549549
window: source_window,
550550
format: 32,
551-
data: [window.window_id.get(), 1, action as _, 0, 0].into(),
551+
data: [window.xcb_window.id().get(), 1, action as _, 0, 0].into(),
552552
sequence: 0,
553553
type_: conn.atoms.XdndFinished as _,
554554
};
@@ -564,7 +564,7 @@ fn request_convert_selection(
564564
let conn = &window.connection;
565565

566566
conn.conn.convert_selection(
567-
window.window_id.get(),
567+
window.xcb_window.id().get(),
568568
conn.atoms.XdndSelection,
569569
conn.atoms.TextUriList,
570570
conn.atoms.XdndSelection,
@@ -585,14 +585,14 @@ fn translate_root_coordinates(
585585
let x = x.try_into().unwrap_or(i16::MAX);
586586
let y = y.try_into().unwrap_or(i16::MAX);
587587

588-
if root_id == window.window_id.get() {
588+
if root_id == window.xcb_window.id().get() {
589589
return Ok(PhysicalPosition::new(x, y));
590590
}
591591

592592
let reply = window
593593
.connection
594594
.conn
595-
.translate_coordinates(root_id, window.window_id.get(), x, y)?
595+
.translate_coordinates(root_id, window.xcb_window.id().get(), x, y)?
596596
.reply()?;
597597

598598
Ok(PhysicalPosition::new(reply.dst_x, reply.dst_y))
@@ -602,7 +602,7 @@ fn fetch_dnd_data(window: &WindowInner) -> Result<DropData, Box<dyn Error>> {
602602
let conn = &window.connection;
603603

604604
let data: Vec<u8> = conn.get_property(
605-
window.window_id.get(),
605+
window.xcb_window.id().get(),
606606
conn.atoms.XdndSelection,
607607
conn.atoms.TextUriList,
608608
)?;

src/platform/x11/gl.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crate::gl::*;
33
use crate::wrappers::glx::*;
44
use crate::wrappers::xlib::{XErrorHandler, XLibError};
55

6-
use std::ffi::{c_void, CString};
7-
use std::os::raw::c_ulong;
6+
use crate::platform::x11::xcb_window::XcbWindow;
7+
use std::ffi::{c_ulong, c_void, CString};
88
use std::rc::Rc;
99
use x11_dl::error::OpenError;
1010
use x11_dl::glx::GLXContext;
@@ -36,7 +36,7 @@ pub type GlContext = Rc<GlContextInner>;
3636

3737
pub struct GlContextInner {
3838
glx: Glx,
39-
window: c_ulong,
39+
window: NonZeroU32,
4040
connection: Rc<X11Connection>,
4141
context: GLXContext,
4242
}
@@ -65,8 +65,8 @@ impl GlContextInner {
6565
///
6666
/// Use [Self::get_fb_config_and_visual] to create both of these things.
6767
pub fn create(
68-
window: c_ulong, connection: Rc<X11Connection>, config: FbConfig,
69-
) -> Result<GlContextInner, GlError> {
68+
window: &XcbWindow, connection: Rc<X11Connection>, config: FbConfig,
69+
) -> Result<Rc<GlContextInner>, GlError> {
7070
let glx = Glx::open()?;
7171

7272
let xlib_connection = connection.conn.xlib_connection();
@@ -87,28 +87,33 @@ impl GlContextInner {
8787
error_handler,
8888
)?;
8989

90+
let window_id = window.id().get().into();
9091
// Create context object here so that error or panic will properly free the context
91-
let context =
92-
GlContextInner { glx, window, connection: Rc::clone(&connection), context };
92+
let context = GlContextInner {
93+
glx,
94+
window: window.id(),
95+
connection: Rc::clone(&connection),
96+
context,
97+
};
9398

9499
unsafe {
95100
context.glx.with_current_context(
96101
xlib_connection,
97-
window,
102+
window_id,
98103
context.context,
99104
error_handler,
100105
|| {
101106
swap_interval(
102107
xlib_connection.as_raw(),
103-
window,
108+
window_id,
104109
config.gl_config.vsync as i32,
105110
);
106111
error_handler.check()
107112
},
108113
)??;
109114
}
110115

111-
Ok(context)
116+
Ok(Rc::new(context))
112117
})
113118
}
114119

@@ -142,7 +147,7 @@ impl GlContextInner {
142147
self.glx
143148
.make_current(
144149
self.connection.conn.xlib_connection(),
145-
self.window,
150+
self.window_id(),
146151
self.context,
147152
error_handler,
148153
)
@@ -156,6 +161,10 @@ impl GlContextInner {
156161
})
157162
}
158163

164+
fn window_id(&self) -> c_ulong {
165+
self.window.get().into()
166+
}
167+
159168
pub fn get_proc_address(&self, symbol: &str) -> *const c_void {
160169
let symbol = CString::new(symbol).unwrap();
161170

@@ -168,7 +177,11 @@ impl GlContextInner {
168177
pub fn swap_buffers(&self) {
169178
XErrorHandler::handle(self.connection.conn.xlib_connection(), |error_handler| {
170179
self.glx
171-
.swap_buffers(self.connection.conn.xlib_connection(), self.window, error_handler)
180+
.swap_buffers(
181+
self.connection.conn.xlib_connection(),
182+
self.window_id(),
183+
error_handler,
184+
)
172185
.unwrap()
173186
})
174187
}

src/platform/x11/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod xcb_connection;
22

33
use raw_window_handle::{DisplayHandle, HasWindowHandle, RawWindowHandle, XcbWindowHandle};
44
use std::fmt::Formatter;
5-
use std::num::NonZero;
5+
use std::num::{NonZero, NonZeroU32};
66
use std::rc::Rc;
77
use std::sync::Arc;
88
pub(crate) use xcb_connection::X11Connection;
@@ -15,6 +15,7 @@ mod drag_n_drop;
1515
mod event_loop;
1616
mod keyboard;
1717
mod visual_info;
18+
mod xcb_window;
1819

1920
mod window_shared;
2021

@@ -59,14 +60,14 @@ impl std::fmt::Debug for PlatformHandle {
5960

6061
#[derive(Debug, Clone, PartialEq)]
6162
pub struct ParentWindowHandle {
62-
window_id: u32,
63+
window_id: NonZeroU32,
6364
}
6465

6566
impl ParentWindowHandle {
6667
pub fn extract(window: &impl HasWindowHandle) -> Self {
6768
let window_id = match window.window_handle().unwrap().as_raw() {
68-
RawWindowHandle::Xlib(h) => h.window as u32,
69-
RawWindowHandle::Xcb(h) => h.window.get(),
69+
RawWindowHandle::Xlib(h) => NonZeroU32::new(h.window.try_into().unwrap()).unwrap(),
70+
RawWindowHandle::Xcb(h) => h.window,
7071
h => panic!("unsupported parent handle type {:?}", h),
7172
};
7273

src/platform/x11/window.rs

Lines changed: 18 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,14 @@ use std::sync::Arc;
88
use std::thread::{self, JoinHandle};
99

1010
use x11rb::connection::Connection;
11-
use x11rb::protocol::xproto::{
12-
AtomEnum, ConnectionExt, CreateGCAux, CreateWindowAux, EventMask, PropMode, WindowClass,
13-
};
14-
use x11rb::wrapper::ConnectionExt as _;
1511

1612
use super::X11Connection;
1713
use super::{event_loop::EventLoop, visual_info::WindowVisualConfig};
18-
use crate::context::WindowContext;
1914
use crate::handler::WindowHandlerBuilder;
2015
use crate::platform::x11::window_shared::WindowInner;
21-
use crate::{WindowOpenOptions, WindowScalePolicy, WindowSize};
16+
use crate::platform::x11::xcb_window::XcbWindow;
17+
use crate::wrappers::xkbcommon::XkbcommonState;
18+
use crate::*;
2219

2320
pub struct WindowHandle {
2421
window_id: Option<NonZero<x11rb::protocol::xproto::Window>>,
@@ -105,22 +102,10 @@ impl Window {
105102
tx: mpsc::SyncSender<WindowOpenResult>, parent_handle: Option<ParentHandle>,
106103
) -> Result<(), Box<dyn Error>> {
107104
// Connect to the X server
108-
// FIXME: baseview error type instead of unwrap()
109105
let xcb_connection = X11Connection::new()?;
110106

111107
// Setup xkbcommon
112-
let xkb_state = crate::wrappers::xkbcommon::XkbcommonState::new(&xcb_connection);
113-
114-
// Get screen information
115-
let screen = xcb_connection.screen();
116-
let parent_id = options.parent.map(|p| p.window_id).unwrap_or(screen.root);
117-
118-
let gc_id = xcb_connection.conn.generate_id()?;
119-
xcb_connection.conn.create_gc(
120-
gc_id,
121-
parent_id,
122-
&CreateGCAux::new().foreground(screen.black_pixel).graphics_exposures(0),
123-
)?;
108+
let xkb_state = XkbcommonState::new(&xcb_connection);
124109

125110
let scaling = match options.scale {
126111
WindowScalePolicy::SystemScaleFactor => xcb_connection.get_scaling(),
@@ -136,88 +121,33 @@ impl Window {
136121
#[cfg(not(feature = "opengl"))]
137122
let visual_info = WindowVisualConfig::find_best_visual_config(&xcb_connection)?;
138123

139-
let Some(window_id) = NonZero::new(xcb_connection.conn.generate_id()?) else {
140-
unreachable!();
141-
};
142-
143-
xcb_connection.conn.create_window(
144-
visual_info.visual_depth,
145-
window_id.get(),
146-
parent_id,
147-
0, // x coordinate of the new window
148-
0, // y coordinate of the new window
149-
physical_size.width, // window width
150-
physical_size.height, // window height
151-
0, // window border
152-
WindowClass::INPUT_OUTPUT,
153-
visual_info.visual_id,
154-
&CreateWindowAux::new()
155-
.event_mask(
156-
EventMask::EXPOSURE
157-
| EventMask::POINTER_MOTION
158-
| EventMask::BUTTON_PRESS
159-
| EventMask::BUTTON_RELEASE
160-
| EventMask::KEY_PRESS
161-
| EventMask::KEY_RELEASE
162-
| EventMask::STRUCTURE_NOTIFY
163-
| EventMask::ENTER_WINDOW
164-
| EventMask::LEAVE_WINDOW
165-
| EventMask::FOCUS_CHANGE,
166-
)
167-
// As mentioned above, these two values are needed to be able to create a window
168-
// with a depth of 32-bits when the parent window has a different depth
169-
.colormap(visual_info.color_map)
170-
.border_pixel(0),
171-
)?;
172-
xcb_connection.conn.map_window(window_id.get())?;
173-
174-
// Change window title
175-
let title = options.title;
176-
xcb_connection.conn.change_property8(
177-
PropMode::REPLACE,
178-
window_id.get(),
179-
AtomEnum::WM_NAME,
180-
AtomEnum::STRING,
181-
title.as_bytes(),
182-
)?;
124+
let xcb_connection = Rc::new(xcb_connection);
183125

184-
xcb_connection.conn.change_property32(
185-
PropMode::REPLACE,
186-
window_id.get(),
187-
xcb_connection.atoms.WM_PROTOCOLS,
188-
AtomEnum::ATOM,
189-
&[xcb_connection.atoms.WM_DELETE_WINDOW],
126+
let x_window = XcbWindow::new(
127+
Rc::clone(&xcb_connection),
128+
physical_size,
129+
&visual_info,
130+
options.parent.map(|p| p.window_id),
190131
)?;
191132

192-
// Enable drag and drop (TODO: Make this toggleable?)
193-
xcb_connection.conn.change_property32(
194-
PropMode::REPLACE,
195-
window_id.get(),
196-
xcb_connection.atoms.XdndAware,
197-
AtomEnum::ATOM,
198-
&[5u32], // Latest version; hasn't changed since 2002
199-
)?;
133+
x_window.map_window()?;
134+
x_window.set_title(&options.title)?;
135+
x_window.enable_wm_protocols()?;
136+
x_window.enable_dnd_protocols()?;
200137

201138
xcb_connection.conn.flush()?;
202-
let xcb_connection = Rc::new(xcb_connection);
203139

204140
#[cfg(feature = "opengl")]
205141
let gl_context = visual_info.fb_config.map(|fb_config| {
206-
use std::ffi::c_ulong;
207-
208-
let window = window_id.get() as c_ulong;
209-
210142
// Because of the visual negotation we had to take some extra steps to create this context
211-
let context =
212-
super::gl::GlContextInner::create(window, Rc::clone(&xcb_connection), fb_config)
213-
.expect("Could not create OpenGL context");
214-
215-
Rc::new(context)
143+
super::gl::GlContextInner::create(&x_window, Rc::clone(&xcb_connection), fb_config)
144+
.expect("Could not create OpenGL context")
216145
});
217146

147+
let window_id = x_window.id();
218148
let inner = Rc::new(WindowInner::new(
219149
xcb_connection,
220-
window_id,
150+
x_window,
221151
physical_size,
222152
scaling,
223153
visual_info.visual_id.try_into()?,
@@ -227,10 +157,6 @@ impl Window {
227157

228158
let handler = build.build(WindowContext::new(Rc::clone(&inner)));
229159

230-
// Send an initial window resized event so the user is alerted of
231-
// the correct dpi scaling.
232-
handler.resized(WindowSize::from_physical(physical_size.cast(), scaling));
233-
234160
let _ = tx.send(Ok(window_id));
235161

236162
EventLoop::new(inner, handler, parent_handle, xkb_state).run()?;

0 commit comments

Comments
 (0)