x11 and examples: resize (#72)

* warnings / clippy

* x11: remove deprecated, ignored position hints

* x11: only non-resizable windows have fixed size

* x11: handle resizes of ximage
This commit is contained in:
Chris West 2019-04-01 09:19:23 +01:00 committed by Daniel Collin
parent d6271e513d
commit 2b8094cc6c
6 changed files with 101 additions and 65 deletions

View file

@ -10,6 +10,7 @@ fn main() {
let mut window = match Window::new("Mouse Draw - Press ESC to exit", WIDTH, HEIGHT, let mut window = match Window::new("Mouse Draw - Press ESC to exit", WIDTH, HEIGHT,
WindowOptions { WindowOptions {
resize: true,
scale: Scale::X2, scale: Scale::X2,
..WindowOptions::default() ..WindowOptions::default()
}) { }) {
@ -20,9 +21,29 @@ fn main() {
} }
}; };
let (mut width, mut height) = (WIDTH, HEIGHT);
while window.is_open() && !window.is_key_down(Key::Escape) { while window.is_open() && !window.is_key_down(Key::Escape) {
window.get_mouse_pos(MouseMode::Discard).map(|mouse| { {
let screen_pos = ((mouse.1 as usize) * WIDTH) + mouse.0 as usize; let (new_width, new_height) = window.get_size();
if new_width != width || new_height != height {
// copy valid bits of old buffer to new buffer
let mut new_buffer = vec![0; new_width * new_height / 2 / 2];
for y in 0..(height / 2).min(new_height / 2) {
for x in 0..(width / 2).min(new_width / 2) {
new_buffer[y * (new_width / 2) + x] = buffer[y * (width / 2) + x];
}
}
buffer = new_buffer;
width = new_width;
height = new_height;
}
}
window.get_mouse_pos(MouseMode::Discard).map(|(x, y)| {
let screen_pos = ((y as usize) * width / 2) + x as usize;
println!("{:?}", window.get_unscaled_mouse_pos(MouseMode::Discard).unwrap()); println!("{:?}", window.get_unscaled_mouse_pos(MouseMode::Discard).unwrap());
if window.get_mouse_down(MouseButton::Left) { if window.get_mouse_down(MouseButton::Left) {

View file

@ -6,16 +6,16 @@ fn main() {
let width = 640; let width = 640;
let height = 320; let height = 320;
let mut buffer = vec![0u32; width * height]; let mut buffer = vec![0u32; width * height];
let mut orig = Window::new("Smaller", width, height, WindowOptions {
resize: true,
..WindowOptions::default()
}).unwrap();
let mut double = Window::new("Larger", width, height, WindowOptions { let mut double = Window::new("Larger", width, height, WindowOptions {
resize: true,
scale: Scale::X2, scale: Scale::X2,
..WindowOptions::default() ..WindowOptions::default()
}).unwrap(); }).unwrap();
let mut orig = Window::new("Smaller", width, height, WindowOptions {
..WindowOptions::default()
}).unwrap();
let mut pos = 13; let mut pos = 13;
while orig.is_open() && double.is_open() while orig.is_open() && double.is_open()

View file

@ -2,7 +2,7 @@ extern crate minifb;
use minifb::{Window, Key, Scale, WindowOptions}; use minifb::{Window, Key, Scale, WindowOptions};
const WIDTH: usize = 640; const WIDTH: usize = 2560;
const HEIGHT: usize = 360; const HEIGHT: usize = 360;
fn main() { fn main() {
@ -10,7 +10,6 @@ fn main() {
let mut carry; let mut carry;
let mut seed = 0xbeefu32; let mut seed = 0xbeefu32;
let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
let mut window = match Window::new("Noise Test - Press ESC to exit", WIDTH, HEIGHT, let mut window = match Window::new("Noise Test - Press ESC to exit", WIDTH, HEIGHT,
WindowOptions { WindowOptions {
@ -25,7 +24,19 @@ fn main() {
} }
}; };
let mut buffer: Vec<u32> = Vec::with_capacity(WIDTH * HEIGHT);
let mut size = (0, 0);
while window.is_open() && !window.is_key_down(Key::Escape) { while window.is_open() && !window.is_key_down(Key::Escape) {
{
let new_size = window.get_size();
if new_size != size {
size = new_size;
buffer.resize(size.0 * size.1 / 2 / 2, 0);
}
}
for i in buffer.iter_mut() { for i in buffer.iter_mut() {
noise = seed; noise = seed;
noise >>= 3; noise >>= 3;

View file

@ -45,7 +45,6 @@ fn main() {
WIDTH, WIDTH,
HEIGHT, HEIGHT,
WindowOptions { WindowOptions {
resize: true,
scale: Scale::X2, scale: Scale::X2,
..WindowOptions::default() ..WindowOptions::default()
}) })

View file

@ -881,8 +881,8 @@ pub fn keysym_to_unicode(keysym: u32) -> Option<u32> {
} }
// Also check for directly encoded 24-bit UCS characters // Also check for directly encoded 24-bit UCS characters
if (keysym & 0xff000000) == 0x01000000 { if (keysym & 0xff00_0000) == 0x0100_0000 {
return Some(keysym & 0x00ffffff); return Some(keysym & 0x00ff_ffff);
} }
// Binary search in table // Binary search in table
@ -905,9 +905,7 @@ pub fn test_it() {
} }
// check ability to find every value in the table // check ability to find every value in the table
for i in 0..LENGTH { for p in keysymtab.iter() {
let p = keysymtab[i];
assert_eq!(keysym_to_unicode(p.0), Some(p.1)); assert_eq!(keysym_to_unicode(p.0), Some(p.1));
} }
} }

View file

@ -45,7 +45,7 @@ struct DisplayInfo {
depth: i32, depth: i32,
screen_width: usize, screen_width: usize,
screen_height: usize, screen_height: usize,
context: xlib::XContext, _context: xlib::XContext,
cursor_lib: x11_dl::xcursor::Xcursor, cursor_lib: x11_dl::xcursor::Xcursor,
cursors: [xlib::Cursor; 8], cursors: [xlib::Cursor; 8],
keyb_ext: bool, keyb_ext: bool,
@ -66,20 +66,11 @@ impl DisplayInfo {
fn setup() -> Result<DisplayInfo> { fn setup() -> Result<DisplayInfo> {
unsafe { unsafe {
// load the Xlib library let lib = xlib::Xlib::open()
let lib = match xlib::Xlib::open() { .map_err(|e| Error::WindowCreate(format!("failed to load Xlib: {:?}", e)))?;
Err(_) => {
return Err(Error::WindowCreate("failed to load Xlib".to_owned()));
}
Ok(v) => v,
};
let cursor_lib = match xcursor::Xcursor::open() { let cursor_lib = xcursor::Xcursor::open()
Err(_) => { .map_err(|e| Error::WindowCreate(format!("failed to load XCursor: {:?}", e)))?;
return Err(Error::WindowCreate("failed to load Xcursor".to_owned()));
}
Ok(v) => v,
};
let display = (lib.XOpenDisplay)(ptr::null()); let display = (lib.XOpenDisplay)(ptr::null());
@ -110,7 +101,7 @@ impl DisplayInfo {
depth, depth,
screen_width, screen_width,
screen_height, screen_height,
context, _context: context,
cursor_lib, cursor_lib,
// the following are determined later... // the following are determined later...
cursors: [0 as xlib::Cursor; 8], cursors: [0 as xlib::Cursor; 8],
@ -174,9 +165,6 @@ impl DisplayInfo {
} }
fn init_cursors(&mut self) { fn init_cursors(&mut self) {
// andrewj: TODO: consider using the XCreateFontCursor() API, since
// some of these names are not working for me (they return zero).
self.cursors[0] = self.load_cursor("arrow"); self.cursors[0] = self.load_cursor("arrow");
self.cursors[1] = self.load_cursor("xterm"); self.cursors[1] = self.load_cursor("xterm");
self.cursors[2] = self.load_cursor("crosshair"); self.cursors[2] = self.load_cursor("crosshair");
@ -320,12 +308,10 @@ impl Window {
| xlib::ButtonReleaseMask, | xlib::ButtonReleaseMask,
); );
if opts.resize { if !opts.resize {
let mut size_hints: xlib::XSizeHints = mem::zeroed(); let mut size_hints: xlib::XSizeHints = mem::zeroed();
size_hints.flags = xlib::PPosition | xlib::PMinSize | xlib::PMaxSize; size_hints.flags = xlib::PMinSize | xlib::PMaxSize;
size_hints.x = 0;
size_hints.y = 0;
size_hints.min_width = width as i32; size_hints.min_width = width as i32;
size_hints.max_width = width as i32; size_hints.max_width = width as i32;
size_hints.min_height = height as i32; size_hints.min_height = height as i32;
@ -342,32 +328,17 @@ impl Window {
(d.lib.XMapRaised)(d.display, handle); (d.lib.XMapRaised)(d.display, handle);
(d.lib.XFlush)(d.display); (d.lib.XFlush)(d.display);
let bytes_per_line = (width as i32) * 4;
let ximage = (d.lib.XCreateImage)(
d.display,
d.visual, /* TODO: this was CopyFromParent in the C code */
d.depth as u32,
xlib::ZPixmap,
0,
ptr::null_mut(),
width as u32,
height as u32,
32,
bytes_per_line,
);
if ximage == ptr::null_mut() {
(d.lib.XDestroyWindow)(d.display, handle);
return Err(Error::WindowCreate(
"Unable to create pixel buffer".to_owned(),
));
}
let mut draw_buffer: Vec<u32> = Vec::new(); let mut draw_buffer: Vec<u32> = Vec::new();
draw_buffer.resize(width * height, 0);
(*ximage).data = draw_buffer[..].as_mut_ptr() as *mut c_char; let ximage = match Self::alloc_image(&d, width, height, &mut draw_buffer) {
Some(ximage) => ximage,
None => {
(d.lib.XDestroyWindow)(d.display, handle);
return Err(Error::WindowCreate(
"Unable to create pixel buffer".to_owned(),
));
}
};
Ok(Window { Ok(Window {
d, d,
@ -391,6 +362,37 @@ impl Window {
} }
} }
unsafe fn alloc_image(d: &DisplayInfo, width: usize, height: usize, draw_buffer: &mut Vec<u32>) -> Option<*mut xlib::XImage> {
let bytes_per_line = (width as i32) * 4;
draw_buffer.resize(width * height, 0);
let image = (d.lib.XCreateImage)(
d.display,
d.visual, /* TODO: this was CopyFromParent in the C code */
d.depth as u32,
xlib::ZPixmap,
0,
draw_buffer[..].as_mut_ptr() as *mut c_char,
width as u32,
height as u32,
32,
bytes_per_line,
);
if image.is_null() {
None
} else {
Some(image)
}
}
unsafe fn free_image(&mut self) {
(*self.ximage).data = ptr::null_mut();
(self.d.lib.XDestroyImage)(self.ximage);
self.ximage = ptr::null_mut();
}
pub fn set_title(&mut self, title: &str) { pub fn set_title(&mut self, title: &str) {
match CString::new(title) { match CString::new(title) {
Err(_) => { Err(_) => {
@ -434,7 +436,7 @@ impl Window {
#[inline] #[inline]
pub fn get_window_handle(&self) -> *mut raw::c_void { pub fn get_window_handle(&self) -> *mut raw::c_void {
unsafe { mem::transmute(self.handle as usize) } self.handle as *mut raw::c_void
} }
#[inline] #[inline]
@ -765,6 +767,12 @@ impl Window {
// TODO : pass this onto the application // TODO : pass this onto the application
self.width = ev.configure.width as u32; self.width = ev.configure.width as u32;
self.height = ev.configure.height as u32; self.height = ev.configure.height as u32;
self.free_image();
self.ximage = Self::alloc_image(
&self.d,
cast::usize(self.width),
cast::usize(self.height),
&mut self.draw_buffer).expect("todo");
} }
_ => {} _ => {}
@ -992,13 +1000,12 @@ impl Window {
impl Drop for Window { impl Drop for Window {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
(*self.ximage).data = ptr::null_mut(); self.free_image();
// TODO [ andrewj: right now DisplayInfo is not shared, so doing this is // TODO [ andrewj: right now DisplayInfo is not shared, so doing this is
// probably pointless ] // probably pointless ]
// XSaveContext(s_display, info->window, s_context, (XPointer)0); // XSaveContext(s_display, info->window, s_context, (XPointer)0);
(self.d.lib.XDestroyImage)(self.ximage);
(self.d.lib.XDestroyWindow)(self.d.display, self.handle); (self.d.lib.XDestroyWindow)(self.d.display, self.handle);
} }
} }
@ -1024,7 +1031,7 @@ impl Menu {
let handle = self.next_item_handle(); let handle = self.next_item_handle();
self.internal.items.push(UnixMenuItem { self.internal.items.push(UnixMenuItem {
label: name.to_owned(), label: name.to_owned(),
handle: handle, handle,
sub_menu: Some(Box::new(sub_menu.internal.clone())), sub_menu: Some(Box::new(sub_menu.internal.clone())),
id: 0, id: 0,
enabled: true, enabled: true,