Added set_title and set_cursor_style

This commit is contained in:
Daniel Collin 2016-06-24 13:08:01 +02:00
parent b231ee1b5a
commit 495f7c4cca
9 changed files with 621 additions and 314 deletions

View file

@ -14,7 +14,6 @@ build = "build.rs"
gcc = "0.3.19" gcc = "0.3.19"
[dependencies] [dependencies]
libc = "0.2"
time = "0.1.34" time = "0.1.34"
[target.x86_64-pc-windows-msvc.dependencies] [target.x86_64-pc-windows-msvc.dependencies]

79
examples/title_cursor.rs Normal file
View file

@ -0,0 +1,79 @@
extern crate minifb;
use minifb::{CursorStyle, Window, Key, Scale, WindowOptions, MouseMode};
const WIDTH: usize = 640;
const HEIGHT: usize = 360;
struct Rect {
x: usize,
y: usize,
width: usize,
height: usize,
color: u32,
cursor_style: CursorStyle,
}
impl Rect {
pub fn is_inside(&self, xf: f32, yf: f32) -> bool {
let x = xf as usize;
let y = yf as usize;
let xe = self.x + self.width;
let ye = self.y + self.height;
if (y >= self.y) && (y <= ye) &&
(x >= self.x) && (x <= xe) {
true
} else {
false
}
}
}
fn fill_rect(dest: &mut [u32], rect: &Rect) {
for y in 0..rect.height {
for x in 0..rect.width {
dest[((rect.y + y) * WIDTH) + rect.x + x] = rect.color;
}
}
}
fn main() {
let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
let mut window = Window::new("I haz no title :(",
WIDTH,
HEIGHT,
WindowOptions {
resize: true,
scale: Scale::X2,
..WindowOptions::default()
})
.expect("Unable to Open Window");
let rects = [
Rect { x: 0, y: 0, width: 160, height: 180, color: 0x00b27474, cursor_style: CursorStyle::Arrow },
Rect { x: 160, y: 0, width: 160, height: 180, color: 0x00b28050, cursor_style: CursorStyle::Ibeam },
Rect { x: 320, y: 0, width: 160, height: 180, color: 0x00a9b250, cursor_style: CursorStyle::Crosshair },
Rect { x: 480, y: 0, width: 160, height: 180, color: 0x0060b250, cursor_style: CursorStyle::ClosedHand },
Rect { x: 0, y: 180, width: 160, height: 180, color: 0x004fb292, cursor_style: CursorStyle::OpenHand },
Rect { x: 160, y: 180, width: 160, height: 180, color: 0x004f71b2, cursor_style: CursorStyle::ResizeLeftRight },
Rect { x: 320, y: 180, width: 160, height: 180, color: 0x008850b2, cursor_style: CursorStyle::ResizeUpDown },
Rect { x: 480, y: 180, width: 160, height: 180, color: 0x00b25091, cursor_style: CursorStyle::ResizeAll }
];
window.set_title("Diffrent cursor on each color region");
while window.is_open() && !window.is_key_down(Key::Escape) {
let (mx, my) = window.get_mouse_pos(MouseMode::Clamp).unwrap();
for rect in &rects {
fill_rect(&mut buffer, rect);
if rect.is_inside(mx, my) {
window.set_cursor_style(rect.cursor_style);
}
}
window.update_with_buffer(&buffer);
}
}

View file

@ -2,8 +2,6 @@
//! open windows (usually native to the running operating system) and can optionally show a 32-bit //! open windows (usually native to the running operating system) and can optionally show a 32-bit
//! buffer. minifb also support keyboard, mouse input and menus on selected operating systems. //! buffer. minifb also support keyboard, mouse input and menus on selected operating systems.
//! //!
extern crate libc;
use std::os::raw; use std::os::raw;
/// Scale will scale the frame buffer and the window that is being sent in when calling the update /// Scale will scale the frame buffer and the window that is being sent in when calling the update
@ -51,7 +49,7 @@ pub enum MouseButton
} }
/// Key is used by the get key functions to check if some keys on the keyboard has been pressed /// The diffrent modes that can be used to decide how mouse coordinates should be handled
#[derive(PartialEq, Clone, Copy)] #[derive(PartialEq, Clone, Copy)]
pub enum MouseMode { pub enum MouseMode {
/// Return mouse coords from outside of the window (may be negative) /// Return mouse coords from outside of the window (may be negative)
@ -62,14 +60,33 @@ pub enum MouseMode {
Discard, Discard,
} }
/// Different style of cursors that can be used
#[derive(PartialEq, Clone, Copy)]
pub enum CursorStyle {
/// Regular arrow style (this is what the cursor normal looks like)
Arrow,
/// Used when indicating insertion (like text field)
Ibeam,
/// Cross-hair cursor
Crosshair,
/// Closed hand which useful for dragging things, may use default hand on unsupported OSes.
ClosedHand,
/// Open hand which useful for indicating drangable things, may use default hand on unsupported OSes.
OpenHand,
/// Rezining left-rigth direction
ResizeLeftRight,
/// Rezining up-down direction
ResizeUpDown,
/// Resize in all directions
ResizeAll,
}
/// This trait can be implemented and set with ```set_input_callback``` to reieve a callback /// This trait can be implemented and set with ```set_input_callback``` to reieve a callback
/// whene there is inputs incoming. Currently only support unicode chars. /// whene there is inputs incoming. Currently only support unicode chars.
pub trait InputCallback { pub trait InputCallback {
fn add_char(&mut self, uni_char: u32); fn add_char(&mut self, uni_char: u32);
} }
#[doc(hidden)] #[doc(hidden)]
mod error; mod error;
pub use self::error::Error; pub use self::error::Error;
@ -163,6 +180,21 @@ impl Window {
imp::Window::new(name, width, height, opts).map(Window) imp::Window::new(name, width, height, opts).map(Window)
} }
///
/// Allows you to set a new title of the window after creation
///
/// # Examples
///
/// ```ignore
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap();
///
/// window.set_title("My New Title!");
/// ```
///
pub fn set_title(&mut self, title: &str) {
self.0.set_title(title)
}
/// ///
/// Returns the native handle for a window which is an opaque pointer/handle which /// Returns the native handle for a window which is an opaque pointer/handle which
/// dependens on the current operating system: /// dependens on the current operating system:
@ -314,6 +346,20 @@ impl Window {
self.0.get_scroll_wheel() self.0.get_scroll_wheel()
} }
///
/// Set a diffrent cursor style. This can be used if you have resizing
/// elements or something like that
///
/// # Examples
///
/// ```ignore
/// window.set_cursor_style(CursorStyle::ResizeLeftRight);
/// ```
///
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
self.0.set_cursor_style(cursor)
}
/// ///
/// Get the current keys that are down. /// Get the current keys that are down.
/// ///
@ -515,7 +561,7 @@ pub struct UnixMenu {
/// Name of the menu /// Name of the menu
pub name: String, pub name: String,
/// All items of the menu. /// All items of the menu.
pub items: Vec<UnixMenuItem>, pub items: Vec<UnixMenuItem>,
#[doc(hidden)] #[doc(hidden)]
pub handle: MenuHandle, pub handle: MenuHandle,
#[doc(hidden)] #[doc(hidden)]
@ -554,7 +600,7 @@ pub struct MenuHandle(pub u64);
/// ///
/// Menu holds info for menus /// Menu holds info for menus
/// ///
pub struct Menu(imp::Menu); pub struct Menu(imp::Menu);
@ -565,24 +611,24 @@ impl Menu {
} }
#[inline] #[inline]
/// Destroys a menu. Currently not implemented /// Destroys a menu. Currently not implemented
pub fn destroy_menu(&mut self) { pub fn destroy_menu(&mut self) {
//self.0.destroy_menu() //self.0.destroy_menu()
} }
#[inline] #[inline]
/// Adds a sub menu to the current menu /// Adds a sub menu to the current menu
pub fn add_sub_menu(&mut self, name: &str, menu: &Menu) { pub fn add_sub_menu(&mut self, name: &str, menu: &Menu) {
self.0.add_sub_menu(name, &menu.0) self.0.add_sub_menu(name, &menu.0)
} }
/// Adds a menu separator /// Adds a menu separator
pub fn add_separator(&mut self) { pub fn add_separator(&mut self) {
self.add_menu_item(&MenuItem { id: MENU_ID_SEPARATOR, ..MenuItem::default() }); self.add_menu_item(&MenuItem { id: MENU_ID_SEPARATOR, ..MenuItem::default() });
} }
#[inline] #[inline]
/// Adds an item to the menu /// Adds an item to the menu
pub fn add_menu_item(&mut self, item: &MenuItem) -> MenuItemHandle { pub fn add_menu_item(&mut self, item: &MenuItem) -> MenuItemHandle {
self.0.add_menu_item(item) self.0.add_menu_item(item)
} }
@ -604,14 +650,14 @@ impl Menu {
} }
#[inline] #[inline]
/// Removes an item from the menu /// Removes an item from the menu
pub fn remove_item(&mut self, item: &MenuItemHandle) { pub fn remove_item(&mut self, item: &MenuItemHandle) {
self.0.remove_item(item) self.0.remove_item(item)
} }
} }
/// ///
/// Holds info about each item in a menu /// Holds info about each item in a menu
/// ///
pub struct MenuItem<'a> { pub struct MenuItem<'a> {
pub id: usize, pub id: usize,
@ -640,10 +686,10 @@ impl<'a> Clone for MenuItem<'a> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
MenuItem { MenuItem {
id: self.id, id: self.id,
label: self.label.clone(), label: self.label.clone(),
enabled: self.enabled, enabled: self.enabled,
key: self.key, key: self.key,
modifier: self.modifier, modifier: self.modifier,
menu: None, menu: None,
} }
} }
@ -659,7 +705,7 @@ impl<'a> MenuItem<'a> {
} }
} }
#[inline] #[inline]
/// Sets a shortcut key and modifer (and returns itself) /// Sets a shortcut key and modifer (and returns itself)
/// ///
/// # Examples /// # Examples
/// ///
@ -674,7 +720,7 @@ impl<'a> MenuItem<'a> {
} }
} }
#[inline] #[inline]
/// Sets item to a separator /// Sets item to a separator
/// ///
/// # Examples /// # Examples
/// ///
@ -703,7 +749,7 @@ impl<'a> MenuItem<'a> {
} }
} }
#[inline] #[inline]
/// Must be called to finialize building of a menu item when started with ```menu.add_item()``` /// Must be called to finialize building of a menu item when started with ```menu.add_item()```
/// ///
/// # Examples /// # Examples
/// ///

View file

@ -13,6 +13,34 @@ const uint32_t WINDOW_TITLE = 1 << 3;
static void create_standard_menu(); static void create_standard_menu();
// Needs to match lib.rs enum
enum CursorStyle {
CursorStyle_Arrow,
CursorStyle_Ibeam,
CursorStyle_Crosshair,
CursorStyle_ClosedHand,
CursorStyle_OpenHand,
CursorStyle_ResizeLeftRight,
CursorStyle_ResizeUpDown,
CursorStyle_SizeAll,
CursorStyle_Count,
};
static NSCursor* s_cursors[CursorStyle_Count];
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void cursor_init() {
s_cursors[CursorStyle_Arrow] = [[NSCursor arrowCursor] retain];
s_cursors[CursorStyle_Ibeam] = [[NSCursor IBeamCursor] retain];
s_cursors[CursorStyle_Crosshair] = [[NSCursor crosshairCursor] retain];
s_cursors[CursorStyle_ClosedHand] = [[NSCursor closedHandCursor] retain];
s_cursors[CursorStyle_OpenHand] = [[NSCursor openHandCursor] retain];
s_cursors[CursorStyle_ResizeLeftRight] = [[NSCursor resizeLeftRightCursor] retain];
s_cursors[CursorStyle_ResizeUpDown] = [[NSCursor resizeUpDownCursor] retain];
s_cursors[CursorStyle_SizeAll] = [[NSCursor closedHandCursor] retain];
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef __clang__ #ifdef __clang__
@ -31,6 +59,7 @@ void* mfb_open(const char* name, int width, int height, uint32_t flags, int scal
[NSApplication sharedApplication]; [NSApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
create_standard_menu(); create_standard_menu();
cursor_init();
s_init = true; s_init = true;
} }
@ -63,6 +92,7 @@ void* mfb_open(const char* name, int width, int height, uint32_t flags, int scal
window->key_callback = 0; window->key_callback = 0;
window->shared_data = 0; window->shared_data = 0;
window->active_menu_id = -1; window->active_menu_id = -1;
window->prev_cursor = 0;
window->menu_data = malloc(sizeof(MenuData)); window->menu_data = malloc(sizeof(MenuData));
memset(window->menu_data, 0, sizeof(MenuData)); memset(window->menu_data, 0, sizeof(MenuData));
@ -195,6 +225,14 @@ static void create_standard_menu(void)
//[NSApp performSelector:setAppleMenuSelector withObject:appMenu]; //[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_title(void* window, const char* title)
{
OSXWindow* win = (OSXWindow*)window;
NSString* ns_title = [NSString stringWithUTF8String: title];
[win setTitle: ns_title];
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -240,7 +278,7 @@ static int update_events()
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int generic_update(OSXWindow* win) static int generic_update(OSXWindow* win)
{ {
int state = update_events(); int state = update_events();
@ -336,6 +374,25 @@ void mfb_set_mouse_data(void* window, SharedData* shared_data)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_cursor_style(void* window, int cursor)
{
OSXWindow* win = (OSXWindow*)window;
if (win->prev_cursor == cursor)
return;
if (cursor < 0 || cursor >= CursorStyle_Count) {
printf("cursor out of range %d\n", cursor);
return;
}
[s_cursors[cursor] set];
win->prev_cursor = cursor;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t mfb_is_active(void* window) uint32_t mfb_is_active(void* window)
{ {
OSXWindow* win = (OSXWindow*)window; OSXWindow* win = (OSXWindow*)window;
@ -451,12 +508,12 @@ static NSString* get_string_for_key(uint32_t t) {
uint64_t mfb_add_menu_item( uint64_t mfb_add_menu_item(
void* in_menu, void* in_menu,
int32_t menu_id, int32_t menu_id,
const char* item_name, const char* item_name,
bool enabled, bool enabled,
uint32_t key, uint32_t key,
uint32_t modfier) uint32_t modfier)
{ {
NSMenu* menu = (NSMenu*)in_menu; NSMenu* menu = (NSMenu*)in_menu;
NSString* name = [NSString stringWithUTF8String: item_name]; NSString* name = [NSString stringWithUTF8String: item_name];
@ -517,7 +574,7 @@ uint64_t mfb_add_menu_item(
[newItem setKeyEquivalentModifierMask: mask]; [newItem setKeyEquivalentModifierMask: mask];
[newItem setKeyEquivalent:key_string]; [newItem setKeyEquivalent:key_string];
} }
if (enabled) { if (enabled) {
[newItem setEnabled:YES]; [newItem setEnabled:YES];
} else { } else {
@ -567,7 +624,7 @@ void mfb_destroy_menu(void* menu_item, const char* name)
void mfb_remove_menu_item(void* parent, uint64_t menu_item) { void mfb_remove_menu_item(void* parent, uint64_t menu_item) {
NSMenu* menu = (NSMenu*)parent; NSMenu* menu = (NSMenu*)parent;
NSMenuItem* item = (NSMenuItem*)(uintptr_t)menu_item; NSMenuItem* item = (NSMenuItem*)(uintptr_t)menu_item;
[menu removeItem:item]; [menu removeItem:item];
} }
@ -576,7 +633,7 @@ void mfb_remove_menu_item(void* parent, uint64_t menu_item) {
uint64_t mfb_add_menu(void* window, void* m) uint64_t mfb_add_menu(void* window, void* m)
{ {
OSXWindow* win = (OSXWindow*)window; OSXWindow* win = (OSXWindow*)window;
NSMenu* menu = (NSMenu*)m; NSMenu* menu = (NSMenu*)m;
NSMenu* main_menu = [NSApp mainMenu]; NSMenu* main_menu = [NSApp mainMenu];

View file

@ -51,6 +51,7 @@ void build_submenu(NSMenu* menu, MenuDesc* desc);
@public bool should_close; @public bool should_close;
@public bool is_active; @public bool is_active;
@public int active_menu_id; @public int active_menu_id;
@public int prev_cursor;
@public MenuData* menu_data; @public MenuData* menu_data;
} }

View file

@ -1,6 +1,7 @@
#include <X11/Xresource.h> #include <X11/Xresource.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/Xcursor/Xcursor.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -34,12 +35,27 @@ static int s_screen_height;
static XContext s_context; static XContext s_context;
static Atom s_wm_delete_window; static Atom s_wm_delete_window;
// Needs to match lib.rs enum
enum CursorStyle {
CursorStyle_Arrow,
CursorStyle_Ibeam,
CursorStyle_Crosshair,
CursorStyle_ClosedHand,
CursorStyle_OpenHand,
CursorStyle_ResizeLeftRight,
CursorStyle_ResizeUpDown,
CursorStyle_SizeAll,
CursorStyle_Count,
};
static Cursor s_cursors[CursorStyle_Count];
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct SharedData { typedef struct SharedData {
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
float scale; float scale;
float mouse_x; float mouse_x;
float mouse_y; float mouse_y;
float scroll_x; float scroll_x;
@ -50,157 +66,181 @@ typedef struct SharedData {
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct WindowInfo { typedef struct WindowInfo {
void (*key_callback)(void* user_data, int key, int state); void (*key_callback)(void* user_data, int key, int state);
void* rust_data; void* rust_data;
SharedData* shared_data; SharedData* shared_data;
Window window; Window window;
XImage* ximage; XImage* ximage;
void* draw_buffer; void* draw_buffer;
int scale; int scale;
int width; int width;
int height; int height;
int update; int update;
int prev_cursor;
} WindowInfo; } WindowInfo;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void init_cursors() {
s_cursors[CursorStyle_Arrow] = XcursorLibraryLoadCursor(s_display, "arrow");
s_cursors[CursorStyle_Ibeam] = XcursorLibraryLoadCursor(s_display, "xterm");
s_cursors[CursorStyle_Crosshair] = XcursorLibraryLoadCursor(s_display, "crosshair");
s_cursors[CursorStyle_ClosedHand] = XcursorLibraryLoadCursor(s_display, "hand2");
s_cursors[CursorStyle_OpenHand] = XcursorLibraryLoadCursor(s_display, "hand2");
s_cursors[CursorStyle_ResizeLeftRight] = XcursorLibraryLoadCursor(s_display, "sb_h_double_arrow");
s_cursors[CursorStyle_ResizeUpDown] = XcursorLibraryLoadCursor(s_display, "sb_v_double_arrow");
s_cursors[CursorStyle_SizeAll] = XcursorLibraryLoadCursor(s_display, "diamond_cross");
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int setup_display() { static int setup_display() {
int depth, i, formatCount, convDepth = -1; int depth, i, formatCount, convDepth = -1;
XPixmapFormatValues* formats; XPixmapFormatValues* formats;
if (s_setup_done) { if (s_setup_done) {
return 1; return 1;
} }
s_display = XOpenDisplay(0); s_display = XOpenDisplay(0);
if (!s_display) { if (!s_display) {
printf("Unable to open X11 display\n"); printf("Unable to open X11 display\n");
return 0; return 0;
} }
s_context = XUniqueContext(); s_context = XUniqueContext();
s_screen = DefaultScreen(s_display); s_screen = DefaultScreen(s_display);
s_visual = DefaultVisual(s_display, s_screen); s_visual = DefaultVisual(s_display, s_screen);
formats = XListPixmapFormats(s_display, &formatCount); formats = XListPixmapFormats(s_display, &formatCount);
depth = DefaultDepth(s_display, s_screen); depth = DefaultDepth(s_display, s_screen);
for (i = 0; i < formatCount; ++i) { for (i = 0; i < formatCount; ++i) {
if (depth == formats[i].depth) { if (depth == formats[i].depth) {
convDepth = formats[i].bits_per_pixel; convDepth = formats[i].bits_per_pixel;
break; break;
} }
} }
XFree(formats); XFree(formats);
// We only support 32-bit right now // We only support 32-bit right now
if (convDepth != 32) { if (convDepth != 32) {
printf("Unable to find 32-bit format for X11 display\n"); printf("Unable to find 32-bit format for X11 display\n");
XCloseDisplay(s_display); XCloseDisplay(s_display);
return 0; return 0;
} }
s_depth = depth; s_depth = depth;
s_gc = DefaultGC(s_display, s_screen); s_gc = DefaultGC(s_display, s_screen);
s_screen_width = DisplayWidth(s_display, s_screen); s_screen_width = DisplayWidth(s_display, s_screen);
s_screen_height = DisplayHeight(s_display, s_screen); s_screen_height = DisplayHeight(s_display, s_screen);
const char* wmDeleteWindowName = "WM_DELETE_WINDOW"; const char* wmDeleteWindowName = "WM_DELETE_WINDOW";
XInternAtoms(s_display, (char**)&wmDeleteWindowName, 1, False, &s_wm_delete_window); XInternAtoms(s_display, (char**)&wmDeleteWindowName, 1, False, &s_wm_delete_window);
s_setup_done = 1; s_setup_done = 1;
return 1; init_cursors();
return 1;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void* mfb_open(const char* title, int width, int height, unsigned int flags, int scale) void* mfb_open(const char* title, int width, int height, unsigned int flags, int scale)
{ {
XSetWindowAttributes windowAttributes; XSetWindowAttributes windowAttributes;
XSizeHints sizeHints; XSizeHints sizeHints;
XImage* image; XImage* image;
Window window; Window window;
WindowInfo* window_info; WindowInfo* window_info;
if (!setup_display()) { if (!setup_display()) {
return 0; return 0;
} }
//TODO: Handle no title/borderless //TODO: Handle no title/borderless
(void)flags; (void)flags;
width *= scale; width *= scale;
height *= scale; height *= scale;
Window defaultRootWindow = DefaultRootWindow(s_display); Window defaultRootWindow = DefaultRootWindow(s_display);
windowAttributes.border_pixel = BlackPixel(s_display, s_screen); windowAttributes.border_pixel = BlackPixel(s_display, s_screen);
windowAttributes.background_pixel = BlackPixel(s_display, s_screen); windowAttributes.background_pixel = BlackPixel(s_display, s_screen);
windowAttributes.backing_store = NotUseful; windowAttributes.backing_store = NotUseful;
window = XCreateWindow(s_display, defaultRootWindow, (s_screen_width - width) / 2, window = XCreateWindow(s_display, defaultRootWindow, (s_screen_width - width) / 2,
(s_screen_height - height) / 2, width, height, 0, s_depth, InputOutput, (s_screen_height - height) / 2, width, height, 0, s_depth, InputOutput,
s_visual, CWBackPixel | CWBorderPixel | CWBackingStore, s_visual, CWBackPixel | CWBorderPixel | CWBackingStore,
&windowAttributes); &windowAttributes);
if (!window) { if (!window) {
printf("Unable to create X11 Window\n"); printf("Unable to create X11 Window\n");
return 0; return 0;
} }
//XSelectInput(s_display, s_window, KeyPressMask | KeyReleaseMask); //XSelectInput(s_display, s_window, KeyPressMask | KeyReleaseMask);
XStoreName(s_display, window, title); XStoreName(s_display, window, title);
XSelectInput(s_display, window, XSelectInput(s_display, window,
StructureNotifyMask | StructureNotifyMask |
ButtonPressMask | KeyPressMask | KeyReleaseMask | ButtonReleaseMask); ButtonPressMask | KeyPressMask | KeyReleaseMask | ButtonReleaseMask);
if (!(flags & WINDOW_RESIZE)) { if (!(flags & WINDOW_RESIZE)) {
sizeHints.flags = PPosition | PMinSize | PMaxSize; sizeHints.flags = PPosition | PMinSize | PMaxSize;
sizeHints.x = 0; sizeHints.x = 0;
sizeHints.y = 0; sizeHints.y = 0;
sizeHints.min_width = width; sizeHints.min_width = width;
sizeHints.max_width = width; sizeHints.max_width = width;
sizeHints.min_height = height; sizeHints.min_height = height;
sizeHints.max_height = height; sizeHints.max_height = height;
XSetWMNormalHints(s_display, window, &sizeHints); XSetWMNormalHints(s_display, window, &sizeHints);
} }
XClearWindow(s_display, window); XClearWindow(s_display, window);
XMapRaised(s_display, window); XMapRaised(s_display, window);
XFlush(s_display); XFlush(s_display);
image = XCreateImage(s_display, CopyFromParent, s_depth, ZPixmap, 0, NULL, width, height, 32, width * 4); image = XCreateImage(s_display, CopyFromParent, s_depth, ZPixmap, 0, NULL, width, height, 32, width * 4);
if (!image) { if (!image) {
XDestroyWindow(s_display, window); XDestroyWindow(s_display, window);
printf("Unable to create XImage\n"); printf("Unable to create XImage\n");
return 0; return 0;
} }
window_info = (WindowInfo*)malloc(sizeof(WindowInfo)); window_info = (WindowInfo*)malloc(sizeof(WindowInfo));
window_info->key_callback = 0; window_info->key_callback = 0;
window_info->rust_data = 0; window_info->rust_data = 0;
window_info->window = window; window_info->window = window;
window_info->ximage = image; window_info->ximage = image;
window_info->scale = scale; window_info->scale = scale;
window_info->width = width; window_info->width = width;
window_info->height = height; window_info->height = height;
window_info->draw_buffer = malloc(width * height * 4); window_info->draw_buffer = malloc(width * height * 4);
window_info->update = 1; window_info->update = 1;
XSetWMProtocols(s_display, window, &s_wm_delete_window, 1); XSetWMProtocols(s_display, window, &s_wm_delete_window, 1);
XSaveContext(s_display, window, s_context, (XPointer) window_info); XSaveContext(s_display, window, s_context, (XPointer) window_info);
image->data = (char*)window_info->draw_buffer; image->data = (char*)window_info->draw_buffer;
s_window_count += 1; s_window_count += 1;
return (void*)window_info; return (void*)window_info;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_title(void* window_info, const char* title)
{
WindowInfo* info = (WindowInfo*)window_info;
XStoreName(s_display, info->window, title);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -218,296 +258,315 @@ static WindowInfo* find_handle(Window handle)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int process_event(XEvent* event) { void mfb_set_cursor_style(void* window_info, int cursor)
KeySym sym; {
WindowInfo* info = (WindowInfo*)window_info;
WindowInfo* info = find_handle(event->xany.window); if (info->prev_cursor == cursor)
return;
if (!info) if (cursor < 0 || cursor >= CursorStyle_Count) {
return 1; printf("cursor out of range %d\n", cursor);
return;
if (event->type == ClientMessage) {
if ((Atom)event->xclient.data.l[0] == s_wm_delete_window) {
info->update = 0;
mfb_close(info);
return 0;
}
} }
switch (event->type) XDefineCursor(s_display, info->window, s_cursors[cursor]);
{
case KeyPress:
{
sym = XLookupKeysym(&event->xkey, 0);
if (info->key_callback) info->prev_cursor = cursor;
info->key_callback(info->rust_data, sym, 1); }
break; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
case KeyRelease: static int process_event(XEvent* event) {
{ KeySym sym;
sym = XLookupKeysym(&event->xkey, 0);
if (info->key_callback) WindowInfo* info = find_handle(event->xany.window);
info->key_callback(info->rust_data, sym, 0);
break;
}
case ButtonPress: if (!info)
return 1;
if (event->type == ClientMessage) {
if ((Atom)event->xclient.data.l[0] == s_wm_delete_window) {
info->update = 0;
mfb_close(info);
return 0;
}
}
switch (event->type)
{
case KeyPress:
{ {
if (!info->shared_data) sym = XLookupKeysym(&event->xkey, 0);
break;
if (info->key_callback)
info->key_callback(info->rust_data, sym, 1);
break;
}
case KeyRelease:
{
sym = XLookupKeysym(&event->xkey, 0);
if (info->key_callback)
info->key_callback(info->rust_data, sym, 0);
break;
}
case ButtonPress:
{
if (!info->shared_data)
break;
if (event->xbutton.button == Button1) if (event->xbutton.button == Button1)
info->shared_data->state[0] = 1; info->shared_data->state[0] = 1;
else if (event->xbutton.button == Button2) else if (event->xbutton.button == Button2)
info->shared_data->state[1] = 1; info->shared_data->state[1] = 1;
else if (event->xbutton.button == Button3) else if (event->xbutton.button == Button3)
info->shared_data->state[2] = 1; info->shared_data->state[2] = 1;
else if (event->xbutton.button == Button4) else if (event->xbutton.button == Button4)
info->shared_data->scroll_y = 10.0f; info->shared_data->scroll_y = 10.0f;
else if (event->xbutton.button == Button5) else if (event->xbutton.button == Button5)
info->shared_data->scroll_y = -10.0f; info->shared_data->scroll_y = -10.0f;
else if (event->xbutton.button == Button6) else if (event->xbutton.button == Button6)
info->shared_data->scroll_x = 10.0f; info->shared_data->scroll_x = 10.0f;
else if (event->xbutton.button == Button7) else if (event->xbutton.button == Button7)
info->shared_data->scroll_y = -10.0f; info->shared_data->scroll_y = -10.0f;
break; break;
} }
case ButtonRelease: case ButtonRelease:
{ {
if (!info->shared_data) if (!info->shared_data)
break; break;
if (event->xbutton.button == Button1) if (event->xbutton.button == Button1)
info->shared_data->state[0] = 0; info->shared_data->state[0] = 0;
else if (event->xbutton.button == Button2) else if (event->xbutton.button == Button2)
info->shared_data->state[1] = 0; info->shared_data->state[1] = 0;
else if (event->xbutton.button == Button3) else if (event->xbutton.button == Button3)
info->shared_data->state[2] = 0; info->shared_data->state[2] = 0;
break; break;
} }
case ConfigureNotify: case ConfigureNotify:
{ {
info->width = event->xconfigure.width; info->width = event->xconfigure.width;
info->height = event->xconfigure.height; info->height = event->xconfigure.height;
break; break;
} }
} }
return 1; return 1;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void get_mouse_pos(WindowInfo* info) { static void get_mouse_pos(WindowInfo* info) {
Window root, child; Window root, child;
int rootX, rootY, childX, childY; int rootX, rootY, childX, childY;
unsigned int mask; unsigned int mask;
XQueryPointer(s_display, info->window, XQueryPointer(s_display, info->window,
&root, &child, &root, &child,
&rootX, &rootY, &childX, &childY, &rootX, &rootY, &childX, &childY,
&mask); &mask);
if (info->shared_data) { if (info->shared_data) {
info->shared_data->mouse_x = (float)childX; info->shared_data->mouse_x = (float)childX;
info->shared_data->mouse_y = (float)childY; info->shared_data->mouse_y = (float)childY;
} }
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int process_events() static int process_events()
{ {
int count; int count;
XEvent event; XEvent event;
KeySym sym; KeySym sym;
count = XPending(s_display); count = XPending(s_display);
while (count--) while (count--)
{ {
XEvent event; XEvent event;
XNextEvent(s_display, &event); XNextEvent(s_display, &event);
// Don't process any more messages if event is 0 // Don't process any more messages if event is 0
if (process_event(&event) == 0) if (process_event(&event) == 0)
return 0; return 0;
} }
return 0; return 0;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void scale_2x(unsigned int* dest, unsigned int* source, int width, int height, int scale) { static void scale_2x(unsigned int* dest, unsigned int* source, int width, int height, int scale) {
int x, y; int x, y;
for (y = 0; y < height; y += scale) { for (y = 0; y < height; y += scale) {
for (x = 0; x < width; x += scale) { for (x = 0; x < width; x += scale) {
const unsigned int t = *source++; const unsigned int t = *source++;
dest[0] = t; dest[0] = t;
dest[1] = t; dest[1] = t;
dest[width + 0] = t; dest[width + 0] = t;
dest[width + 1] = t; dest[width + 1] = t;
dest += scale; dest += scale;
} }
dest += width * (scale - 1); dest += width * (scale - 1);
} }
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void scale_4x(unsigned int* dest, unsigned int* source, int width, int height, int scale) { static void scale_4x(unsigned int* dest, unsigned int* source, int width, int height, int scale) {
int x, y; int x, y;
for (y = 0; y < height; y += scale) { for (y = 0; y < height; y += scale) {
for (x = 0; x < width; x += scale) { for (x = 0; x < width; x += scale) {
const unsigned int t = *source++; const unsigned int t = *source++;
dest[(width * 0) + 0] = t; dest[(width * 0) + 0] = t;
dest[(width * 0) + 1] = t; dest[(width * 0) + 1] = t;
dest[(width * 0) + 2] = t; dest[(width * 0) + 2] = t;
dest[(width * 0) + 3] = t; dest[(width * 0) + 3] = t;
dest[(width * 1) + 0] = t; dest[(width * 1) + 0] = t;
dest[(width * 1) + 1] = t; dest[(width * 1) + 1] = t;
dest[(width * 1) + 2] = t; dest[(width * 1) + 2] = t;
dest[(width * 1) + 3] = t; dest[(width * 1) + 3] = t;
dest[(width * 2) + 0] = t; dest[(width * 2) + 0] = t;
dest[(width * 2) + 1] = t; dest[(width * 2) + 1] = t;
dest[(width * 2) + 2] = t; dest[(width * 2) + 2] = t;
dest[(width * 2) + 3] = t; dest[(width * 2) + 3] = t;
dest[(width * 3) + 0] = t; dest[(width * 3) + 0] = t;
dest[(width * 3) + 1] = t; dest[(width * 3) + 1] = t;
dest[(width * 3) + 2] = t; dest[(width * 3) + 2] = t;
dest[(width * 3) + 3] = t; dest[(width * 3) + 3] = t;
dest += scale; dest += scale;
} }
dest += width * (scale - 1); dest += width * (scale - 1);
} }
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_update_with_buffer(void* window_info, void* buffer) void mfb_update_with_buffer(void* window_info, void* buffer)
{ {
WindowInfo* info = (WindowInfo*)window_info; WindowInfo* info = (WindowInfo*)window_info;
int width = info->width; int width = info->width;
int height = info->height; int height = info->height;
int scale = info->scale; int scale = info->scale;
if (info->update && buffer) { if (info->update && buffer) {
switch (scale) { switch (scale) {
case 1: { case 1: {
memcpy(info->draw_buffer, buffer, width * height * 4); memcpy(info->draw_buffer, buffer, width * height * 4);
break; break;
} }
case 2: { case 2: {
scale_2x(info->draw_buffer, buffer, width, height, scale); scale_2x(info->draw_buffer, buffer, width, height, scale);
break; break;
} }
case 4: { case 4: {
scale_4x(info->draw_buffer, buffer, width, height, scale); scale_4x(info->draw_buffer, buffer, width, height, scale);
break; break;
} }
} }
XPutImage(s_display, info->window, s_gc, info->ximage, 0, 0, 0, 0, width, height); XPutImage(s_display, info->window, s_gc, info->ximage, 0, 0, 0, 0, width, height);
XFlush(s_display); XFlush(s_display);
} }
// clear before processing new events // clear before processing new events
if (info->shared_data) { if (info->shared_data) {
info->shared_data->scroll_x = 0.0f; info->shared_data->scroll_x = 0.0f;
info->shared_data->scroll_y = 0.0f; info->shared_data->scroll_y = 0.0f;
} }
get_mouse_pos(info); get_mouse_pos(info);
process_events(); process_events();
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_update(void* window_info, void* buffer) void mfb_update(void* window_info, void* buffer)
{ {
mfb_update_with_buffer(window_info, 0); mfb_update_with_buffer(window_info, 0);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_position(void* window, int x, int y) void mfb_set_position(void* window, int x, int y)
{ {
WindowInfo* info = (WindowInfo*)window; WindowInfo* info = (WindowInfo*)window;
XMoveWindow(s_display, info->window, x, y); XMoveWindow(s_display, info->window, x, y);
XFlush(s_display); XFlush(s_display);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_close(void* window_info) void mfb_close(void* window_info)
{ {
WindowInfo* info = (WindowInfo*)window_info; WindowInfo* info = (WindowInfo*)window_info;
if (!info->draw_buffer) if (!info->draw_buffer)
return; return;
XSaveContext(s_display, info->window, s_context, (XPointer)0); XSaveContext(s_display, info->window, s_context, (XPointer)0);
free(info->draw_buffer); free(info->draw_buffer);
info->ximage->data = NULL; info->ximage->data = NULL;
info->draw_buffer = 0; info->draw_buffer = 0;
XDestroyImage(info->ximage); XDestroyImage(info->ximage);
XDestroyWindow(s_display, info->window); XDestroyWindow(s_display, info->window);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_key_callback(void* window, void* rust_data, void (*key_callback)(void* user_data, int key, int state)) void mfb_set_key_callback(void* window, void* rust_data, void (*key_callback)(void* user_data, int key, int state))
{ {
WindowInfo* win = (WindowInfo*)window; WindowInfo* win = (WindowInfo*)window;
win->key_callback = key_callback; win->key_callback = key_callback;
win->rust_data = rust_data; win->rust_data = rust_data;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_shared_data(void* window, SharedData* data) void mfb_set_shared_data(void* window, SharedData* data)
{ {
WindowInfo* win = (WindowInfo*)window; WindowInfo* win = (WindowInfo*)window;
win->shared_data = data; win->shared_data = data;
win->shared_data->width = win->width; win->shared_data->width = win->width;
win->shared_data->height = win->height; win->shared_data->height = win->height;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int mfb_should_close(void* window) { int mfb_should_close(void* window) {
WindowInfo* win = (WindowInfo*)window; WindowInfo* win = (WindowInfo*)window;
return !!win->update; return !!win->update;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned int mfb_get_screen_size() { unsigned int mfb_get_screen_size() {
setup_display(); setup_display();
return (s_screen_width << 16) | s_screen_height; return (s_screen_width << 16) | s_screen_height;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void* mfb_get_window_handle(void* window) { void* mfb_get_window_handle(void* window) {
WindowInfo* win = (WindowInfo*)window; WindowInfo* win = (WindowInfo*)window;
return (void*)(uintptr_t)win->window; return (void*)(uintptr_t)win->window;
} }

View file

@ -8,10 +8,10 @@ use Result;
use InputCallback; use InputCallback;
use mouse_handler; use mouse_handler;
use window_flags; use window_flags;
use {MenuItem, MenuItemHandle, MenuHandle}; use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle};
// use menu::Menu; // use menu::Menu;
use libc::{c_void, c_char, c_uchar}; use std::os::raw::{c_void, c_char, c_uchar};
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr;
use std::mem; use std::mem;
@ -159,6 +159,7 @@ extern "C" {
flags: u32, flags: u32,
scale: i32) scale: i32)
-> *mut c_void; -> *mut c_void;
fn mfb_set_title(window: *mut c_void, title: *const c_char);
fn mfb_close(window: *mut c_void); fn mfb_close(window: *mut c_void);
fn mfb_update(window: *mut c_void); fn mfb_update(window: *mut c_void);
fn mfb_update_with_buffer(window: *mut c_void, buffer: *const c_uchar); fn mfb_update_with_buffer(window: *mut c_void, buffer: *const c_uchar);
@ -168,6 +169,7 @@ extern "C" {
cb: unsafe extern "C" fn(*mut c_void, i32, i32), cb: unsafe extern "C" fn(*mut c_void, i32, i32),
cb: unsafe extern "C" fn(*mut c_void, u32)); cb: unsafe extern "C" fn(*mut c_void, u32));
fn mfb_set_mouse_data(window_handle: *mut c_void, shared_data: *mut SharedData); fn mfb_set_mouse_data(window_handle: *mut c_void, shared_data: *mut SharedData);
fn mfb_set_cursor_style(window: *mut c_void, cursor: u32);
fn mfb_should_close(window: *mut c_void) -> i32; fn mfb_should_close(window: *mut c_void) -> i32;
fn mfb_get_screen_size() -> u32; fn mfb_get_screen_size() -> u32;
fn mfb_is_active(window: *mut c_void) -> u32; fn mfb_is_active(window: *mut c_void) -> u32;
@ -271,6 +273,14 @@ impl Window {
} }
} }
#[inline]
pub fn set_title(&mut self, title: &str) {
unsafe {
let t = CString::new(title).unwrap();
mfb_set_title(self.window_handle, t.as_ptr());
}
}
#[inline] #[inline]
pub fn get_window_handle(&self) -> *mut raw::c_void { pub fn get_window_handle(&self) -> *mut raw::c_void {
self.window_handle as *mut raw::c_void self.window_handle as *mut raw::c_void
@ -349,6 +359,13 @@ impl Window {
h) h)
} }
#[inline]
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
unsafe {
mfb_set_cursor_style(self.window_handle, cursor as u32);
}
}
#[inline] #[inline]
pub fn get_keys(&self) -> Option<Vec<Key>> { pub fn get_keys(&self) -> Option<Vec<Key>> {
self.key_handler.get_keys() self.key_handler.get_keys()

View file

@ -8,13 +8,12 @@ extern crate x11_dl;
use {MouseMode, MouseButton, Scale, Key, KeyRepeat, WindowOptions, InputCallback}; use {MouseMode, MouseButton, Scale, Key, KeyRepeat, WindowOptions, InputCallback};
use key_handler::KeyHandler; use key_handler::KeyHandler;
//use menu::Menu;
use self::x11_dl::keysym::*; use self::x11_dl::keysym::*;
use error::Error; use error::Error;
use Result; use Result;
use {MenuItem, MenuItemHandle, MenuHandle, UnixMenu, UnixMenuItem}; use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle, UnixMenu, UnixMenuItem};
use libc::{c_void, c_char, c_uchar}; use std::os::raw::{c_void, c_char, c_uchar};
use std::ffi::{CString}; use std::ffi::{CString};
use std::ptr; use std::ptr;
use std::mem; use std::mem;
@ -23,8 +22,10 @@ use mouse_handler;
use window_flags; use window_flags;
#[link(name = "X11")] #[link(name = "X11")]
#[link(name = "Xcursor")]
extern { extern {
fn mfb_open(name: *const c_char, width: u32, height: u32, flags: u32, scale: i32) -> *mut c_void; fn mfb_open(name: *const c_char, width: u32, height: u32, flags: u32, scale: i32) -> *mut c_void;
fn mfb_set_title(window: *mut c_void, title: *const c_char);
fn mfb_close(window: *mut c_void); fn mfb_close(window: *mut c_void);
fn mfb_update(window: *mut c_void); fn mfb_update(window: *mut c_void);
fn mfb_update_with_buffer(window: *mut c_void, buffer: *const c_uchar); fn mfb_update_with_buffer(window: *mut c_void, buffer: *const c_uchar);
@ -33,6 +34,7 @@ extern {
fn mfb_set_shared_data(window: *mut c_void, target: *mut SharedData); fn mfb_set_shared_data(window: *mut c_void, target: *mut SharedData);
fn mfb_should_close(window: *mut c_void) -> i32; fn mfb_should_close(window: *mut c_void) -> i32;
fn mfb_get_screen_size() -> u32; fn mfb_get_screen_size() -> u32;
fn mfb_set_cursor_style(window: *mut c_void, cursor: u32);
fn mfb_get_window_handle(window: *mut c_void) -> *mut c_void; fn mfb_get_window_handle(window: *mut c_void) -> *mut c_void;
} }
@ -204,6 +206,13 @@ impl Window {
} }
} }
pub fn set_title(&mut self, title: &str) {
unsafe {
let t = CString::new(title).unwrap();
mfb_set_title(self.window_handle, t.as_ptr());
}
}
unsafe fn set_shared_data(&mut self) { unsafe fn set_shared_data(&mut self) {
mfb_set_shared_data(self.window_handle, &mut self.shared_data); mfb_set_shared_data(self.window_handle, &mut self.shared_data);
} }
@ -268,6 +277,13 @@ impl Window {
} }
} }
#[inline]
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
unsafe {
mfb_set_cursor_style(self.window_handle, cursor as u32);
}
}
#[inline] #[inline]
pub fn get_keys(&self) -> Option<Vec<Key>> { pub fn get_keys(&self) -> Option<Vec<Key>> {
self.key_handler.get_keys() self.key_handler.get_keys()
@ -388,7 +404,7 @@ pub struct Menu {
impl Menu { impl Menu {
pub fn new(name: &str) -> Result<Menu> { pub fn new(name: &str) -> Result<Menu> {
Ok(Menu { Ok(Menu {
internal: UnixMenu { internal: UnixMenu {
handle: MenuHandle(0), handle: MenuHandle(0),
item_counter: MenuItemHandle(0), item_counter: MenuItemHandle(0),

View file

@ -12,7 +12,7 @@ use {Scale, Key, KeyRepeat, MouseButton, MouseMode, WindowOptions, InputCallback
use key_handler::KeyHandler; use key_handler::KeyHandler;
use error::Error; use error::Error;
use Result; use Result;
use {MenuItem, MenuItemHandle, MenuHandle}; use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle};
use {MENU_KEY_WIN, MENU_KEY_SHIFT, MENU_KEY_CTRL, MENU_KEY_ALT}; use {MENU_KEY_WIN, MENU_KEY_SHIFT, MENU_KEY_CTRL, MENU_KEY_ALT};
use std::ptr; use std::ptr;
@ -331,6 +331,8 @@ pub struct Window {
key_handler: KeyHandler, key_handler: KeyHandler,
accel_table: HACCEL, accel_table: HACCEL,
accel_key: usize, accel_key: usize,
prev_cursor: CursorStyle,
cursors: [winapi::HCURSOR; 8],
} }
// TranslateAccelerator is currently missing in win-rs // TranslateAccelerator is currently missing in win-rs
@ -454,12 +456,31 @@ impl Window {
menus: Vec::new(), menus: Vec::new(),
accel_table: ptr::null_mut(), accel_table: ptr::null_mut(),
accel_key: INVALID_ACCEL, accel_key: INVALID_ACCEL,
prev_cursor: CursorStyle::Arrow,
cursors: [
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_ARROW),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_IBEAM),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_CROSS),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_HAND),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_HAND),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_SIZENS),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_SIZEWE),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_SIZEALL),
],
}; };
Ok(window) Ok(window)
} }
} }
#[inline]
pub fn set_title(&mut self, title: &str) {
unsafe {
let title_name = to_wstring(title);
user32::SetWindowTextW(self.window.unwrap(), title_name.as_ptr());
}
}
#[inline] #[inline]
pub fn get_window_handle(&self) -> *mut raw::c_void { pub fn get_window_handle(&self) -> *mut raw::c_void {
self.window.unwrap() as *mut raw::c_void self.window.unwrap() as *mut raw::c_void
@ -503,6 +524,19 @@ impl Window {
} }
} }
#[inline]
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
unsafe {
if self.prev_cursor == cursor {
return;
}
user32::SetCursor(self.cursors[cursor as usize]);
self.prev_cursor = cursor;
}
}
#[inline] #[inline]
pub fn get_keys(&self) -> Option<Vec<Key>> { pub fn get_keys(&self) -> Option<Vec<Key>> {
self.key_handler.get_keys() self.key_handler.get_keys()
@ -538,7 +572,6 @@ impl Window {
self.key_handler.is_key_pressed(key, repeat) self.key_handler.is_key_pressed(key, repeat)
} }
#[inline] #[inline]
pub fn is_open(&self) -> bool { pub fn is_open(&self) -> bool {
return self.is_open return self.is_open
@ -675,7 +708,7 @@ impl Window {
println!("accel {:?}", self.accel_table); println!("accel {:?}", self.accel_table);
} }
pub fn add_menu(&mut self, menu: &Menu) -> MenuHandle { pub fn add_menu(&mut self, menu: &Menu) -> MenuHandle {
unsafe { unsafe {
let window = self.window.unwrap(); let window = self.window.unwrap();
@ -687,9 +720,9 @@ impl Window {
Self::adjust_window_size_for_menu(window); Self::adjust_window_size_for_menu(window);
} }
user32::AppendMenuW(main_menu, user32::AppendMenuW(main_menu,
0x10, 0x10,
menu.menu_handle as UINT_PTR, menu.menu_handle as UINT_PTR,
menu.name.as_ptr()); menu.name.as_ptr());
self.menus.push(menu.clone()); self.menus.push(menu.clone());
@ -702,7 +735,7 @@ impl Window {
} }
// TODO: Proper handle // TODO: Proper handle
MenuHandle(menu.menu_handle as u64) MenuHandle(menu.menu_handle as u64)
} }
@ -867,9 +900,9 @@ impl Menu {
pub fn add_sub_menu(&mut self, name: &str, menu: &Menu) { pub fn add_sub_menu(&mut self, name: &str, menu: &Menu) {
unsafe { unsafe {
let menu_name = to_wstring(name); let menu_name = to_wstring(name);
user32::AppendMenuW(self.menu_handle, user32::AppendMenuW(self.menu_handle,
0x10, 0x10,
menu.menu_handle as UINT_PTR, menu.menu_handle as UINT_PTR,
menu_name.as_ptr()); menu_name.as_ptr());
self.accel_table.extend_from_slice(menu.accel_table.as_slice()); self.accel_table.extend_from_slice(menu.accel_table.as_slice());
} }