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"
[dependencies]
libc = "0.2"
time = "0.1.34"
[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
//! buffer. minifb also support keyboard, mouse input and menus on selected operating systems.
//!
extern crate libc;
use std::os::raw;
/// 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)]
pub enum MouseMode {
/// Return mouse coords from outside of the window (may be negative)
@ -62,14 +60,33 @@ pub enum MouseMode {
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
/// whene there is inputs incoming. Currently only support unicode chars.
pub trait InputCallback {
fn add_char(&mut self, uni_char: u32);
}
#[doc(hidden)]
mod error;
pub use self::error::Error;
@ -163,6 +180,21 @@ impl 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
/// dependens on the current operating system:
@ -314,6 +346,20 @@ impl Window {
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.
///
@ -515,7 +561,7 @@ pub struct UnixMenu {
/// Name of the menu
pub name: String,
/// All items of the menu.
pub items: Vec<UnixMenuItem>,
pub items: Vec<UnixMenuItem>,
#[doc(hidden)]
pub handle: MenuHandle,
#[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);
@ -565,24 +611,24 @@ impl Menu {
}
#[inline]
/// Destroys a menu. Currently not implemented
/// Destroys a menu. Currently not implemented
pub fn destroy_menu(&mut self) {
//self.0.destroy_menu()
}
#[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) {
self.0.add_sub_menu(name, &menu.0)
}
/// Adds a menu separator
/// Adds a menu separator
pub fn add_separator(&mut self) {
self.add_menu_item(&MenuItem { id: MENU_ID_SEPARATOR, ..MenuItem::default() });
}
#[inline]
/// Adds an item to the menu
/// Adds an item to the menu
pub fn add_menu_item(&mut self, item: &MenuItem) -> MenuItemHandle {
self.0.add_menu_item(item)
}
@ -604,14 +650,14 @@ impl Menu {
}
#[inline]
/// Removes an item from the menu
/// Removes an item from the menu
pub fn remove_item(&mut self, item: &MenuItemHandle) {
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 id: usize,
@ -640,10 +686,10 @@ impl<'a> Clone for MenuItem<'a> {
fn clone(&self) -> Self {
MenuItem {
id: self.id,
label: self.label.clone(),
label: self.label.clone(),
enabled: self.enabled,
key: self.key,
modifier: self.modifier,
modifier: self.modifier,
menu: None,
}
}
@ -659,7 +705,7 @@ impl<'a> MenuItem<'a> {
}
}
#[inline]
/// Sets a shortcut key and modifer (and returns itself)
/// Sets a shortcut key and modifer (and returns itself)
///
/// # Examples
///
@ -674,7 +720,7 @@ impl<'a> MenuItem<'a> {
}
}
#[inline]
/// Sets item to a separator
/// Sets item to a separator
///
/// # Examples
///
@ -703,7 +749,7 @@ impl<'a> MenuItem<'a> {
}
}
#[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
///

View file

@ -13,6 +13,34 @@ const uint32_t WINDOW_TITLE = 1 << 3;
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__
@ -31,6 +59,7 @@ void* mfb_open(const char* name, int width, int height, uint32_t flags, int scal
[NSApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
create_standard_menu();
cursor_init();
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->shared_data = 0;
window->active_menu_id = -1;
window->prev_cursor = 0;
window->menu_data = malloc(sizeof(MenuData));
memset(window->menu_data, 0, sizeof(MenuData));
@ -195,6 +225,14 @@ static void create_standard_menu(void)
//[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();
@ -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)
{
OSXWindow* win = (OSXWindow*)window;
@ -451,12 +508,12 @@ static NSString* get_string_for_key(uint32_t t) {
uint64_t mfb_add_menu_item(
void* in_menu,
int32_t menu_id,
const char* item_name,
bool enabled,
const char* item_name,
bool enabled,
uint32_t key,
uint32_t modfier)
{
NSMenu* menu = (NSMenu*)in_menu;
NSMenu* menu = (NSMenu*)in_menu;
NSString* name = [NSString stringWithUTF8String: item_name];
@ -517,7 +574,7 @@ uint64_t mfb_add_menu_item(
[newItem setKeyEquivalentModifierMask: mask];
[newItem setKeyEquivalent:key_string];
}
if (enabled) {
[newItem setEnabled:YES];
} 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) {
NSMenu* menu = (NSMenu*)parent;
NSMenuItem* item = (NSMenuItem*)(uintptr_t)menu_item;
NSMenuItem* item = (NSMenuItem*)(uintptr_t)menu_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)
{
OSXWindow* win = (OSXWindow*)window;
NSMenu* menu = (NSMenu*)m;
NSMenu* menu = (NSMenu*)m;
NSMenu* main_menu = [NSApp mainMenu];

View file

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

View file

@ -1,6 +1,7 @@
#include <X11/Xresource.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xcursor/Xcursor.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -34,12 +35,27 @@ static int s_screen_height;
static XContext s_context;
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 {
uint32_t width;
uint32_t height;
float scale;
uint32_t width;
uint32_t height;
float scale;
float mouse_x;
float mouse_y;
float scroll_x;
@ -50,157 +66,181 @@ typedef struct SharedData {
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct WindowInfo {
void (*key_callback)(void* user_data, int key, int state);
void* rust_data;
SharedData* shared_data;
Window window;
XImage* ximage;
void* draw_buffer;
int scale;
int width;
int height;
int update;
void (*key_callback)(void* user_data, int key, int state);
void* rust_data;
SharedData* shared_data;
Window window;
XImage* ximage;
void* draw_buffer;
int scale;
int width;
int height;
int update;
int prev_cursor;
} 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() {
int depth, i, formatCount, convDepth = -1;
XPixmapFormatValues* formats;
int depth, i, formatCount, convDepth = -1;
XPixmapFormatValues* formats;
if (s_setup_done) {
return 1;
}
if (s_setup_done) {
return 1;
}
s_display = XOpenDisplay(0);
s_display = XOpenDisplay(0);
if (!s_display) {
printf("Unable to open X11 display\n");
return 0;
}
if (!s_display) {
printf("Unable to open X11 display\n");
return 0;
}
s_context = XUniqueContext();
s_screen = DefaultScreen(s_display);
s_visual = DefaultVisual(s_display, s_screen);
formats = XListPixmapFormats(s_display, &formatCount);
depth = DefaultDepth(s_display, s_screen);
s_context = XUniqueContext();
s_screen = DefaultScreen(s_display);
s_visual = DefaultVisual(s_display, s_screen);
formats = XListPixmapFormats(s_display, &formatCount);
depth = DefaultDepth(s_display, s_screen);
for (i = 0; i < formatCount; ++i) {
if (depth == formats[i].depth) {
convDepth = formats[i].bits_per_pixel;
break;
}
}
for (i = 0; i < formatCount; ++i) {
if (depth == formats[i].depth) {
convDepth = formats[i].bits_per_pixel;
break;
}
}
XFree(formats);
XFree(formats);
// We only support 32-bit right now
if (convDepth != 32) {
printf("Unable to find 32-bit format for X11 display\n");
XCloseDisplay(s_display);
return 0;
}
// We only support 32-bit right now
if (convDepth != 32) {
printf("Unable to find 32-bit format for X11 display\n");
XCloseDisplay(s_display);
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_height = DisplayHeight(s_display, s_screen);
s_screen_width = DisplayWidth(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);
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)
{
XSetWindowAttributes windowAttributes;
XSizeHints sizeHints;
XImage* image;
Window window;
WindowInfo* window_info;
XSetWindowAttributes windowAttributes;
XSizeHints sizeHints;
XImage* image;
Window window;
WindowInfo* window_info;
if (!setup_display()) {
return 0;
}
if (!setup_display()) {
return 0;
}
//TODO: Handle no title/borderless
(void)flags;
//TODO: Handle no title/borderless
(void)flags;
width *= scale;
height *= scale;
width *= scale;
height *= scale;
Window defaultRootWindow = DefaultRootWindow(s_display);
Window defaultRootWindow = DefaultRootWindow(s_display);
windowAttributes.border_pixel = BlackPixel(s_display, s_screen);
windowAttributes.background_pixel = BlackPixel(s_display, s_screen);
windowAttributes.backing_store = NotUseful;
windowAttributes.border_pixel = BlackPixel(s_display, s_screen);
windowAttributes.background_pixel = BlackPixel(s_display, s_screen);
windowAttributes.backing_store = NotUseful;
window = XCreateWindow(s_display, defaultRootWindow, (s_screen_width - width) / 2,
(s_screen_height - height) / 2, width, height, 0, s_depth, InputOutput,
s_visual, CWBackPixel | CWBorderPixel | CWBackingStore,
&windowAttributes);
if (!window) {
printf("Unable to create X11 Window\n");
return 0;
}
window = XCreateWindow(s_display, defaultRootWindow, (s_screen_width - width) / 2,
(s_screen_height - height) / 2, width, height, 0, s_depth, InputOutput,
s_visual, CWBackPixel | CWBorderPixel | CWBackingStore,
&windowAttributes);
if (!window) {
printf("Unable to create X11 Window\n");
return 0;
}
//XSelectInput(s_display, s_window, KeyPressMask | KeyReleaseMask);
XStoreName(s_display, window, title);
//XSelectInput(s_display, s_window, KeyPressMask | KeyReleaseMask);
XStoreName(s_display, window, title);
XSelectInput(s_display, window,
StructureNotifyMask |
ButtonPressMask | KeyPressMask | KeyReleaseMask | ButtonReleaseMask);
XSelectInput(s_display, window,
StructureNotifyMask |
ButtonPressMask | KeyPressMask | KeyReleaseMask | ButtonReleaseMask);
if (!(flags & WINDOW_RESIZE)) {
sizeHints.flags = PPosition | PMinSize | PMaxSize;
sizeHints.x = 0;
sizeHints.y = 0;
sizeHints.min_width = width;
sizeHints.max_width = width;
sizeHints.min_height = height;
sizeHints.max_height = height;
XSetWMNormalHints(s_display, window, &sizeHints);
}
if (!(flags & WINDOW_RESIZE)) {
sizeHints.flags = PPosition | PMinSize | PMaxSize;
sizeHints.x = 0;
sizeHints.y = 0;
sizeHints.min_width = width;
sizeHints.max_width = width;
sizeHints.min_height = height;
sizeHints.max_height = height;
XSetWMNormalHints(s_display, window, &sizeHints);
}
XClearWindow(s_display, window);
XMapRaised(s_display, window);
XFlush(s_display);
XClearWindow(s_display, window);
XMapRaised(s_display, window);
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) {
XDestroyWindow(s_display, window);
printf("Unable to create XImage\n");
return 0;
}
if (!image) {
XDestroyWindow(s_display, window);
printf("Unable to create XImage\n");
return 0;
}
window_info = (WindowInfo*)malloc(sizeof(WindowInfo));
window_info->key_callback = 0;
window_info->rust_data = 0;
window_info->window = window;
window_info->ximage = image;
window_info->scale = scale;
window_info->width = width;
window_info->height = height;
window_info->draw_buffer = malloc(width * height * 4);
window_info->update = 1;
window_info = (WindowInfo*)malloc(sizeof(WindowInfo));
window_info->key_callback = 0;
window_info->rust_data = 0;
window_info->window = window;
window_info->ximage = image;
window_info->scale = scale;
window_info->width = width;
window_info->height = height;
window_info->draw_buffer = malloc(width * height * 4);
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) {
KeySym sym;
void mfb_set_cursor_style(void* window_info, int cursor)
{
WindowInfo* info = (WindowInfo*)window_info;
WindowInfo* info = find_handle(event->xany.window);
if (info->prev_cursor == cursor)
return;
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;
}
if (cursor < 0 || cursor >= CursorStyle_Count) {
printf("cursor out of range %d\n", cursor);
return;
}
switch (event->type)
{
case KeyPress:
{
sym = XLookupKeysym(&event->xkey, 0);
XDefineCursor(s_display, info->window, s_cursors[cursor]);
if (info->key_callback)
info->key_callback(info->rust_data, sym, 1);
info->prev_cursor = cursor;
}
break;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
case KeyRelease:
{
sym = XLookupKeysym(&event->xkey, 0);
static int process_event(XEvent* event) {
KeySym sym;
if (info->key_callback)
info->key_callback(info->rust_data, sym, 0);
break;
}
WindowInfo* info = find_handle(event->xany.window);
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)
break;
sym = XLookupKeysym(&event->xkey, 0);
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)
info->shared_data->state[0] = 1;
info->shared_data->state[0] = 1;
else if (event->xbutton.button == Button2)
info->shared_data->state[1] = 1;
info->shared_data->state[1] = 1;
else if (event->xbutton.button == Button3)
info->shared_data->state[2] = 1;
info->shared_data->state[2] = 1;
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)
info->shared_data->scroll_y = -10.0f;
info->shared_data->scroll_y = -10.0f;
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)
info->shared_data->scroll_y = -10.0f;
info->shared_data->scroll_y = -10.0f;
break;
}
}
case ButtonRelease:
case ButtonRelease:
{
if (!info->shared_data)
break;
if (!info->shared_data)
break;
if (event->xbutton.button == Button1)
info->shared_data->state[0] = 0;
info->shared_data->state[0] = 0;
else if (event->xbutton.button == Button2)
info->shared_data->state[1] = 0;
info->shared_data->state[1] = 0;
else if (event->xbutton.button == Button3)
info->shared_data->state[2] = 0;
info->shared_data->state[2] = 0;
break;
}
}
case ConfigureNotify:
{
info->width = event->xconfigure.width;
info->height = event->xconfigure.height;
break;
info->width = event->xconfigure.width;
info->height = event->xconfigure.height;
break;
}
}
}
return 1;
return 1;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void get_mouse_pos(WindowInfo* info) {
Window root, child;
int rootX, rootY, childX, childY;
unsigned int mask;
Window root, child;
int rootX, rootY, childX, childY;
unsigned int mask;
XQueryPointer(s_display, info->window,
&root, &child,
&rootX, &rootY, &childX, &childY,
&mask);
XQueryPointer(s_display, info->window,
&root, &child,
&rootX, &rootY, &childX, &childY,
&mask);
if (info->shared_data) {
info->shared_data->mouse_x = (float)childX;
info->shared_data->mouse_y = (float)childY;
}
if (info->shared_data) {
info->shared_data->mouse_x = (float)childX;
info->shared_data->mouse_y = (float)childY;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int process_events()
{
int count;
XEvent event;
KeySym sym;
int count;
XEvent event;
KeySym sym;
count = XPending(s_display);
count = XPending(s_display);
while (count--)
{
XEvent 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)
return 0;
return 0;
}
return 0;
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void scale_2x(unsigned int* dest, unsigned int* source, int width, int height, int scale) {
int x, y;
for (y = 0; y < height; y += scale) {
for (x = 0; x < width; x += scale) {
const unsigned int t = *source++;
dest[0] = t;
dest[1] = t;
dest[width + 0] = t;
dest[width + 1] = t;
dest += scale;
}
int x, y;
for (y = 0; y < height; y += scale) {
for (x = 0; x < width; x += scale) {
const unsigned int t = *source++;
dest[0] = t;
dest[1] = t;
dest[width + 0] = t;
dest[width + 1] = t;
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) {
int x, y;
for (y = 0; y < height; y += scale) {
for (x = 0; x < width; x += scale) {
const unsigned int t = *source++;
dest[(width * 0) + 0] = t;
dest[(width * 0) + 1] = t;
dest[(width * 0) + 2] = t;
dest[(width * 0) + 3] = t;
dest[(width * 1) + 0] = t;
dest[(width * 1) + 1] = t;
dest[(width * 1) + 2] = t;
dest[(width * 1) + 3] = t;
dest[(width * 2) + 0] = t;
dest[(width * 2) + 1] = t;
dest[(width * 2) + 2] = t;
dest[(width * 2) + 3] = t;
dest[(width * 3) + 0] = t;
dest[(width * 3) + 1] = t;
dest[(width * 3) + 2] = t;
dest[(width * 3) + 3] = t;
dest += scale;
}
int x, y;
for (y = 0; y < height; y += scale) {
for (x = 0; x < width; x += scale) {
const unsigned int t = *source++;
dest[(width * 0) + 0] = t;
dest[(width * 0) + 1] = t;
dest[(width * 0) + 2] = t;
dest[(width * 0) + 3] = t;
dest[(width * 1) + 0] = t;
dest[(width * 1) + 1] = t;
dest[(width * 1) + 2] = t;
dest[(width * 1) + 3] = t;
dest[(width * 2) + 0] = t;
dest[(width * 2) + 1] = t;
dest[(width * 2) + 2] = t;
dest[(width * 2) + 3] = t;
dest[(width * 3) + 0] = t;
dest[(width * 3) + 1] = t;
dest[(width * 3) + 2] = t;
dest[(width * 3) + 3] = t;
dest += scale;
}
dest += width * (scale - 1);
}
dest += width * (scale - 1);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_update_with_buffer(void* window_info, void* buffer)
{
WindowInfo* info = (WindowInfo*)window_info;
int width = info->width;
int height = info->height;
int scale = info->scale;
WindowInfo* info = (WindowInfo*)window_info;
int width = info->width;
int height = info->height;
int scale = info->scale;
if (info->update && buffer) {
switch (scale) {
case 1: {
memcpy(info->draw_buffer, buffer, width * height * 4);
break;
}
case 2: {
scale_2x(info->draw_buffer, buffer, width, height, scale);
break;
}
if (info->update && buffer) {
switch (scale) {
case 1: {
memcpy(info->draw_buffer, buffer, width * height * 4);
break;
}
case 2: {
scale_2x(info->draw_buffer, buffer, width, height, scale);
break;
}
case 4: {
scale_4x(info->draw_buffer, buffer, width, height, scale);
break;
}
}
case 4: {
scale_4x(info->draw_buffer, buffer, width, height, scale);
break;
}
}
XPutImage(s_display, info->window, s_gc, info->ximage, 0, 0, 0, 0, width, height);
XFlush(s_display);
}
XPutImage(s_display, info->window, s_gc, info->ximage, 0, 0, 0, 0, width, height);
XFlush(s_display);
}
// clear before processing new events
// clear before processing new events
if (info->shared_data) {
info->shared_data->scroll_x = 0.0f;
info->shared_data->scroll_y = 0.0f;
}
if (info->shared_data) {
info->shared_data->scroll_x = 0.0f;
info->shared_data->scroll_y = 0.0f;
}
get_mouse_pos(info);
process_events();
get_mouse_pos(info);
process_events();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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)
{
WindowInfo* info = (WindowInfo*)window;
WindowInfo* info = (WindowInfo*)window;
XMoveWindow(s_display, info->window, x, y);
XFlush(s_display);
XFlush(s_display);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_close(void* window_info)
{
WindowInfo* info = (WindowInfo*)window_info;
WindowInfo* info = (WindowInfo*)window_info;
if (!info->draw_buffer)
return;
if (!info->draw_buffer)
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->draw_buffer = 0;
info->ximage->data = NULL;
info->draw_buffer = 0;
XDestroyImage(info->ximage);
XDestroyWindow(s_display, info->window);
XDestroyImage(info->ximage);
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))
{
WindowInfo* win = (WindowInfo*)window;
win->key_callback = key_callback;
win->rust_data = rust_data;
WindowInfo* win = (WindowInfo*)window;
win->key_callback = key_callback;
win->rust_data = rust_data;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_shared_data(void* window, SharedData* data)
{
WindowInfo* win = (WindowInfo*)window;
win->shared_data = data;
win->shared_data->width = win->width;
win->shared_data->height = win->height;
WindowInfo* win = (WindowInfo*)window;
win->shared_data = data;
win->shared_data->width = win->width;
win->shared_data->height = win->height;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int mfb_should_close(void* window) {
WindowInfo* win = (WindowInfo*)window;
return !!win->update;
WindowInfo* win = (WindowInfo*)window;
return !!win->update;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned int mfb_get_screen_size() {
setup_display();
return (s_screen_width << 16) | s_screen_height;
setup_display();
return (s_screen_width << 16) | s_screen_height;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void* mfb_get_window_handle(void* window) {
WindowInfo* win = (WindowInfo*)window;
return (void*)(uintptr_t)win->window;
WindowInfo* win = (WindowInfo*)window;
return (void*)(uintptr_t)win->window;
}

View file

@ -8,10 +8,10 @@ use Result;
use InputCallback;
use mouse_handler;
use window_flags;
use {MenuItem, MenuItemHandle, MenuHandle};
use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle};
// 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::ptr;
use std::mem;
@ -159,6 +159,7 @@ extern "C" {
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_update(window: *mut c_void);
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, u32));
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_get_screen_size() -> 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]
pub fn get_window_handle(&self) -> *mut raw::c_void {
self.window_handle as *mut raw::c_void
@ -349,6 +359,13 @@ impl Window {
h)
}
#[inline]
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
unsafe {
mfb_set_cursor_style(self.window_handle, cursor as u32);
}
}
#[inline]
pub fn get_keys(&self) -> Option<Vec<Key>> {
self.key_handler.get_keys()

View file

@ -8,13 +8,12 @@ extern crate x11_dl;
use {MouseMode, MouseButton, Scale, Key, KeyRepeat, WindowOptions, InputCallback};
use key_handler::KeyHandler;
//use menu::Menu;
use self::x11_dl::keysym::*;
use error::Error;
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::ptr;
use std::mem;
@ -23,8 +22,10 @@ use mouse_handler;
use window_flags;
#[link(name = "X11")]
#[link(name = "Xcursor")]
extern {
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_update(window: *mut c_void);
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_should_close(window: *mut c_void) -> i32;
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;
}
@ -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) {
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]
pub fn get_keys(&self) -> Option<Vec<Key>> {
self.key_handler.get_keys()
@ -388,7 +404,7 @@ pub struct Menu {
impl Menu {
pub fn new(name: &str) -> Result<Menu> {
Ok(Menu {
Ok(Menu {
internal: UnixMenu {
handle: MenuHandle(0),
item_counter: MenuItemHandle(0),

View file

@ -12,7 +12,7 @@ use {Scale, Key, KeyRepeat, MouseButton, MouseMode, WindowOptions, InputCallback
use key_handler::KeyHandler;
use error::Error;
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 std::ptr;
@ -331,6 +331,8 @@ pub struct Window {
key_handler: KeyHandler,
accel_table: HACCEL,
accel_key: usize,
prev_cursor: CursorStyle,
cursors: [winapi::HCURSOR; 8],
}
// TranslateAccelerator is currently missing in win-rs
@ -454,12 +456,31 @@ impl Window {
menus: Vec::new(),
accel_table: ptr::null_mut(),
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)
}
}
#[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]
pub fn get_window_handle(&self) -> *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]
pub fn get_keys(&self) -> Option<Vec<Key>> {
self.key_handler.get_keys()
@ -538,7 +572,6 @@ impl Window {
self.key_handler.is_key_pressed(key, repeat)
}
#[inline]
pub fn is_open(&self) -> bool {
return self.is_open
@ -675,7 +708,7 @@ impl Window {
println!("accel {:?}", self.accel_table);
}
pub fn add_menu(&mut self, menu: &Menu) -> MenuHandle {
unsafe {
let window = self.window.unwrap();
@ -687,9 +720,9 @@ impl Window {
Self::adjust_window_size_for_menu(window);
}
user32::AppendMenuW(main_menu,
0x10,
menu.menu_handle as UINT_PTR,
user32::AppendMenuW(main_menu,
0x10,
menu.menu_handle as UINT_PTR,
menu.name.as_ptr());
self.menus.push(menu.clone());
@ -702,7 +735,7 @@ impl Window {
}
// TODO: Proper handle
MenuHandle(menu.menu_handle as u64)
}
@ -867,9 +900,9 @@ impl Menu {
pub fn add_sub_menu(&mut self, name: &str, menu: &Menu) {
unsafe {
let menu_name = to_wstring(name);
user32::AppendMenuW(self.menu_handle,
0x10,
menu.menu_handle as UINT_PTR,
user32::AppendMenuW(self.menu_handle,
0x10,
menu.menu_handle as UINT_PTR,
menu_name.as_ptr());
self.accel_table.extend_from_slice(menu.accel_table.as_slice());
}