diff --git a/.gitignore b/.gitignore index 96ef6c0..26629f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ /target Cargo.lock + +# CLion stuff +.idea/ diff --git a/Cargo.toml b/Cargo.toml index 8d79041..a61ec75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,16 @@ [package] name = "baseview" version = "0.1.0" -authors = ["William Light "] +authors = [ + "William Light ", + "Charles Saracco " +] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] +[target.'cfg(target_os="linux")'.dependencies] +xcb = { version = "0.9", features = ["thread", "xlib_xcb", "dri2"] } + +# [target.'cfg(target_os="windows")'.dependencies] + +# [target.'cfg(target_os="macos")'.dependencies] \ No newline at end of file diff --git a/examples/x11.rs b/examples/x11.rs new file mode 100644 index 0000000..e147269 --- /dev/null +++ b/examples/x11.rs @@ -0,0 +1,10 @@ +fn main() { + let window_open_options = baseview::WindowOpenOptions { + title: "baseview", + width: 512, + height: 512, + parent: baseview::Parent::None, + }; + + baseview::run(window_open_options); +} diff --git a/src/lib.rs b/src/lib.rs index e3fafdb..aaf7105 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,11 @@ use std::ffi::c_void; +mod x11; + pub enum Parent { None, AsIfParented, - WithParent(*mut c_void) + WithParent(*mut c_void), } pub struct WindowOpenOptions<'a> { @@ -12,5 +14,9 @@ pub struct WindowOpenOptions<'a> { pub width: usize, pub height: usize, - pub parent: Parent + pub parent: Parent, +} + +pub fn run(options: WindowOpenOptions) { + x11::run(options); } diff --git a/src/x11.rs b/src/x11.rs new file mode 100644 index 0000000..cd3cc17 --- /dev/null +++ b/src/x11.rs @@ -0,0 +1,110 @@ +// TODO: messy for now, will refactor when I have more of an idea of the API/architecture +// TODO: actually handle events +// TODO: set window title +// TODO: close window + +use crate::Parent; +use crate::WindowOpenOptions; + +struct X11Window { + xcb_connection: xcb::Connection, +} + +impl X11Window { + pub fn run(options: WindowOpenOptions) -> Self { + // Convert the parent to a X11 window ID if we're given one + let parent = match options.parent { + Parent::None => None, + Parent::AsIfParented => None, // ??? + Parent::WithParent(p) => Some(p as u32), + }; + + // Connect to the X server + let (conn, screen_num) = xcb::Connection::connect_with_xlib_display().unwrap(); + + // Figure out screen information + let setup = conn.get_setup(); + let screen = setup.roots().nth(screen_num as usize).unwrap(); + + // Create window, connecting to the parent if we have one + let win = conn.generate_id(); + let event_mask = &[ + (xcb::CW_BACK_PIXEL, screen.black_pixel()), + ( + xcb::CW_EVENT_MASK, + xcb::EVENT_MASK_EXPOSURE + | xcb::EVENT_MASK_BUTTON_PRESS + | xcb::EVENT_MASK_BUTTON_RELEASE + | xcb::EVENT_MASK_BUTTON_1_MOTION, + ), + ]; + xcb::create_window( + // Connection + &conn, + // Depth + xcb::COPY_FROM_PARENT as u8, + // Window ID + win, + // Parent ID + if let Some(p) = parent { + p + } else { + screen.root() + }, + // x + 0, + // y + 0, + // width + 1024, + // height + 1024, + // border width + 0, + // class + xcb::WINDOW_CLASS_INPUT_OUTPUT as u16, + // visual + screen.root_visual(), + // masks + event_mask, + ); + + // Change window title + let title = options.title; + xcb::change_property( + &conn, + xcb::PROP_MODE_REPLACE as u8, + win, + xcb::ATOM_WM_NAME, + xcb::ATOM_STRING, + 8, + title.as_bytes(), + ); + + // Display the window + xcb::map_window(&conn, win); + conn.flush(); + + let x11_window = Self { + xcb_connection: conn, + }; + + x11_window.handle_events(); + + return x11_window; + } + + // Event loop + fn handle_events(&self) { + loop { + let ev = self.xcb_connection.wait_for_event(); + if let Some(event) = ev { + println!("{:?}", event.response_type()); + } + } + } +} + +pub fn run(options: WindowOpenOptions) { + X11Window::run(options); +}