mirror of
https://github.com/italicsjenga/rust_minifb.git
synced 2025-01-26 18:46:34 +11:00
Added set_title and set_cursor_style
This commit is contained in:
parent
b231ee1b5a
commit
495f7c4cca
9 changed files with 621 additions and 314 deletions
|
@ -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
79
examples/title_cursor.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
82
src/lib.rs
82
src/lib.rs
|
@ -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
|
||||
///
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue