mirror of
https://github.com/italicsjenga/rust_minifb.git
synced 2025-01-11 03:21:32 +11:00
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:
parent
d6271e513d
commit
2b8094cc6c
|
@ -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) {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -45,7 +45,6 @@ fn main() {
|
||||||
WIDTH,
|
WIDTH,
|
||||||
HEIGHT,
|
HEIGHT,
|
||||||
WindowOptions {
|
WindowOptions {
|
||||||
resize: true,
|
|
||||||
scale: Scale::X2,
|
scale: Scale::X2,
|
||||||
..WindowOptions::default()
|
..WindowOptions::default()
|
||||||
})
|
})
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue