1
0
Fork 0

Merge remote-tracking branch 'upstream/master' into experiments

This commit is contained in:
Mirko Covizzi 2020-07-08 23:04:39 +02:00
commit fd7f4c1032
3 changed files with 97 additions and 34 deletions

View file

@ -16,6 +16,7 @@ log = "0.4.8"
[target.'cfg(target_os="linux")'.dependencies] [target.'cfg(target_os="linux")'.dependencies]
xcb = { version = "0.9", features = ["thread", "xlib_xcb", "dri2"] } xcb = { version = "0.9", features = ["thread", "xlib_xcb", "dri2"] }
x11 = { version = "2.3", features = ["xlib", "glx"]} x11 = { version = "2.3", features = ["xlib", "glx"]}
libc = "0.2"
[target.'cfg(target_os="windows")'.dependencies] [target.'cfg(target_os="windows")'.dependencies]
winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi", "wingdi", "errhandlingapi"] } winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef", "guiddef", "combaseapi", "wingdi", "errhandlingapi"] }

View file

@ -4,13 +4,18 @@ A low-level windowing system geared towards making audio plugin UIs.
`baseview` abstracts the platform-specific windowing APIs (winapi, cocoa, xcb) into a platform-independent API, but otherwise gets out of your way so you can write plugin UIs. `baseview` abstracts the platform-specific windowing APIs (winapi, cocoa, xcb) into a platform-independent API, but otherwise gets out of your way so you can write plugin UIs.
Interested in learning more about the project? Join us on [discord](https://discord.gg/b3hjnGw), channel `#vst2-gui`.
## Roadmap ## Roadmap
Below is a proposed list of milestones (roughly in-order) and their status. Subject to change at any time. Below is a proposed list of milestones (roughly in-order) and their status. Subject to change at any time.
| Feature | Windows | Mac OS | Linux | | Feature | Windows | Mac OS | Linux |
| -------------------------------------- | ------------------ | ------------------ | ------------------ | | ----------------------------------------------- | ------------------ | ------------------ | ------------------ |
| Spawns a window, no parent | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Spawns a window, no parent | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Cross-platform API for window spawning | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Cross-platform API for window spawning | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Window uses an OpenGL surface | :heavy_check_mark: | | :heavy_check_mark: | | Window uses an OpenGL surface | :heavy_check_mark: | | :heavy_check_mark: |
| Basic DPI scaling support | | | :question: | | Can find DPI scale factor | | | :heavy_check_mark: |
| Basic event handling (mouse, keyboard) | | | |
| Parent window support | | | |
| *(Converge on a common API for all platforms?)* | | | |

View file

@ -19,6 +19,7 @@ use crate::WindowOpenOptions;
pub struct Window { pub struct Window {
xcb_connection: XcbConnection, xcb_connection: XcbConnection,
scaling: Option<f64>, // DPI scale, 96.0 is "default".
} }
impl Window { impl Window {
@ -229,8 +230,15 @@ impl Window {
xlib::XSync(xcb_connection.conn.get_raw_dpy(), xlib::False); xlib::XSync(xcb_connection.conn.get_raw_dpy(), xlib::False);
} }
let x11_window = Self { xcb_connection }; let mut x11_window = Self {
xcb_connection,
scaling: None,
};
x11_window.scaling = x11_window
.get_scaling_xft()
.or(x11_window.get_scaling_screen_dimensions());
println!("Scale factor: {:?}", x11_window.scaling);
x11_window.handle_events(window_id, ctx); x11_window.handle_events(window_id, ctx);
return x11_window; return x11_window;
@ -259,34 +267,83 @@ impl Window {
} }
} }
} }
}
// Figure out the DPI scaling by opening a new temporary connection and asking XCB // Try to get the scaling with this function first.
// TODO: currently returning (96, 96) on my system, even though I have 4k screens. Problem with my setup perhaps? // If this gives you `None`, fall back to `get_scaling_screen_dimensions`.
#[allow(dead_code)] // If neither work, I guess just assume 96.0 and don't do any scaling.
pub fn get_scaling() -> (u32, u32) { fn get_scaling_xft(&self) -> Option<f64> {
// Connect to the X server use std::ffi::CString;
let xcb_connection = XcbConnection::new(); use x11::xlib::{
XResourceManagerString, XrmDestroyDatabase, XrmGetResource, XrmGetStringDatabase,
XrmValue,
};
// Figure out screen information let display = self.xcb_connection.conn.get_raw_dpy();
let setup = xcb_connection.conn.get_setup(); unsafe {
let screen = setup let rms = XResourceManagerString(display);
.roots() if !rms.is_null() {
.nth(xcb_connection.xlib_display as usize) let db = XrmGetStringDatabase(rms);
.unwrap(); if !db.is_null() {
let mut value = XrmValue {
size: 0,
addr: std::ptr::null_mut(),
};
// Get the DPI from the screen struct let mut value_type: *mut libc::c_char = std::ptr::null_mut();
// let name_c_str = CString::new("Xft.dpi").unwrap();
// there are 2.54 centimeters to an inch; so there are 25.4 millimeters. let c_str = CString::new("Xft.Dpi").unwrap();
// dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
// = N pixels / (M inch / 25.4)
// = N * 25.4 pixels / M inch
let width_px = screen.width_in_pixels() as f64;
let width_mm = screen.width_in_millimeters() as f64;
let height_px = screen.height_in_pixels() as f64;
let height_mm = screen.height_in_millimeters() as f64;
let xres = width_px * 25.4 / width_mm;
let yres = height_px * 25.4 / height_mm;
((xres + 0.5) as u32, (yres + 0.5) as u32) let dpi = if XrmGetResource(
} db,
name_c_str.as_ptr(),
c_str.as_ptr(),
&mut value_type,
&mut value,
) != 0
&& !value.addr.is_null()
{
let value_addr: &CStr = CStr::from_ptr(value.addr);
value_addr.to_str().ok();
let value_str = value_addr.to_str().ok()?;
let value_f64 = value_str.parse().ok()?;
Some(value_f64)
} else {
None
};
XrmDestroyDatabase(db);
return dpi;
}
}
}
None
}
// Try to get the scaling with `get_scaling_xft` first.
// Only use this function as a fallback.
// If neither work, I guess just assume 96.0 and don't do any scaling.
fn get_scaling_screen_dimensions(&self) -> Option<f64> {
// Figure out screen information
let setup = self.xcb_connection.conn.get_setup();
let screen = setup
.roots()
.nth(self.xcb_connection.xlib_display as usize)
.unwrap();
// Get the DPI from the screen struct
//
// there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
// dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
// = N pixels / (M inch / 25.4)
// = N * 25.4 pixels / M inch
let width_px = screen.width_in_pixels() as f64;
let width_mm = screen.width_in_millimeters() as f64;
let height_px = screen.height_in_pixels() as f64;
let height_mm = screen.height_in_millimeters() as f64;
let _xres = width_px * 25.4 / width_mm;
let yres = height_px * 25.4 / height_mm;
// TODO: choose between `xres` and `yres`? (probably both are the same?)
Some(yres)
}
}