Add input events (#18)
* MacOSX with input events and mfb_set_viewport * Windows with input events and mfb_set_viewport * Minor changes in macosx and windows * X11 with input and mfb_set_viewport * Minor changes on X11 * Fix bug in X11 resize event * Fix bug in windows resize * added scale image to X11 * Added stretch_image with & without bilinear interpolation * moved MiniFB_internal.h * Added wayland events * minor changes * unify a bit the window structs * More work on wayland * Added cmake file * minor fix on windows * modified test * Fix on wayland. Unset wayland as default for linux * Use stdbool instead of our own macro eBool Remove prefix e from all enums * Remove _ex sufix in common files * merge X11MiniFB_ex.c into X11MiniFB.c * Merge WaylandMiniFB_ex.c into WaylandMiniFB.c * Add user_data to callbacks * Merge WinMiniFB_ex.c into WinMiniFB.c * Some minor changes on Windows * Fix bug on Wayland * Added mfb_get_key_name * keyboard_default on all platforms
This commit is contained in:
parent
d6a52459ef
commit
8b6148cf97
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,2 +1,8 @@
|
|||||||
.tundra2.*
|
.tundra2.*
|
||||||
t2-output
|
t2-output
|
||||||
|
/.vscode
|
||||||
|
/win
|
||||||
|
/macosx
|
||||||
|
/linux
|
||||||
|
/build
|
||||||
|
/.history
|
||||||
|
75
CMakeLists.txt
Normal file
75
CMakeLists.txt
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8.9)
|
||||||
|
project (noise)
|
||||||
|
|
||||||
|
include_directories(include src)
|
||||||
|
|
||||||
|
file(GLOB SrcLib "src/*.c"
|
||||||
|
"src/*.cpp"
|
||||||
|
"include/*.h")
|
||||||
|
file(GLOB SrcWindows "src/windows/*.c"
|
||||||
|
"src/windows/*.h")
|
||||||
|
file(GLOB SrcMacOSX "src/macosx/*.c"
|
||||||
|
"src/macosx/*.cpp"
|
||||||
|
"src/macosx/*.m"
|
||||||
|
"src/macosx/*.mm"
|
||||||
|
"src/macosx/*.h")
|
||||||
|
file(GLOB SrcWayland "src/wayland/*.c")
|
||||||
|
file(GLOB SrcX11 "src/x11/*.c")
|
||||||
|
|
||||||
|
if (NOT MSVC)
|
||||||
|
set (CMAKE_C_FLAGS "-g -Wall -Wextra -Wno-switch -Wno-unused-function")
|
||||||
|
set (CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11")
|
||||||
|
set (CMAKE_OBJC_FLAGS "${CMAKE_C_FLAGS}")
|
||||||
|
set (CMAKE_OBJCXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
OPTION(USE_METAL_API "Build the project using metal API code" ON)
|
||||||
|
elseif (UNIX)
|
||||||
|
OPTION(USE_WAYLAND_API "Build the project using wayland API code" OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||||
|
list (APPEND SrcLib ${SrcWindows})
|
||||||
|
elseif (MINGW)
|
||||||
|
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||||
|
list(APPEND SrcLib ${SrcWindows})
|
||||||
|
elseif (APPLE)
|
||||||
|
if(USE_METAL_API)
|
||||||
|
add_definitions(-DUSE_METAL_API)
|
||||||
|
endif()
|
||||||
|
list(APPEND SrcLib ${SrcMacOSX})
|
||||||
|
elseif (UNIX)
|
||||||
|
if(USE_WAYLAND_API)
|
||||||
|
list(APPEND SrcLib ${SrcWayland})
|
||||||
|
else()
|
||||||
|
list(APPEND SrcLib ${SrcX11})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(minifb STATIC
|
||||||
|
${SrcLib}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(noise
|
||||||
|
tests/noise.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(noise minifb)
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
elseif (MINGW)
|
||||||
|
elseif (APPLE)
|
||||||
|
target_link_libraries(noise "-framework Cocoa")
|
||||||
|
target_link_libraries(noise "-framework QuartzCore")
|
||||||
|
target_link_libraries(noise "-framework Metal")
|
||||||
|
target_link_libraries(noise "-framework MetalKit")
|
||||||
|
elseif (UNIX)
|
||||||
|
if(USE_WAYLAND_API)
|
||||||
|
target_link_libraries(noise -lwayland-client -lwayland-cursor)
|
||||||
|
else()
|
||||||
|
target_link_libraries(noise -lX11)
|
||||||
|
endif()
|
||||||
|
endif()
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef _MINIFB_H_
|
#ifndef _MINIFB_H_
|
||||||
#define _MINIFB_H_
|
#define _MINIFB_H_
|
||||||
|
|
||||||
|
#include "MiniFB_enums.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -13,6 +15,7 @@ extern "C" {
|
|||||||
|
|
||||||
// Create a window that is used to display the buffer sent into the mfb_update function, returns 0 if fails
|
// Create a window that is used to display the buffer sent into the mfb_update function, returns 0 if fails
|
||||||
int mfb_open(const char* name, int width, int height);
|
int mfb_open(const char* name, int width, int height);
|
||||||
|
int mfb_open_ex(const char* name, int width, int height, int flags);
|
||||||
|
|
||||||
// Update the display. Input buffer is assumed to be a 32-bit buffer of the size given in the open call
|
// Update the display. Input buffer is assumed to be a 32-bit buffer of the size given in the open call
|
||||||
// Will return -1 when ESC key is pressed (later on will return keycode and -1 on other close signal)
|
// Will return -1 when ESC key is pressed (later on will return keycode and -1 on other close signal)
|
||||||
@ -21,10 +24,37 @@ int mfb_update(void* buffer);
|
|||||||
// Close the window
|
// Close the window
|
||||||
void mfb_close();
|
void mfb_close();
|
||||||
|
|
||||||
|
// Set user data
|
||||||
|
void mfb_set_user_data(void *user_data);
|
||||||
|
|
||||||
|
// Set viewport (useful when resize)
|
||||||
|
bool mfb_set_viewport(unsigned offset_x, unsigned offset_y, unsigned width, unsigned height);
|
||||||
|
|
||||||
|
// Event callbacks
|
||||||
|
typedef void(*mfb_active_func)(void *user_data, bool isActive);
|
||||||
|
typedef void(*mfb_resize_func)(void *user_data, int width, int height);
|
||||||
|
typedef void(*mfb_keyboard_func)(void *user_data, Key key, KeyMod mod, bool isPressed);
|
||||||
|
typedef void(*mfb_char_input_func)(void *user_data, unsigned int code);
|
||||||
|
typedef void(*mfb_mouse_btn_func)(void *user_data, MouseButton button, KeyMod mod, bool isPressed);
|
||||||
|
typedef void(*mfb_mouse_move_func)(void *user_data, int x, int y);
|
||||||
|
typedef void(*mfb_mouse_scroll_func)(void *user_data, KeyMod mod, float deltaX, float deltaY);
|
||||||
|
|
||||||
|
void mfb_active_callback(mfb_active_func callback);
|
||||||
|
void mfb_resize_callback(mfb_resize_func callback);
|
||||||
|
void mfb_keyboard_callback(mfb_keyboard_func callback);
|
||||||
|
void mfb_char_input_callback(mfb_char_input_func callback);
|
||||||
|
void mfb_mouse_button_callback(mfb_mouse_btn_func callback);
|
||||||
|
void mfb_mouse_move_callback(mfb_mouse_move_func callback);
|
||||||
|
void mfb_mouse_scroll_callback(mfb_mouse_scroll_func callback);
|
||||||
|
|
||||||
|
const char *mfb_get_key_name(Key key);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "MiniFB_cpp.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
124
include/MiniFB_cpp.h
Executable file
124
include/MiniFB_cpp.h
Executable file
@ -0,0 +1,124 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include "MiniFB.h"
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void mfb_active_callback(T *obj, void (T::*method)(void *, bool));
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void mfb_resize_callback(T *obj, void (T::*method)(void *, int, int));
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void mfb_keyboard_callback(T *obj, void (T::*method)(void *, Key, KeyMod, bool));
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void mfb_char_input_callback(T *obj, void (T::*method)(void *, unsigned int));
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void mfb_mouse_button_callback(T *obj, void (T::*method)(void *, MouseButton, KeyMod, bool));
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void mfb_mouse_move_callback(T *obj, void (T::*method)(void *, int, int));
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void mfb_mouse_scroll_callback(T *obj, void (T::*method)(void *, KeyMod, float, float));
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
// To avoid clumsy hands
|
||||||
|
//-------------------------------------
|
||||||
|
class Stub {
|
||||||
|
template <class T>
|
||||||
|
friend void mfb_active_callback(T *obj, void (T::*method)(void *, bool));
|
||||||
|
template <class T>
|
||||||
|
friend void mfb_resize_callback(T *obj, void (T::*method)(void *, int, int));
|
||||||
|
template <class T>
|
||||||
|
friend void mfb_mouse_button_callback(T *obj, void (T::*method)(void *, MouseButton, KeyMod, bool));
|
||||||
|
template <class T>
|
||||||
|
friend void mfb_keyboard_callback(T *obj, void (T::*method)(void *, Key, KeyMod, bool));
|
||||||
|
template <class T>
|
||||||
|
friend void mfb_char_input_callback(T *obj, void (T::*method)(void *, unsigned int));
|
||||||
|
template <class T>
|
||||||
|
friend void mfb_mouse_button_callback(T *obj, void (T::*method)(void *, MouseButton, KeyMod, bool));
|
||||||
|
template <class T>
|
||||||
|
friend void mfb_mouse_move_callback(T *obj, void (T::*method)(void *, int, int));
|
||||||
|
template <class T>
|
||||||
|
friend void mfb_mouse_scroll_callback(T *obj, void (T::*method)(void *, KeyMod, float, float));
|
||||||
|
|
||||||
|
static void active_stub(void *user_data, bool isActive);
|
||||||
|
static void resize_stub(void *user_data, int width, int height);
|
||||||
|
static void keyboard_stub(void *user_data, Key key, KeyMod mod, bool isPressed);
|
||||||
|
static void char_input_stub(void *user_data, unsigned int);
|
||||||
|
static void mouse_btn_stub(void *user_data, MouseButton button, KeyMod mod, bool isPressed);
|
||||||
|
static void mouse_move_stub(void *user_data, int x, int y);
|
||||||
|
static void scroll_stub(void *user_data, KeyMod mod, float deltaX, float deltaY);
|
||||||
|
|
||||||
|
static std::function<void(void *user_data, bool)> m_active;
|
||||||
|
static std::function<void(void *user_data, int, int)> m_resize;
|
||||||
|
static std::function<void(void *user_data, Key, KeyMod, bool)> m_keyboard;
|
||||||
|
static std::function<void(void *user_data, unsigned int)> m_char_input;
|
||||||
|
static std::function<void(void *user_data, MouseButton, KeyMod, bool)> m_mouse_btn;
|
||||||
|
static std::function<void(void *user_data, int, int)> m_mouse_move;
|
||||||
|
static std::function<void(void *user_data, KeyMod, float, float)> m_scroll;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
template <class T>
|
||||||
|
inline void mfb_active_callback(T *obj, void (T::*method)(void *user_data, bool)) {
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
Stub::m_active = std::bind(method, obj, _1, _2);
|
||||||
|
mfb_active_callback(Stub::active_stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void mfb_resize_callback(T *obj, void (T::*method)(void *user_data, int, int)) {
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
Stub::m_resize = std::bind(method, obj, _1, _2, _3);
|
||||||
|
mfb_resize_callback(Stub::resize_stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void mfb_keyboard_callback(T *obj, void (T::*method)(void *user_data, Key, KeyMod, bool)) {
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
Stub::m_keyboard = std::bind(method, obj, _1, _2, _3, _4);
|
||||||
|
mfb_keyboard_callback(Stub::keyboard_stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void mfb_char_input_callback(T *obj, void (T::*method)(void *user_data, unsigned int)) {
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
Stub::m_char_input = std::bind(method, obj, _1, _2);
|
||||||
|
mfb_char_input_callback(Stub::char_input_stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void mfb_mouse_button_callback(T *obj, void (T::*method)(void *user_data, MouseButton, KeyMod, bool)) {
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
Stub::m_mouse_btn = std::bind(method, obj, _1, _2, _3, _4);
|
||||||
|
mfb_mouse_button_callback(Stub::mouse_btn_stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void mfb_mouse_move_callback(T *obj, void (T::*method)(void *user_data, int, int)) {
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
Stub::m_mouse_move = std::bind(method, obj, _1, _2, _3);
|
||||||
|
mfb_mouse_move_callback(Stub::mouse_move_stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void mfb_mouse_scroll_callback(T *obj, void (T::*method)(void *user_data, KeyMod, float, float)) {
|
||||||
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
Stub::m_scroll = std::bind(method, obj, _1, _2, _3, _4);
|
||||||
|
mfb_mouse_scroll_callback(Stub::scroll_stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
163
include/MiniFB_enums.h
Executable file
163
include/MiniFB_enums.h
Executable file
@ -0,0 +1,163 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MOUSE_BTN_0, // No mouse button
|
||||||
|
MOUSE_BTN_1,
|
||||||
|
MOUSE_BTN_2,
|
||||||
|
MOUSE_BTN_3,
|
||||||
|
MOUSE_BTN_4,
|
||||||
|
MOUSE_BTN_5,
|
||||||
|
MOUSE_BTN_6,
|
||||||
|
MOUSE_BTN_7,
|
||||||
|
MOUSE_BTN_8
|
||||||
|
} MouseButton;
|
||||||
|
#define MOUSE_LAST MOUSE_BTN_8
|
||||||
|
#define MOUSE_LEFT MOUSE_BTN_0
|
||||||
|
#define MOUSE_RIGHT MOUSE_BTN_1
|
||||||
|
#define MOUSE_MIDDLE MOUSE_BTN_2
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KB_KEY_UNKNOWN = -1,
|
||||||
|
|
||||||
|
KB_KEY_SPACE = 32,
|
||||||
|
KB_KEY_APOSTROPHE = 39,
|
||||||
|
KB_KEY_COMMA = 44,
|
||||||
|
KB_KEY_MINUS = 45,
|
||||||
|
KB_KEY_PERIOD = 46,
|
||||||
|
KB_KEY_SLASH = 47,
|
||||||
|
KB_KEY_0 = 48,
|
||||||
|
KB_KEY_1 = 49,
|
||||||
|
KB_KEY_2 = 50,
|
||||||
|
KB_KEY_3 = 51,
|
||||||
|
KB_KEY_4 = 52,
|
||||||
|
KB_KEY_5 = 53,
|
||||||
|
KB_KEY_6 = 54,
|
||||||
|
KB_KEY_7 = 55,
|
||||||
|
KB_KEY_8 = 56,
|
||||||
|
KB_KEY_9 = 57,
|
||||||
|
KB_KEY_SEMICOLON = 59,
|
||||||
|
KB_KEY_EQUAL = 61,
|
||||||
|
KB_KEY_A = 65,
|
||||||
|
KB_KEY_B = 66,
|
||||||
|
KB_KEY_C = 67,
|
||||||
|
KB_KEY_D = 68,
|
||||||
|
KB_KEY_E = 69,
|
||||||
|
KB_KEY_F = 70,
|
||||||
|
KB_KEY_G = 71,
|
||||||
|
KB_KEY_H = 72,
|
||||||
|
KB_KEY_I = 73,
|
||||||
|
KB_KEY_J = 74,
|
||||||
|
KB_KEY_K = 75,
|
||||||
|
KB_KEY_L = 76,
|
||||||
|
KB_KEY_M = 77,
|
||||||
|
KB_KEY_N = 78,
|
||||||
|
KB_KEY_O = 79,
|
||||||
|
KB_KEY_P = 80,
|
||||||
|
KB_KEY_Q = 81,
|
||||||
|
KB_KEY_R = 82,
|
||||||
|
KB_KEY_S = 83,
|
||||||
|
KB_KEY_T = 84,
|
||||||
|
KB_KEY_U = 85,
|
||||||
|
KB_KEY_V = 86,
|
||||||
|
KB_KEY_W = 87,
|
||||||
|
KB_KEY_X = 88,
|
||||||
|
KB_KEY_Y = 89,
|
||||||
|
KB_KEY_Z = 90,
|
||||||
|
KB_KEY_LEFT_BRACKET = 91,
|
||||||
|
KB_KEY_BACKSLASH = 92,
|
||||||
|
KB_KEY_RIGHT_BRACKET = 93,
|
||||||
|
KB_KEY_GRAVE_ACCENT = 96,
|
||||||
|
KB_KEY_WORLD_1 = 161,
|
||||||
|
KB_KEY_WORLD_2 = 162,
|
||||||
|
|
||||||
|
KB_KEY_ESCAPE = 256,
|
||||||
|
KB_KEY_ENTER = 257,
|
||||||
|
KB_KEY_TAB = 258,
|
||||||
|
KB_KEY_BACKSPACE = 259,
|
||||||
|
KB_KEY_INSERT = 260,
|
||||||
|
KB_KEY_DELETE = 261,
|
||||||
|
KB_KEY_RIGHT = 262,
|
||||||
|
KB_KEY_LEFT = 263,
|
||||||
|
KB_KEY_DOWN = 264,
|
||||||
|
KB_KEY_UP = 265,
|
||||||
|
KB_KEY_PAGE_UP = 266,
|
||||||
|
KB_KEY_PAGE_DOWN = 267,
|
||||||
|
KB_KEY_HOME = 268,
|
||||||
|
KB_KEY_END = 269,
|
||||||
|
KB_KEY_CAPS_LOCK = 280,
|
||||||
|
KB_KEY_SCROLL_LOCK = 281,
|
||||||
|
KB_KEY_NUM_LOCK = 282,
|
||||||
|
KB_KEY_PRINT_SCREEN = 283,
|
||||||
|
KB_KEY_PAUSE = 284,
|
||||||
|
KB_KEY_F1 = 290,
|
||||||
|
KB_KEY_F2 = 291,
|
||||||
|
KB_KEY_F3 = 292,
|
||||||
|
KB_KEY_F4 = 293,
|
||||||
|
KB_KEY_F5 = 294,
|
||||||
|
KB_KEY_F6 = 295,
|
||||||
|
KB_KEY_F7 = 296,
|
||||||
|
KB_KEY_F8 = 297,
|
||||||
|
KB_KEY_F9 = 298,
|
||||||
|
KB_KEY_F10 = 299,
|
||||||
|
KB_KEY_F11 = 300,
|
||||||
|
KB_KEY_F12 = 301,
|
||||||
|
KB_KEY_F13 = 302,
|
||||||
|
KB_KEY_F14 = 303,
|
||||||
|
KB_KEY_F15 = 304,
|
||||||
|
KB_KEY_F16 = 305,
|
||||||
|
KB_KEY_F17 = 306,
|
||||||
|
KB_KEY_F18 = 307,
|
||||||
|
KB_KEY_F19 = 308,
|
||||||
|
KB_KEY_F20 = 309,
|
||||||
|
KB_KEY_F21 = 310,
|
||||||
|
KB_KEY_F22 = 311,
|
||||||
|
KB_KEY_F23 = 312,
|
||||||
|
KB_KEY_F24 = 313,
|
||||||
|
KB_KEY_F25 = 314,
|
||||||
|
KB_KEY_KP_0 = 320,
|
||||||
|
KB_KEY_KP_1 = 321,
|
||||||
|
KB_KEY_KP_2 = 322,
|
||||||
|
KB_KEY_KP_3 = 323,
|
||||||
|
KB_KEY_KP_4 = 324,
|
||||||
|
KB_KEY_KP_5 = 325,
|
||||||
|
KB_KEY_KP_6 = 326,
|
||||||
|
KB_KEY_KP_7 = 327,
|
||||||
|
KB_KEY_KP_8 = 328,
|
||||||
|
KB_KEY_KP_9 = 329,
|
||||||
|
KB_KEY_KP_DECIMAL = 330,
|
||||||
|
KB_KEY_KP_DIVIDE = 331,
|
||||||
|
KB_KEY_KP_MULTIPLY = 332,
|
||||||
|
KB_KEY_KP_SUBTRACT = 333,
|
||||||
|
KB_KEY_KP_ADD = 334,
|
||||||
|
KB_KEY_KP_ENTER = 335,
|
||||||
|
KB_KEY_KP_EQUAL = 336,
|
||||||
|
KB_KEY_LEFT_SHIFT = 340,
|
||||||
|
KB_KEY_LEFT_CONTROL = 341,
|
||||||
|
KB_KEY_LEFT_ALT = 342,
|
||||||
|
KB_KEY_LEFT_SUPER = 343,
|
||||||
|
KB_KEY_RIGHT_SHIFT = 344,
|
||||||
|
KB_KEY_RIGHT_CONTROL = 345,
|
||||||
|
KB_KEY_RIGHT_ALT = 346,
|
||||||
|
KB_KEY_RIGHT_SUPER = 347,
|
||||||
|
KB_KEY_MENU = 348
|
||||||
|
} Key;
|
||||||
|
#define KB_KEY_LAST KB_KEY_MENU
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KB_MOD_SHIFT = 0x0001,
|
||||||
|
KB_MOD_CONTROL = 0x0002,
|
||||||
|
KB_MOD_ALT = 0x0004,
|
||||||
|
KB_MOD_SUPER = 0x0008,
|
||||||
|
KB_MOD_CAPS_LOCK = 0x0010,
|
||||||
|
KB_MOD_NUM_LOCK = 0x0020
|
||||||
|
} KeyMod;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WF_RESIZABLE = 0x01,
|
||||||
|
WF_FULLSCREEN = 0x02,
|
||||||
|
WF_FULLSCREEN_DESKTOP = 0x04,
|
||||||
|
WF_BORDERLESS = 0x08,
|
||||||
|
WF_ALWAYS_ON_TOP = 0x10,
|
||||||
|
} WindowFlags;
|
421
src/MiniFB_common.c
Executable file
421
src/MiniFB_common.c
Executable file
@ -0,0 +1,421 @@
|
|||||||
|
#include "MiniFB.h"
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
mfb_active_func g_active_func = 0x0;
|
||||||
|
mfb_resize_func g_resize_func = 0x0;
|
||||||
|
mfb_keyboard_func g_keyboard_func = 0x0;
|
||||||
|
mfb_char_input_func g_char_input_func = 0x0;
|
||||||
|
mfb_mouse_btn_func g_mouse_btn_func = 0x0;
|
||||||
|
mfb_mouse_move_func g_mouse_move_func = 0x0;
|
||||||
|
mfb_mouse_scroll_func g_mouse_wheel_func = 0x0;
|
||||||
|
|
||||||
|
void *g_user_data = 0x0;
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
void mfb_active_callback(mfb_active_func callback) {
|
||||||
|
g_active_func = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
void mfb_resize_callback(mfb_resize_func callback) {
|
||||||
|
g_resize_func = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
void mfb_keyboard_callback(mfb_keyboard_func callback) {
|
||||||
|
g_keyboard_func = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
void mfb_char_input_callback(mfb_char_input_func callback) {
|
||||||
|
g_char_input_func = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
void mfb_mouse_button_callback(mfb_mouse_btn_func callback) {
|
||||||
|
g_mouse_btn_func = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
void mfb_mouse_move_callback(mfb_mouse_move_func callback) {
|
||||||
|
g_mouse_move_func = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
void mfb_mouse_scroll_callback(mfb_mouse_scroll_func callback) {
|
||||||
|
g_mouse_wheel_func = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
void mfb_set_user_data(void *user_data) {
|
||||||
|
g_user_data = user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
const char *mfb_get_key_name(Key key) {
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case KB_KEY_SPACE:
|
||||||
|
return "Space";
|
||||||
|
|
||||||
|
case KB_KEY_APOSTROPHE:
|
||||||
|
return "Apostrophe";
|
||||||
|
|
||||||
|
case KB_KEY_COMMA:
|
||||||
|
return "Comma";
|
||||||
|
|
||||||
|
case KB_KEY_MINUS:
|
||||||
|
return "Minus";
|
||||||
|
|
||||||
|
case KB_KEY_PERIOD:
|
||||||
|
return "Period";
|
||||||
|
|
||||||
|
case KB_KEY_SLASH:
|
||||||
|
return "Slash";
|
||||||
|
|
||||||
|
case KB_KEY_0:
|
||||||
|
return "0";
|
||||||
|
|
||||||
|
case KB_KEY_1:
|
||||||
|
return "1";
|
||||||
|
|
||||||
|
case KB_KEY_2:
|
||||||
|
return "2";
|
||||||
|
|
||||||
|
case KB_KEY_3:
|
||||||
|
return "3";
|
||||||
|
|
||||||
|
case KB_KEY_4:
|
||||||
|
return "4";
|
||||||
|
|
||||||
|
case KB_KEY_5:
|
||||||
|
return "5";
|
||||||
|
|
||||||
|
case KB_KEY_6:
|
||||||
|
return "6";
|
||||||
|
|
||||||
|
case KB_KEY_7:
|
||||||
|
return "7";
|
||||||
|
|
||||||
|
case KB_KEY_8:
|
||||||
|
return "8";
|
||||||
|
|
||||||
|
case KB_KEY_9:
|
||||||
|
return "9";
|
||||||
|
|
||||||
|
case KB_KEY_SEMICOLON:
|
||||||
|
return "Semicolon";
|
||||||
|
|
||||||
|
case KB_KEY_EQUAL:
|
||||||
|
return "Equal";
|
||||||
|
|
||||||
|
case KB_KEY_A:
|
||||||
|
return "A";
|
||||||
|
|
||||||
|
case KB_KEY_B:
|
||||||
|
return "B";
|
||||||
|
|
||||||
|
case KB_KEY_C:
|
||||||
|
return "C";
|
||||||
|
|
||||||
|
case KB_KEY_D:
|
||||||
|
return "D";
|
||||||
|
|
||||||
|
case KB_KEY_E:
|
||||||
|
return "E";
|
||||||
|
|
||||||
|
case KB_KEY_F:
|
||||||
|
return "F";
|
||||||
|
|
||||||
|
case KB_KEY_G:
|
||||||
|
return "G";
|
||||||
|
|
||||||
|
case KB_KEY_H:
|
||||||
|
return "H";
|
||||||
|
|
||||||
|
case KB_KEY_I:
|
||||||
|
return "I";
|
||||||
|
|
||||||
|
case KB_KEY_J:
|
||||||
|
return "J";
|
||||||
|
|
||||||
|
case KB_KEY_K:
|
||||||
|
return "K";
|
||||||
|
|
||||||
|
case KB_KEY_L:
|
||||||
|
return "L";
|
||||||
|
|
||||||
|
case KB_KEY_M:
|
||||||
|
return "M";
|
||||||
|
|
||||||
|
case KB_KEY_N:
|
||||||
|
return "N";
|
||||||
|
|
||||||
|
case KB_KEY_O:
|
||||||
|
return "O";
|
||||||
|
|
||||||
|
case KB_KEY_P:
|
||||||
|
return "P";
|
||||||
|
|
||||||
|
case KB_KEY_Q:
|
||||||
|
return "Q";
|
||||||
|
|
||||||
|
case KB_KEY_R:
|
||||||
|
return "R";
|
||||||
|
|
||||||
|
case KB_KEY_S:
|
||||||
|
return "S";
|
||||||
|
|
||||||
|
case KB_KEY_T:
|
||||||
|
return "T";
|
||||||
|
|
||||||
|
case KB_KEY_U:
|
||||||
|
return "U";
|
||||||
|
|
||||||
|
case KB_KEY_V:
|
||||||
|
return "V";
|
||||||
|
|
||||||
|
case KB_KEY_W:
|
||||||
|
return "W";
|
||||||
|
|
||||||
|
case KB_KEY_X:
|
||||||
|
return "X";
|
||||||
|
|
||||||
|
case KB_KEY_Y:
|
||||||
|
return "Y";
|
||||||
|
|
||||||
|
case KB_KEY_Z:
|
||||||
|
return "Z";
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_BRACKET:
|
||||||
|
return "Left_Bracket";
|
||||||
|
|
||||||
|
case KB_KEY_BACKSLASH:
|
||||||
|
return "Backslash";
|
||||||
|
|
||||||
|
case KB_KEY_RIGHT_BRACKET:
|
||||||
|
return "Right_Bracket";
|
||||||
|
|
||||||
|
case KB_KEY_GRAVE_ACCENT:
|
||||||
|
return "Grave_Accent";
|
||||||
|
|
||||||
|
case KB_KEY_WORLD_1:
|
||||||
|
return "World_1";
|
||||||
|
|
||||||
|
case KB_KEY_WORLD_2:
|
||||||
|
return "World_2";
|
||||||
|
|
||||||
|
case KB_KEY_ESCAPE:
|
||||||
|
return "Escape";
|
||||||
|
|
||||||
|
case KB_KEY_ENTER:
|
||||||
|
return "Enter";
|
||||||
|
|
||||||
|
case KB_KEY_TAB:
|
||||||
|
return "Tab";
|
||||||
|
|
||||||
|
case KB_KEY_BACKSPACE:
|
||||||
|
return "Backspace";
|
||||||
|
|
||||||
|
case KB_KEY_INSERT:
|
||||||
|
return "Insert";
|
||||||
|
|
||||||
|
case KB_KEY_DELETE:
|
||||||
|
return "Delete";
|
||||||
|
|
||||||
|
case KB_KEY_RIGHT:
|
||||||
|
return "Right";
|
||||||
|
|
||||||
|
case KB_KEY_LEFT:
|
||||||
|
return "Left";
|
||||||
|
|
||||||
|
case KB_KEY_DOWN:
|
||||||
|
return "Down";
|
||||||
|
|
||||||
|
case KB_KEY_UP:
|
||||||
|
return "Up";
|
||||||
|
|
||||||
|
case KB_KEY_PAGE_UP:
|
||||||
|
return "Page_Up";
|
||||||
|
|
||||||
|
case KB_KEY_PAGE_DOWN:
|
||||||
|
return "Page_Down";
|
||||||
|
|
||||||
|
case KB_KEY_HOME:
|
||||||
|
return "Home";
|
||||||
|
|
||||||
|
case KB_KEY_END:
|
||||||
|
return "End";
|
||||||
|
|
||||||
|
case KB_KEY_CAPS_LOCK:
|
||||||
|
return "Caps_Lock";
|
||||||
|
|
||||||
|
case KB_KEY_SCROLL_LOCK:
|
||||||
|
return "Scroll_Lock";
|
||||||
|
|
||||||
|
case KB_KEY_NUM_LOCK:
|
||||||
|
return "Num_Lock";
|
||||||
|
|
||||||
|
case KB_KEY_PRINT_SCREEN:
|
||||||
|
return "Print_Screen";
|
||||||
|
|
||||||
|
case KB_KEY_PAUSE:
|
||||||
|
return "Pause";
|
||||||
|
|
||||||
|
case KB_KEY_F1:
|
||||||
|
return "F1";
|
||||||
|
|
||||||
|
case KB_KEY_F2:
|
||||||
|
return "F2";
|
||||||
|
|
||||||
|
case KB_KEY_F3:
|
||||||
|
return "F3";
|
||||||
|
|
||||||
|
case KB_KEY_F4:
|
||||||
|
return "F4";
|
||||||
|
|
||||||
|
case KB_KEY_F5:
|
||||||
|
return "F5";
|
||||||
|
|
||||||
|
case KB_KEY_F6:
|
||||||
|
return "F6";
|
||||||
|
|
||||||
|
case KB_KEY_F7:
|
||||||
|
return "F7";
|
||||||
|
|
||||||
|
case KB_KEY_F8:
|
||||||
|
return "F8";
|
||||||
|
|
||||||
|
case KB_KEY_F9:
|
||||||
|
return "F9";
|
||||||
|
|
||||||
|
case KB_KEY_F10:
|
||||||
|
return "F10";
|
||||||
|
|
||||||
|
case KB_KEY_F11:
|
||||||
|
return "F11";
|
||||||
|
|
||||||
|
case KB_KEY_F12:
|
||||||
|
return "F12";
|
||||||
|
|
||||||
|
case KB_KEY_F13:
|
||||||
|
return "F13";
|
||||||
|
|
||||||
|
case KB_KEY_F14:
|
||||||
|
return "F14";
|
||||||
|
|
||||||
|
case KB_KEY_F15:
|
||||||
|
return "F15";
|
||||||
|
|
||||||
|
case KB_KEY_F16:
|
||||||
|
return "F16";
|
||||||
|
|
||||||
|
case KB_KEY_F17:
|
||||||
|
return "F17";
|
||||||
|
|
||||||
|
case KB_KEY_F18:
|
||||||
|
return "F18";
|
||||||
|
|
||||||
|
case KB_KEY_F19:
|
||||||
|
return "F19";
|
||||||
|
|
||||||
|
case KB_KEY_F20:
|
||||||
|
return "F20";
|
||||||
|
|
||||||
|
case KB_KEY_F21:
|
||||||
|
return "F21";
|
||||||
|
|
||||||
|
case KB_KEY_F22:
|
||||||
|
return "F22";
|
||||||
|
|
||||||
|
case KB_KEY_F23:
|
||||||
|
return "F23";
|
||||||
|
|
||||||
|
case KB_KEY_F24:
|
||||||
|
return "F24";
|
||||||
|
|
||||||
|
case KB_KEY_F25:
|
||||||
|
return "F25";
|
||||||
|
|
||||||
|
case KB_KEY_KP_0:
|
||||||
|
return "KP_0";
|
||||||
|
|
||||||
|
case KB_KEY_KP_1:
|
||||||
|
return "KP_1";
|
||||||
|
|
||||||
|
case KB_KEY_KP_2:
|
||||||
|
return "KP_2";
|
||||||
|
|
||||||
|
case KB_KEY_KP_3:
|
||||||
|
return "KP_3";
|
||||||
|
|
||||||
|
case KB_KEY_KP_4:
|
||||||
|
return "KP_4";
|
||||||
|
|
||||||
|
case KB_KEY_KP_5:
|
||||||
|
return "KP_5";
|
||||||
|
|
||||||
|
case KB_KEY_KP_6:
|
||||||
|
return "KP_6";
|
||||||
|
|
||||||
|
case KB_KEY_KP_7:
|
||||||
|
return "KP_7";
|
||||||
|
|
||||||
|
case KB_KEY_KP_8:
|
||||||
|
return "KP_8";
|
||||||
|
|
||||||
|
case KB_KEY_KP_9:
|
||||||
|
return "KP_9";
|
||||||
|
|
||||||
|
case KB_KEY_KP_DECIMAL:
|
||||||
|
return "KP_Decimal";
|
||||||
|
|
||||||
|
case KB_KEY_KP_DIVIDE:
|
||||||
|
return "KP_Divide";
|
||||||
|
|
||||||
|
case KB_KEY_KP_MULTIPLY:
|
||||||
|
return "KP_Multiply";
|
||||||
|
|
||||||
|
case KB_KEY_KP_SUBTRACT:
|
||||||
|
return "KP_Subtract";
|
||||||
|
|
||||||
|
case KB_KEY_KP_ADD:
|
||||||
|
return "KP_Add";
|
||||||
|
|
||||||
|
case KB_KEY_KP_ENTER:
|
||||||
|
return "KP_Enter";
|
||||||
|
|
||||||
|
case KB_KEY_KP_EQUAL:
|
||||||
|
return "KP_Equal";
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_SHIFT:
|
||||||
|
return "Left_Shift";
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_CONTROL:
|
||||||
|
return "Left_Control";
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_ALT:
|
||||||
|
return "Left_Alt";
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_SUPER:
|
||||||
|
return "Left_Super";
|
||||||
|
|
||||||
|
case KB_KEY_RIGHT_SHIFT:
|
||||||
|
return "Right_Shift";
|
||||||
|
|
||||||
|
case KB_KEY_RIGHT_CONTROL:
|
||||||
|
return "Right_Control";
|
||||||
|
|
||||||
|
case KB_KEY_RIGHT_ALT:
|
||||||
|
return "Right_Alt";
|
||||||
|
|
||||||
|
case KB_KEY_RIGHT_SUPER:
|
||||||
|
return "Right_Super";
|
||||||
|
|
||||||
|
case KB_KEY_MENU:
|
||||||
|
return "Menu";
|
||||||
|
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
38
src/MiniFB_cpp.cpp
Executable file
38
src/MiniFB_cpp.cpp
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
#include <MiniFB_cpp.h>
|
||||||
|
#include <MiniFB_enums.h>
|
||||||
|
|
||||||
|
std::function<void(void *, bool)> Stub::m_active;
|
||||||
|
std::function<void(void *, int, int)> Stub::m_resize;
|
||||||
|
std::function<void(void *, Key, KeyMod, bool)> Stub::m_keyboard;
|
||||||
|
std::function<void(void *, unsigned int)> Stub::m_char_input;
|
||||||
|
std::function<void(void *, MouseButton, KeyMod, bool)> Stub::m_mouse_btn;
|
||||||
|
std::function<void(void *, int, int)> Stub::m_mouse_move;
|
||||||
|
std::function<void(void *, KeyMod, float, float)> Stub::m_scroll;
|
||||||
|
|
||||||
|
void Stub::active_stub(void *user_data, bool isActive) {
|
||||||
|
m_active(user_data, isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stub::resize_stub(void *user_data, int width, int height) {
|
||||||
|
m_resize(user_data, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stub::keyboard_stub(void *user_data, Key key, KeyMod mod, bool isPressed) {
|
||||||
|
m_keyboard(user_data, key, mod, isPressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stub::char_input_stub(void *user_data, unsigned int code) {
|
||||||
|
m_char_input(user_data, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stub::mouse_btn_stub(void *user_data, MouseButton button, KeyMod mod, bool isPressed) {
|
||||||
|
m_mouse_btn(user_data, button, mod, isPressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stub::mouse_move_stub(void *user_data, int x, int y) {
|
||||||
|
m_mouse_move(user_data, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stub::scroll_stub(void *user_data, KeyMod mod, float deltaX, float deltaY) {
|
||||||
|
m_scroll(user_data, mod, deltaX, deltaY);
|
||||||
|
}
|
75
src/MiniFB_internal.c
Normal file
75
src/MiniFB_internal.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "MiniFB_internal.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//#define kUseBilinearInterpolation
|
||||||
|
|
||||||
|
#if defined(kUseBilinearInterpolation)
|
||||||
|
static uint32_t interpolate(uint32_t *srcImage, uint32_t x, uint32_t y, uint32_t srcOffsetX, uint32_t srcOffsetY, uint32_t srcWidth, uint32_t srcHeight, uint32_t srcPitch) {
|
||||||
|
uint32_t incX = x + 1 < srcWidth ? 1 : 0;
|
||||||
|
uint32_t incY = y + 1 < srcHeight ? srcPitch : 0;
|
||||||
|
uint8_t *p00 = (uint8_t *) &srcImage[(srcOffsetX >> 16)];
|
||||||
|
uint8_t *p01 = (uint8_t *) &srcImage[(srcOffsetX >> 16) + incX];
|
||||||
|
uint8_t *p10 = (uint8_t *) &srcImage[(srcOffsetX >> 16) + incY];
|
||||||
|
uint8_t *p11 = (uint8_t *) &srcImage[(srcOffsetX >> 16) + incY + incX];
|
||||||
|
|
||||||
|
uint32_t wx2 = srcOffsetX & 0xffff;
|
||||||
|
uint32_t wy2 = srcOffsetY & 0xffff;
|
||||||
|
uint32_t wx1 = 0x10000 - wx2;
|
||||||
|
uint32_t wy1 = 0x10000 - wy2;
|
||||||
|
|
||||||
|
uint32_t w1 = ((uint64_t) wx1 * wy1) >> 16;
|
||||||
|
uint32_t w2 = ((uint64_t) wx2 * wy1) >> 16;
|
||||||
|
uint32_t w3 = ((uint64_t) wx1 * wy2) >> 16;
|
||||||
|
uint32_t w4 = ((uint64_t) wx2 * wy2) >> 16;
|
||||||
|
|
||||||
|
// If you don't have uint64_t
|
||||||
|
//uint32_t b = (((p00[0] * wx1 + p01[0] * wx2) >> 16) * wy1 + ((p10[0] * wx1 + p11[0] * wx2) >> 16) * wy2) >> 16;
|
||||||
|
//uint32_t g = (((p00[1] * wx1 + p01[1] * wx2) >> 16) * wy1 + ((p10[1] * wx1 + p11[1] * wx2) >> 16) * wy2) >> 16;
|
||||||
|
//uint32_t r = (((p00[2] * wx1 + p01[2] * wx2) >> 16) * wy1 + ((p10[2] * wx1 + p11[2] * wx2) >> 16) * wy2) >> 16;
|
||||||
|
//uint32_t a = (((p00[3] * wx1 + p01[3] * wx2) >> 16) * wy1 + ((p10[3] * wx1 + p11[3] * wx2) >> 16) * wy2) >> 16;
|
||||||
|
|
||||||
|
uint32_t b = ((p00[0] * w1 + p01[0] * w2) + (p10[0] * w3 + p11[0] * w4)) >> 16;
|
||||||
|
uint32_t g = ((p00[1] * w1 + p01[1] * w2) + (p10[1] * w3 + p11[1] * w4)) >> 16;
|
||||||
|
uint32_t r = ((p00[2] * w1 + p01[2] * w2) + (p10[2] * w3 + p11[2] * w4)) >> 16;
|
||||||
|
uint32_t a = ((p00[3] * w1 + p01[3] * w2) + (p10[3] * w3 + p11[3] * w4)) >> 16;
|
||||||
|
|
||||||
|
return (a << 24) + (r << 16) + (g << 8) + b;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Only for 32 bits images
|
||||||
|
void stretch_image(uint32_t *srcImage, uint32_t srcX, uint32_t srcY, uint32_t srcWidth, uint32_t srcHeight, uint32_t srcPitch,
|
||||||
|
uint32_t *dstImage, uint32_t dstX, uint32_t dstY, uint32_t dstWidth, uint32_t dstHeight, uint32_t dstPitch) {
|
||||||
|
|
||||||
|
uint32_t x, y;
|
||||||
|
uint32_t srcOffsetX, srcOffsetY;
|
||||||
|
|
||||||
|
if(srcImage == 0x0 || dstImage == 0x0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
srcImage += srcX + srcY * srcPitch;
|
||||||
|
dstImage += dstX + dstY * dstPitch;
|
||||||
|
|
||||||
|
const uint32_t deltaX = (srcWidth << 16) / dstWidth;
|
||||||
|
const uint32_t deltaY = (srcHeight << 16) / dstHeight;
|
||||||
|
|
||||||
|
srcOffsetY = 0;
|
||||||
|
for(y=0; y<dstHeight; ++y) {
|
||||||
|
srcOffsetX = 0;
|
||||||
|
for(x=0; x<dstWidth; ++x) {
|
||||||
|
#if defined(kUseBilinearInterpolation)
|
||||||
|
dstImage[x] = interpolate(srcImage, x+srcX, y+srcY, srcOffsetX, srcOffsetY, srcWidth, srcHeight, srcPitch);
|
||||||
|
#else
|
||||||
|
dstImage[x] = srcImage[srcOffsetX >> 16];
|
||||||
|
#endif
|
||||||
|
srcOffsetX += deltaX;
|
||||||
|
}
|
||||||
|
|
||||||
|
srcOffsetY += deltaY;
|
||||||
|
if(srcOffsetY >= 0x10000) {
|
||||||
|
srcImage += (srcOffsetY >> 16) * srcPitch;
|
||||||
|
srcOffsetY &= 0xffff;
|
||||||
|
}
|
||||||
|
dstImage += dstPitch;
|
||||||
|
}
|
||||||
|
}
|
28
src/MiniFB_internal.h
Executable file
28
src/MiniFB_internal.h
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MiniFB.h"
|
||||||
|
|
||||||
|
extern void *g_user_data;
|
||||||
|
|
||||||
|
#define kCall(f, ...) if((f)) (f)(g_user_data, __VA_ARGS__);
|
||||||
|
#define kUnused(var) (void) var;
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
short int keycodes[512];
|
||||||
|
void init_keycodes();
|
||||||
|
void keyboard_default(void *user_data, Key key, KeyMod mod, bool isPressed);
|
||||||
|
|
||||||
|
extern mfb_active_func g_active_func;
|
||||||
|
extern mfb_resize_func g_resize_func;
|
||||||
|
extern mfb_keyboard_func g_keyboard_func;
|
||||||
|
extern mfb_char_input_func g_char_input_func;
|
||||||
|
extern mfb_mouse_btn_func g_mouse_btn_func;
|
||||||
|
extern mfb_mouse_move_func g_mouse_move_func;
|
||||||
|
extern mfb_mouse_scroll_func g_mouse_wheel_func;
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,12 +1,19 @@
|
|||||||
#include "OSXWindow.h"
|
#include "OSXWindow.h"
|
||||||
#include "OSXWindowFrameView.h"
|
#include "OSXWindowFrameView.h"
|
||||||
|
#include "OSXWindowData.h"
|
||||||
|
#include <MiniFB.h>
|
||||||
|
#include <MiniFB_enums.h>
|
||||||
|
#include <MiniFB_internal.h>
|
||||||
#include <Cocoa/Cocoa.h>
|
#include <Cocoa/Cocoa.h>
|
||||||
#if defined(USE_METAL_API)
|
#if defined(USE_METAL_API)
|
||||||
#include <Carbon/Carbon.h>
|
#include <Carbon/Carbon.h>
|
||||||
#include <MetalKit/MetalKit.h>
|
#include <MetalKit/MetalKit.h>
|
||||||
#endif
|
#endif
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "MiniFB.h"
|
|
||||||
|
SWindowData g_window_data = { 0 };
|
||||||
|
|
||||||
|
void init_keycodes();
|
||||||
|
|
||||||
#if defined(USE_METAL_API)
|
#if defined(USE_METAL_API)
|
||||||
extern id<MTLDevice> g_metal_device;
|
extern id<MTLDevice> g_metal_device;
|
||||||
@ -14,6 +21,13 @@ extern id<MTLCommandQueue> g_command_queue;
|
|||||||
extern id<MTLLibrary> g_library;
|
extern id<MTLLibrary> g_library;
|
||||||
extern id<MTLRenderPipelineState> g_pipeline_state;
|
extern id<MTLRenderPipelineState> g_pipeline_state;
|
||||||
|
|
||||||
|
Vertex gVertices[4] = {
|
||||||
|
{-1.0, -1.0, 0, 1},
|
||||||
|
{-1.0, 1.0, 0, 1},
|
||||||
|
{ 1.0, -1.0, 0, 1},
|
||||||
|
{ 1.0, 1.0, 0, 1},
|
||||||
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
NSString* g_shadersSrc = @
|
NSString* g_shadersSrc = @
|
||||||
@ -25,8 +39,7 @@ NSString* g_shadersSrc = @
|
|||||||
"float2 texcoord;\n"
|
"float2 texcoord;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
|
|
||||||
"vertex VertexOutput vertFunc(\n"
|
"vertex VertexOutput vertFunc(unsigned int vID[[vertex_id]])\n"
|
||||||
"unsigned int vID[[vertex_id]])\n"
|
|
||||||
"{\n"
|
"{\n"
|
||||||
"VertexOutput out;\n"
|
"VertexOutput out;\n"
|
||||||
|
|
||||||
@ -41,6 +54,23 @@ NSString* g_shadersSrc = @
|
|||||||
"return out;\n"
|
"return out;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|
||||||
|
"struct Vertex\n"
|
||||||
|
"{\n"
|
||||||
|
"float4 position [[position]];\n"
|
||||||
|
"};\n"
|
||||||
|
|
||||||
|
"vertex VertexOutput vertFunc2(unsigned int vID[[vertex_id]], device Vertex *pos [[buffer(0)]])\n"
|
||||||
|
"{\n"
|
||||||
|
"VertexOutput out;\n"
|
||||||
|
|
||||||
|
"out.pos = pos[vID].position;\n"
|
||||||
|
|
||||||
|
"out.texcoord.x = (float)(vID / 2);\n"
|
||||||
|
"out.texcoord.y = 1.0 - (float)(vID % 2);\n"
|
||||||
|
|
||||||
|
"return out;\n"
|
||||||
|
"}\n"
|
||||||
|
|
||||||
"fragment float4 fragFunc(VertexOutput input [[stage_in]],\n"
|
"fragment float4 fragFunc(VertexOutput input [[stage_in]],\n"
|
||||||
"texture2d<half> colorTexture [[ texture(0) ]])\n"
|
"texture2d<half> colorTexture [[ texture(0) ]])\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
@ -51,22 +81,13 @@ NSString* g_shadersSrc = @
|
|||||||
|
|
||||||
// We return the color of the texture
|
// We return the color of the texture
|
||||||
"return float4(colorSample);\n"
|
"return float4(colorSample);\n"
|
||||||
//"return half4(input.texcoord.x, input.texcoord.y, 0.0, 1.0);\n"
|
//"return float4(input.texcoord.x, input.texcoord.y, 0.0, 1.0);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if !defined(USE_METAL_API)
|
|
||||||
void* g_updateBuffer = 0;
|
|
||||||
int g_width = 0;
|
|
||||||
int g_height = 0;
|
|
||||||
#endif
|
|
||||||
static OSXWindow *s_window;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#if defined(USE_METAL_API)
|
#if defined(USE_METAL_API)
|
||||||
static bool create_shaders() {
|
static bool create_shaders() {
|
||||||
// Error
|
// Error
|
||||||
@ -86,7 +107,7 @@ static bool create_shaders() {
|
|||||||
g_library = library;
|
g_library = library;
|
||||||
NSLog(@"Names %@", [g_library functionNames]);
|
NSLog(@"Names %@", [g_library functionNames]);
|
||||||
|
|
||||||
id<MTLFunction> vertex_shader_func = [g_library newFunctionWithName:@"vertFunc"];
|
id<MTLFunction> vertex_shader_func = [g_library newFunctionWithName:@"vertFunc2"];
|
||||||
id<MTLFunction> fragment_shader_func = [g_library newFunctionWithName:@"fragFunc"];
|
id<MTLFunction> fragment_shader_func = [g_library newFunctionWithName:@"fragFunc"];
|
||||||
|
|
||||||
if (!vertex_shader_func) {
|
if (!vertex_shader_func) {
|
||||||
@ -120,13 +141,27 @@ static bool create_shaders() {
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int mfb_open(const char* name, int width, int height)
|
int mfb_open(const char* name, int width, int height)
|
||||||
|
{
|
||||||
|
return mfb_open_ex(name, width, height, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int mfb_open_ex(const char* name, int width, int height, int flags)
|
||||||
{
|
{
|
||||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
#if !defined(USE_METAL_API)
|
init_keycodes();
|
||||||
g_width = width;
|
|
||||||
g_height = height;
|
g_window_data.window_width = width;
|
||||||
#endif
|
g_window_data.window_height = height;
|
||||||
|
|
||||||
|
g_window_data.dst_width = width;
|
||||||
|
g_window_data.dst_height = height;
|
||||||
|
|
||||||
|
g_window_data.buffer_width = width;
|
||||||
|
g_window_data.buffer_height = height;
|
||||||
|
|
||||||
[NSApplication sharedApplication];
|
[NSApplication sharedApplication];
|
||||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||||
|
|
||||||
@ -143,18 +178,23 @@ int mfb_open(const char* name, int width, int height)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NSWindowStyleMask styles = NSWindowStyleMaskResizable | NSWindowStyleMaskClosable | NSWindowStyleMaskTitled;
|
NSWindowStyleMask styles = NSWindowStyleMaskClosable | NSWindowStyleMaskTitled;
|
||||||
|
|
||||||
|
if (flags & WF_BORDERLESS)
|
||||||
|
styles |= NSWindowStyleMaskBorderless;
|
||||||
|
|
||||||
|
if (flags & WF_RESIZABLE)
|
||||||
|
styles |= NSWindowStyleMaskResizable;
|
||||||
|
|
||||||
NSRect rectangle = NSMakeRect(0, 0, width, height);
|
NSRect rectangle = NSMakeRect(0, 0, width, height);
|
||||||
s_window = [[OSXWindow alloc] initWithContentRect:rectangle styleMask:styles backing:NSBackingStoreBuffered defer:NO];
|
g_window_data.window = [[OSXWindow alloc] initWithContentRect:rectangle styleMask:styles backing:NSBackingStoreBuffered defer:NO];
|
||||||
|
if (!g_window_data.window)
|
||||||
if (!s_window)
|
|
||||||
return -3;
|
return -3;
|
||||||
|
|
||||||
#if defined(USE_METAL_API)
|
#if defined(USE_METAL_API)
|
||||||
s_window->draw_buffer = malloc(width * height * 4);
|
g_window_data.draw_buffer = malloc(width * height * 4);
|
||||||
|
|
||||||
if (!s_window->draw_buffer)
|
if (!g_window_data.draw_buffer)
|
||||||
return -4;
|
return -4;
|
||||||
|
|
||||||
// Setup command queue
|
// Setup command queue
|
||||||
@ -180,7 +220,7 @@ int mfb_open(const char* name, int width, int height)
|
|||||||
|
|
||||||
// Used for syncing the CPU and GPU
|
// Used for syncing the CPU and GPU
|
||||||
viewController->m_semaphore = dispatch_semaphore_create(MaxBuffersInFlight);
|
viewController->m_semaphore = dispatch_semaphore_create(MaxBuffersInFlight);
|
||||||
viewController->m_draw_buffer = s_window->draw_buffer;
|
viewController->m_draw_buffer = g_window_data.draw_buffer;
|
||||||
viewController->m_width = width;
|
viewController->m_width = width;
|
||||||
viewController->m_height = height;
|
viewController->m_height = height;
|
||||||
|
|
||||||
@ -188,19 +228,20 @@ int mfb_open(const char* name, int width, int height)
|
|||||||
view.device = g_metal_device;
|
view.device = g_metal_device;
|
||||||
view.delegate = viewController;
|
view.delegate = viewController;
|
||||||
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||||
[s_window.contentView addSubview:view];
|
[g_window_data.window.contentView addSubview:view];
|
||||||
|
|
||||||
s_window->width = width;
|
g_window_data.buffer_width = width;
|
||||||
s_window->height = height;
|
g_window_data.buffer_height = height;
|
||||||
|
|
||||||
//[s_window updateSize];
|
//[g_window_data.window updateSize];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[s_window setTitle:[NSString stringWithUTF8String:name]];
|
[g_window_data.window setTitle:[NSString stringWithUTF8String:name]];
|
||||||
[s_window setReleasedWhenClosed:NO];
|
[g_window_data.window setReleasedWhenClosed:NO];
|
||||||
[s_window performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:nil waitUntilDone:YES];
|
[g_window_data.window performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:nil waitUntilDone:YES];
|
||||||
|
[g_window_data.window setAcceptsMouseMovedEvents:YES];
|
||||||
|
|
||||||
[s_window center];
|
[g_window_data.window center];
|
||||||
|
|
||||||
[NSApp activateIgnoringOtherApps:YES];
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
|
|
||||||
@ -208,6 +249,16 @@ int mfb_open(const char* name, int width, int height)
|
|||||||
[NSApp finishLaunching];
|
[NSApp finishLaunching];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (g_keyboard_func == 0x0) {
|
||||||
|
mfb_keyboard_callback(keyboard_default);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(USE_METAL_API)
|
||||||
|
NSLog(@"Window created using Metal API");
|
||||||
|
#else
|
||||||
|
NSLog(@"Window created using Cocoa API");
|
||||||
|
#endif
|
||||||
|
|
||||||
[pool drain];
|
[pool drain];
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -215,59 +266,231 @@ int mfb_open(const char* name, int width, int height)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void keyboard_default(void *user_data, Key key, KeyMod mod, bool isPressed) {
|
||||||
|
kUnused(user_data);
|
||||||
|
kUnused(mod);
|
||||||
|
kUnused(isPressed);
|
||||||
|
if (key == KB_KEY_ESCAPE)
|
||||||
|
g_window_data.close = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void mfb_close()
|
void mfb_close()
|
||||||
{
|
{
|
||||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
if (s_window)
|
g_window_data.close = true;
|
||||||
[s_window close];
|
if (g_window_data.window)
|
||||||
|
[g_window_data.window close];
|
||||||
|
|
||||||
[pool drain];
|
[pool drain];
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static int updateEvents()
|
static int update_events()
|
||||||
{
|
{
|
||||||
int state = 0;
|
NSEvent* event;
|
||||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES];
|
|
||||||
if (event)
|
|
||||||
{
|
|
||||||
switch ([event type])
|
|
||||||
{
|
|
||||||
case NSEventTypeKeyDown:
|
|
||||||
case NSEventTypeKeyUp:
|
|
||||||
{
|
|
||||||
state = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default :
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
do
|
||||||
{
|
{
|
||||||
|
event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES];
|
||||||
|
if (event) {
|
||||||
[NSApp sendEvent:event];
|
[NSApp sendEvent:event];
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while ((g_window_data.close == false) && event);
|
||||||
|
|
||||||
[pool release];
|
[pool release];
|
||||||
|
|
||||||
if (s_window->closed)
|
if(g_window_data.close == true)
|
||||||
state = -1;
|
return -1;
|
||||||
|
|
||||||
return state;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int mfb_update(void* buffer)
|
int mfb_update(void* buffer)
|
||||||
{
|
{
|
||||||
|
if(buffer == 0x0)
|
||||||
|
return -2;
|
||||||
|
|
||||||
#if defined(USE_METAL_API)
|
#if defined(USE_METAL_API)
|
||||||
memcpy(s_window->draw_buffer, buffer, s_window->width * s_window->height * 4);
|
memcpy(g_window_data.draw_buffer, buffer, g_window_data.buffer_width * g_window_data.buffer_height * 4);
|
||||||
#else
|
#else
|
||||||
g_updateBuffer = buffer;
|
g_window_data.draw_buffer = buffer;
|
||||||
#endif
|
#endif
|
||||||
int state = updateEvents();
|
|
||||||
[[s_window contentView] setNeedsDisplay:YES];
|
int state = update_events();
|
||||||
|
if(g_window_data.close == false)
|
||||||
|
[[g_window_data.window contentView] setNeedsDisplay:YES];
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool mfb_set_viewport(unsigned offset_x, unsigned offset_y, unsigned width, unsigned height)
|
||||||
|
{
|
||||||
|
if(offset_x + width > g_window_data.window_width) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(offset_y + height > g_window_data.window_height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_window_data.dst_offset_x = offset_x;
|
||||||
|
g_window_data.dst_offset_y = offset_y;
|
||||||
|
g_window_data.dst_width = width;
|
||||||
|
g_window_data.dst_height = height;
|
||||||
|
|
||||||
|
#if defined(USE_METAL_API)
|
||||||
|
float x1 = ((float) offset_x / g_window_data.window_width) * 2.0f - 1.0f;
|
||||||
|
float x2 = (((float) offset_x + width) / g_window_data.window_width) * 2.0f - 1.0f;
|
||||||
|
float y1 = ((float) offset_y / g_window_data.window_height) * 2.0f - 1.0f;
|
||||||
|
float y2 = (((float) offset_y + height) / g_window_data.window_height) * 2.0f - 1.0f;
|
||||||
|
|
||||||
|
gVertices[0].x = x1;
|
||||||
|
gVertices[0].y = y1;
|
||||||
|
|
||||||
|
gVertices[1].x = x1;
|
||||||
|
gVertices[1].y = y2;
|
||||||
|
|
||||||
|
gVertices[2].x = x2;
|
||||||
|
gVertices[2].y = y1;
|
||||||
|
|
||||||
|
gVertices[3].x = x2;
|
||||||
|
gVertices[3].y = y2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
extern short int keycodes[512];
|
||||||
|
|
||||||
|
void init_keycodes()
|
||||||
|
{
|
||||||
|
// Clear keys
|
||||||
|
for (unsigned int i = 0; i < sizeof(keycodes) / sizeof(keycodes[0]); ++i)
|
||||||
|
keycodes[i] = 0;
|
||||||
|
|
||||||
|
keycodes[0x1D] = KB_KEY_0;
|
||||||
|
keycodes[0x12] = KB_KEY_1;
|
||||||
|
keycodes[0x13] = KB_KEY_2;
|
||||||
|
keycodes[0x14] = KB_KEY_3;
|
||||||
|
keycodes[0x15] = KB_KEY_4;
|
||||||
|
keycodes[0x17] = KB_KEY_5;
|
||||||
|
keycodes[0x16] = KB_KEY_6;
|
||||||
|
keycodes[0x1A] = KB_KEY_7;
|
||||||
|
keycodes[0x1C] = KB_KEY_8;
|
||||||
|
keycodes[0x19] = KB_KEY_9;
|
||||||
|
keycodes[0x00] = KB_KEY_A;
|
||||||
|
keycodes[0x0B] = KB_KEY_B;
|
||||||
|
keycodes[0x08] = KB_KEY_C;
|
||||||
|
keycodes[0x02] = KB_KEY_D;
|
||||||
|
keycodes[0x0E] = KB_KEY_E;
|
||||||
|
keycodes[0x03] = KB_KEY_F;
|
||||||
|
keycodes[0x05] = KB_KEY_G;
|
||||||
|
keycodes[0x04] = KB_KEY_H;
|
||||||
|
keycodes[0x22] = KB_KEY_I;
|
||||||
|
keycodes[0x26] = KB_KEY_J;
|
||||||
|
keycodes[0x28] = KB_KEY_K;
|
||||||
|
keycodes[0x25] = KB_KEY_L;
|
||||||
|
keycodes[0x2E] = KB_KEY_M;
|
||||||
|
keycodes[0x2D] = KB_KEY_N;
|
||||||
|
keycodes[0x1F] = KB_KEY_O;
|
||||||
|
keycodes[0x23] = KB_KEY_P;
|
||||||
|
keycodes[0x0C] = KB_KEY_Q;
|
||||||
|
keycodes[0x0F] = KB_KEY_R;
|
||||||
|
keycodes[0x01] = KB_KEY_S;
|
||||||
|
keycodes[0x11] = KB_KEY_T;
|
||||||
|
keycodes[0x20] = KB_KEY_U;
|
||||||
|
keycodes[0x09] = KB_KEY_V;
|
||||||
|
keycodes[0x0D] = KB_KEY_W;
|
||||||
|
keycodes[0x07] = KB_KEY_X;
|
||||||
|
keycodes[0x10] = KB_KEY_Y;
|
||||||
|
keycodes[0x06] = KB_KEY_Z;
|
||||||
|
|
||||||
|
keycodes[0x27] = KB_KEY_APOSTROPHE;
|
||||||
|
keycodes[0x2A] = KB_KEY_BACKSLASH;
|
||||||
|
keycodes[0x2B] = KB_KEY_COMMA;
|
||||||
|
keycodes[0x18] = KB_KEY_EQUAL;
|
||||||
|
keycodes[0x32] = KB_KEY_GRAVE_ACCENT;
|
||||||
|
keycodes[0x21] = KB_KEY_LEFT_BRACKET;
|
||||||
|
keycodes[0x1B] = KB_KEY_MINUS;
|
||||||
|
keycodes[0x2F] = KB_KEY_PERIOD;
|
||||||
|
keycodes[0x1E] = KB_KEY_RIGHT_BRACKET;
|
||||||
|
keycodes[0x29] = KB_KEY_SEMICOLON;
|
||||||
|
keycodes[0x2C] = KB_KEY_SLASH;
|
||||||
|
keycodes[0x0A] = KB_KEY_WORLD_1;
|
||||||
|
|
||||||
|
keycodes[0x33] = KB_KEY_BACKSPACE;
|
||||||
|
keycodes[0x39] = KB_KEY_CAPS_LOCK;
|
||||||
|
keycodes[0x75] = KB_KEY_DELETE;
|
||||||
|
keycodes[0x7D] = KB_KEY_DOWN;
|
||||||
|
keycodes[0x77] = KB_KEY_END;
|
||||||
|
keycodes[0x24] = KB_KEY_ENTER;
|
||||||
|
keycodes[0x35] = KB_KEY_ESCAPE;
|
||||||
|
keycodes[0x7A] = KB_KEY_F1;
|
||||||
|
keycodes[0x78] = KB_KEY_F2;
|
||||||
|
keycodes[0x63] = KB_KEY_F3;
|
||||||
|
keycodes[0x76] = KB_KEY_F4;
|
||||||
|
keycodes[0x60] = KB_KEY_F5;
|
||||||
|
keycodes[0x61] = KB_KEY_F6;
|
||||||
|
keycodes[0x62] = KB_KEY_F7;
|
||||||
|
keycodes[0x64] = KB_KEY_F8;
|
||||||
|
keycodes[0x65] = KB_KEY_F9;
|
||||||
|
keycodes[0x6D] = KB_KEY_F10;
|
||||||
|
keycodes[0x67] = KB_KEY_F11;
|
||||||
|
keycodes[0x6F] = KB_KEY_F12;
|
||||||
|
keycodes[0x69] = KB_KEY_F13;
|
||||||
|
keycodes[0x6B] = KB_KEY_F14;
|
||||||
|
keycodes[0x71] = KB_KEY_F15;
|
||||||
|
keycodes[0x6A] = KB_KEY_F16;
|
||||||
|
keycodes[0x40] = KB_KEY_F17;
|
||||||
|
keycodes[0x4F] = KB_KEY_F18;
|
||||||
|
keycodes[0x50] = KB_KEY_F19;
|
||||||
|
keycodes[0x5A] = KB_KEY_F20;
|
||||||
|
keycodes[0x73] = KB_KEY_HOME;
|
||||||
|
keycodes[0x72] = KB_KEY_INSERT;
|
||||||
|
keycodes[0x7B] = KB_KEY_LEFT;
|
||||||
|
keycodes[0x3A] = KB_KEY_LEFT_ALT;
|
||||||
|
keycodes[0x3B] = KB_KEY_LEFT_CONTROL;
|
||||||
|
keycodes[0x38] = KB_KEY_LEFT_SHIFT;
|
||||||
|
keycodes[0x37] = KB_KEY_LEFT_SUPER;
|
||||||
|
keycodes[0x6E] = KB_KEY_MENU;
|
||||||
|
keycodes[0x47] = KB_KEY_NUM_LOCK;
|
||||||
|
keycodes[0x79] = KB_KEY_PAGE_DOWN;
|
||||||
|
keycodes[0x74] = KB_KEY_PAGE_UP;
|
||||||
|
keycodes[0x7C] = KB_KEY_RIGHT;
|
||||||
|
keycodes[0x3D] = KB_KEY_RIGHT_ALT;
|
||||||
|
keycodes[0x3E] = KB_KEY_RIGHT_CONTROL;
|
||||||
|
keycodes[0x3C] = KB_KEY_RIGHT_SHIFT;
|
||||||
|
keycodes[0x36] = KB_KEY_RIGHT_SUPER;
|
||||||
|
keycodes[0x31] = KB_KEY_SPACE;
|
||||||
|
keycodes[0x30] = KB_KEY_TAB;
|
||||||
|
keycodes[0x7E] = KB_KEY_UP;
|
||||||
|
|
||||||
|
keycodes[0x52] = KB_KEY_KP_0;
|
||||||
|
keycodes[0x53] = KB_KEY_KP_1;
|
||||||
|
keycodes[0x54] = KB_KEY_KP_2;
|
||||||
|
keycodes[0x55] = KB_KEY_KP_3;
|
||||||
|
keycodes[0x56] = KB_KEY_KP_4;
|
||||||
|
keycodes[0x57] = KB_KEY_KP_5;
|
||||||
|
keycodes[0x58] = KB_KEY_KP_6;
|
||||||
|
keycodes[0x59] = KB_KEY_KP_7;
|
||||||
|
keycodes[0x5B] = KB_KEY_KP_8;
|
||||||
|
keycodes[0x5C] = KB_KEY_KP_9;
|
||||||
|
keycodes[0x45] = KB_KEY_KP_ADD;
|
||||||
|
keycodes[0x41] = KB_KEY_KP_DECIMAL;
|
||||||
|
keycodes[0x4B] = KB_KEY_KP_DIVIDE;
|
||||||
|
keycodes[0x4C] = KB_KEY_KP_ENTER;
|
||||||
|
keycodes[0x51] = KB_KEY_KP_EQUAL;
|
||||||
|
keycodes[0x43] = KB_KEY_KP_MULTIPLY;
|
||||||
|
keycodes[0x4E] = KB_KEY_KP_SUBTRACT;
|
||||||
|
}
|
||||||
|
@ -2,15 +2,9 @@
|
|||||||
|
|
||||||
// @class OSXWindowFrameView;
|
// @class OSXWindowFrameView;
|
||||||
|
|
||||||
@interface OSXWindow : NSWindow
|
@interface OSXWindow : NSWindow<NSWindowDelegate>
|
||||||
{
|
{
|
||||||
NSView* childContentView;
|
NSView *childContentView;
|
||||||
@public bool closed;
|
|
||||||
#if defined(USE_METAL_API)
|
|
||||||
@public int width;
|
|
||||||
@public int height;
|
|
||||||
@public void* draw_buffer;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
#import "OSXWindow.h"
|
#import "OSXWindow.h"
|
||||||
#import "OSXWindowFrameView.h"
|
#import "OSXWindowFrameView.h"
|
||||||
|
#include "OSXWindowData.h"
|
||||||
|
#include <MiniFB_internal.h>
|
||||||
|
#include <MiniFB_enums.h>
|
||||||
|
|
||||||
|
extern SWindowData g_window_data;
|
||||||
|
extern short int g_keycodes[512];
|
||||||
|
|
||||||
|
bool gActive = false;
|
||||||
|
|
||||||
@implementation OSXWindow
|
@implementation OSXWindow
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if !defined(USE_METAL_API)
|
|
||||||
- (id)initWithContentRect:(NSRect)contentRect
|
- (id)initWithContentRect:(NSRect)contentRect
|
||||||
styleMask:(NSWindowStyleMask)windowStyle
|
styleMask:(NSWindowStyleMask)windowStyle
|
||||||
backing:(NSBackingStoreType)bufferingType
|
backing:(NSBackingStoreType)bufferingType
|
||||||
@ -16,34 +23,16 @@
|
|||||||
styleMask:windowStyle
|
styleMask:windowStyle
|
||||||
backing:bufferingType
|
backing:bufferingType
|
||||||
defer:deferCreation];
|
defer:deferCreation];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
[self setOpaque:YES];
|
[self setOpaque:YES];
|
||||||
[self setBackgroundColor:[NSColor clearColor]];
|
[self setBackgroundColor:[NSColor clearColor]];
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
self.delegate = self;
|
||||||
addObserver:self
|
|
||||||
selector:@selector(mainWindowChanged:)
|
|
||||||
name:NSWindowDidBecomeMainNotification
|
|
||||||
object:self];
|
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
|
||||||
addObserver:self
|
|
||||||
selector:@selector(mainWindowChanged:)
|
|
||||||
name:NSWindowDidResignMainNotification
|
|
||||||
object:self];
|
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
|
||||||
addObserver:self
|
|
||||||
selector:@selector(willClose)
|
|
||||||
name:NSWindowWillCloseNotification
|
|
||||||
object:self];
|
|
||||||
|
|
||||||
closed = false;
|
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -73,9 +62,113 @@
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
- (void)mainWindowChanged:(NSNotification *)aNotification
|
-(void)flagsChanged:(NSEvent *)event
|
||||||
{
|
{
|
||||||
(void)aNotification;
|
const uint32_t flags = [event modifierFlags];
|
||||||
|
uint32_t mod_keys = 0, mod_keys_aux = 0;
|
||||||
|
|
||||||
|
//NSEventModifierFlagHelp = 1 << 22,
|
||||||
|
//NSEventModifierFlagFunction = 1 << 23,
|
||||||
|
if(flags & NSEventModifierFlagCapsLock) {
|
||||||
|
mod_keys |= KB_MOD_CAPS_LOCK;
|
||||||
|
}
|
||||||
|
if(flags & NSEventModifierFlagShift) {
|
||||||
|
mod_keys |= KB_MOD_SHIFT;
|
||||||
|
}
|
||||||
|
if(flags & NSEventModifierFlagControl) {
|
||||||
|
mod_keys |= KB_MOD_CONTROL;
|
||||||
|
}
|
||||||
|
if(flags & NSEventModifierFlagOption) {
|
||||||
|
mod_keys |= KB_MOD_ALT;
|
||||||
|
}
|
||||||
|
if(flags & NSEventModifierFlagCommand) {
|
||||||
|
mod_keys |= KB_MOD_SUPER;
|
||||||
|
}
|
||||||
|
if(flags & NSEventModifierFlagNumericPad) {
|
||||||
|
mod_keys |= KB_MOD_NUM_LOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mod_keys != g_window_data.mod_keys) {
|
||||||
|
short int keyCode = keycodes[[event keyCode] & 0x1ff];
|
||||||
|
if(keyCode != KB_KEY_UNKNOWN) {
|
||||||
|
mod_keys_aux = mod_keys ^ g_window_data.mod_keys;
|
||||||
|
if(mod_keys_aux & KB_MOD_CAPS_LOCK) {
|
||||||
|
kCall(g_keyboard_func, keyCode, mod_keys, (mod_keys & KB_MOD_CAPS_LOCK) != 0);
|
||||||
|
}
|
||||||
|
if(mod_keys_aux & KB_MOD_SHIFT) {
|
||||||
|
kCall(g_keyboard_func, keyCode, mod_keys, (mod_keys & KB_MOD_SHIFT) != 0);
|
||||||
|
}
|
||||||
|
if(mod_keys_aux & KB_MOD_CONTROL) {
|
||||||
|
kCall(g_keyboard_func, keyCode, mod_keys, (mod_keys & KB_MOD_CONTROL) != 0);
|
||||||
|
}
|
||||||
|
if(mod_keys_aux & KB_MOD_ALT) {
|
||||||
|
kCall(g_keyboard_func, keyCode, mod_keys, (mod_keys & KB_MOD_ALT) != 0);
|
||||||
|
}
|
||||||
|
if(mod_keys_aux & KB_MOD_SUPER) {
|
||||||
|
kCall(g_keyboard_func, keyCode, mod_keys, (mod_keys & KB_MOD_SUPER) != 0);
|
||||||
|
}
|
||||||
|
if(mod_keys_aux & KB_MOD_NUM_LOCK) {
|
||||||
|
kCall(g_keyboard_func, keyCode, mod_keys, (mod_keys & KB_MOD_NUM_LOCK) != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_window_data.mod_keys = mod_keys;
|
||||||
|
//NSLog(@"KeyCode: %d (%x) - %x", [event keyCode], [event keyCode], flags);
|
||||||
|
|
||||||
|
[super flagsChanged:event];
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)keyDown:(NSEvent *)event
|
||||||
|
{
|
||||||
|
short int keyCode = keycodes[[event keyCode] & 0x1ff];
|
||||||
|
kCall(g_keyboard_func, keyCode, g_window_data.mod_keys, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)keyUp:(NSEvent *)event
|
||||||
|
{
|
||||||
|
short int keyCode = keycodes[[event keyCode] & 0x1ff];
|
||||||
|
kCall(g_keyboard_func, keyCode, g_window_data.mod_keys, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)insertText:(id)string replacementRange:(NSRange)replacementRange
|
||||||
|
{
|
||||||
|
NSString *characters;
|
||||||
|
NSUInteger length;
|
||||||
|
|
||||||
|
kUnused(replacementRange);
|
||||||
|
|
||||||
|
if ([string isKindOfClass:[NSAttributedString class]])
|
||||||
|
characters = [string string];
|
||||||
|
else
|
||||||
|
characters = (NSString*) string;
|
||||||
|
|
||||||
|
length = [characters length];
|
||||||
|
for (NSUInteger i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
const unichar code = [characters characterAtIndex:i];
|
||||||
|
if ((code & 0xff00) == 0xf700)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
kCall(g_char_input_func, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)mainWindowChanged:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
kUnused(notification);
|
||||||
|
|
||||||
|
if(gActive == true) {
|
||||||
|
gActive = false;
|
||||||
|
kCall(g_active_func, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -86,7 +179,6 @@
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSRect bounds = [self frame];
|
NSRect bounds = [self frame];
|
||||||
bounds.origin = NSZeroPoint;
|
bounds.origin = NSZeroPoint;
|
||||||
|
|
||||||
@ -122,6 +214,23 @@
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)windowDidBecomeKey:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
kUnused(notification);
|
||||||
|
kCall(g_active_func, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)windowDidResignKey:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
kUnused(notification);
|
||||||
|
kCall(g_active_func, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)windowWillClose:(NSNotification *)notification {
|
||||||
|
kUnused(notification);
|
||||||
|
g_window_data.close = true;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
- (BOOL)canBecomeMainWindow
|
- (BOOL)canBecomeMainWindow
|
||||||
@ -141,7 +250,7 @@
|
|||||||
|
|
||||||
+ (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSWindowStyleMask)windowStyle
|
+ (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSWindowStyleMask)windowStyle
|
||||||
{
|
{
|
||||||
(void)windowStyle;
|
kUnused(windowStyle);
|
||||||
return NSInsetRect(windowContentRect, 0, 0);
|
return NSInsetRect(windowContentRect, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +258,19 @@
|
|||||||
|
|
||||||
- (void)willClose
|
- (void)willClose
|
||||||
{
|
{
|
||||||
closed = true;
|
g_window_data.close = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)windowDidResize:(NSNotification *)notification {
|
||||||
|
kUnused(notification);
|
||||||
|
CGSize size = [self contentRectForFrameRect:[self frame]].size;
|
||||||
|
|
||||||
|
g_window_data.window_width = size.width;
|
||||||
|
g_window_data.window_height = size.height;
|
||||||
|
|
||||||
|
kCall(g_resize_func, size.width, size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
22
src/macosx/OSXWindowData.h
Normal file
22
src/macosx/OSXWindowData.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <MiniFB_enums.h>
|
||||||
|
|
||||||
|
@class OSXWindow;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
OSXWindow *window;
|
||||||
|
uint32_t window_width;
|
||||||
|
uint32_t window_height;
|
||||||
|
|
||||||
|
uint32_t dst_offset_x;
|
||||||
|
uint32_t dst_offset_y;
|
||||||
|
uint32_t dst_width;
|
||||||
|
uint32_t dst_height;
|
||||||
|
|
||||||
|
void *draw_buffer;
|
||||||
|
uint32_t buffer_width;
|
||||||
|
uint32_t buffer_height;
|
||||||
|
uint32_t mod_keys;
|
||||||
|
bool close;
|
||||||
|
} SWindowData;
|
@ -3,6 +3,10 @@
|
|||||||
#if defined(USE_METAL_API)
|
#if defined(USE_METAL_API)
|
||||||
#import <MetalKit/MetalKit.h>
|
#import <MetalKit/MetalKit.h>
|
||||||
|
|
||||||
|
typedef struct Vertex {
|
||||||
|
float x, y, z, w;
|
||||||
|
} Vertex;
|
||||||
|
|
||||||
// Number of textures in flight (tripple buffered)
|
// Number of textures in flight (tripple buffered)
|
||||||
static const int MaxBuffersInFlight = 3;
|
static const int MaxBuffersInFlight = 3;
|
||||||
|
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
#import "OSXWindowFrameView.h"
|
#import "OSXWindowFrameView.h"
|
||||||
|
#import "OSXWindow.h"
|
||||||
|
#include "OSXWindowData.h"
|
||||||
|
#include <MiniFB_internal.h>
|
||||||
|
|
||||||
|
extern SWindowData g_window_data;
|
||||||
|
|
||||||
#if defined(USE_METAL_API)
|
#if defined(USE_METAL_API)
|
||||||
#import <MetalKit/MetalKit.h>
|
#import <MetalKit/MetalKit.h>
|
||||||
@ -8,6 +13,8 @@ id<MTLCommandQueue> g_command_queue;
|
|||||||
id<MTLLibrary> g_library;
|
id<MTLLibrary> g_library;
|
||||||
id<MTLRenderPipelineState> g_pipeline_state;
|
id<MTLRenderPipelineState> g_pipeline_state;
|
||||||
|
|
||||||
|
extern Vertex gVertices[4];
|
||||||
|
|
||||||
@implementation WindowViewController
|
@implementation WindowViewController
|
||||||
|
|
||||||
-(void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
|
-(void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
|
||||||
@ -54,7 +61,7 @@ id<MTLRenderPipelineState> g_pipeline_state;
|
|||||||
|
|
||||||
if (renderPassDescriptor != nil)
|
if (renderPassDescriptor != nil)
|
||||||
{
|
{
|
||||||
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0, 0.0, 0.0, 1.0);
|
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
// Create a render command encoder so we can render into something
|
// Create a render command encoder so we can render into something
|
||||||
id<MTLRenderCommandEncoder> renderEncoder =
|
id<MTLRenderCommandEncoder> renderEncoder =
|
||||||
@ -64,12 +71,19 @@ id<MTLRenderPipelineState> g_pipeline_state;
|
|||||||
// Set render command encoder state
|
// Set render command encoder state
|
||||||
[renderEncoder setRenderPipelineState:g_pipeline_state];
|
[renderEncoder setRenderPipelineState:g_pipeline_state];
|
||||||
|
|
||||||
|
[renderEncoder setVertexBytes:gVertices
|
||||||
|
length:sizeof(gVertices)
|
||||||
|
atIndex:0];
|
||||||
|
|
||||||
[renderEncoder setFragmentTexture:m_texture_buffers[m_current_buffer] atIndex:0];
|
[renderEncoder setFragmentTexture:m_texture_buffers[m_current_buffer] atIndex:0];
|
||||||
|
|
||||||
// Draw the vertices of our quads
|
// Draw the vertices of our quads
|
||||||
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
|
// [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
|
||||||
|
// vertexStart:0
|
||||||
|
// vertexCount:3];
|
||||||
|
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip
|
||||||
vertexStart:0
|
vertexStart:0
|
||||||
vertexCount:3];
|
vertexCount:4];
|
||||||
|
|
||||||
// We're done encoding commands
|
// We're done encoding commands
|
||||||
[renderEncoder endEncoding];
|
[renderEncoder endEncoding];
|
||||||
@ -104,9 +118,6 @@ id<MTLRenderPipelineState> g_pipeline_state;
|
|||||||
[self addTrackingArea:trackingArea];
|
[self addTrackingArea:trackingArea];
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
extern void* g_updateBuffer;
|
|
||||||
extern int g_width;
|
|
||||||
extern int g_height;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -131,25 +142,178 @@ extern int g_height;
|
|||||||
{
|
{
|
||||||
(void)rect;
|
(void)rect;
|
||||||
|
|
||||||
if (!g_updateBuffer)
|
if (!g_window_data.window || !g_window_data.draw_buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
|
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
|
||||||
|
|
||||||
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
|
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
|
||||||
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, g_updateBuffer, g_width * g_height * 4, NULL);
|
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, g_window_data.draw_buffer, g_window_data.buffer_width * g_window_data.buffer_height * 4, NULL);
|
||||||
|
|
||||||
CGImageRef img = CGImageCreate(g_width, g_height, 8, 32, g_width * 4, space, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
|
CGImageRef img = CGImageCreate(g_window_data.buffer_width, g_window_data.buffer_height, 8, 32, g_window_data.buffer_width * 4, space, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
|
||||||
provider, NULL, false, kCGRenderingIntentDefault);
|
provider, NULL, false, kCGRenderingIntentDefault);
|
||||||
|
|
||||||
|
const CGFloat components[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
const CGColorRef black = CGColorCreate(space, components);
|
||||||
|
|
||||||
CGColorSpaceRelease(space);
|
CGColorSpaceRelease(space);
|
||||||
CGDataProviderRelease(provider);
|
CGDataProviderRelease(provider);
|
||||||
|
|
||||||
CGContextDrawImage(context, CGRectMake(0, 0, g_width, g_height), img);
|
if(g_window_data.dst_offset_x != 0 || g_window_data.dst_offset_y != 0 || g_window_data.dst_width != g_window_data.window_width || g_window_data.dst_height != g_window_data.window_height) {
|
||||||
|
CGContextSetFillColorWithColor(context, black);
|
||||||
|
CGContextFillRect(context, CGRectMake(0, 0, g_window_data.window_width, g_window_data.window_height));
|
||||||
|
}
|
||||||
|
|
||||||
|
CGContextDrawImage(context, CGRectMake(g_window_data.dst_offset_x, g_window_data.dst_offset_y, g_window_data.dst_width, g_window_data.dst_height), img);
|
||||||
|
|
||||||
CGImageRelease(img);
|
CGImageRelease(img);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (BOOL)acceptsFirstMouse:(NSEvent *)event
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)mouseDown:(NSEvent*)event
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
kCall(g_mouse_btn_func, MOUSE_BTN_1, g_window_data.mod_keys, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)mouseUp:(NSEvent*)event
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
kCall(g_mouse_btn_func, MOUSE_BTN_1, g_window_data.mod_keys, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)rightMouseDown:(NSEvent*)event
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
kCall(g_mouse_btn_func, MOUSE_BTN_2, g_window_data.mod_keys, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)rightMouseUp:(NSEvent*)event
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
kCall(g_mouse_btn_func, MOUSE_BTN_1, g_window_data.mod_keys, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)otherMouseDown:(NSEvent *)event
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
kCall(g_mouse_btn_func, [event buttonNumber], g_window_data.mod_keys, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)otherMouseUp:(NSEvent *)event
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
kCall(g_mouse_btn_func, [event buttonNumber], g_window_data.mod_keys, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)scrollWheel:(NSEvent *)event
|
||||||
|
{
|
||||||
|
kCall(g_mouse_wheel_func, g_window_data.mod_keys, [event deltaX], [event deltaY]);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)mouseDragged:(NSEvent *)event
|
||||||
|
{
|
||||||
|
[self mouseMoved:event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rightMouseDragged:(NSEvent *)event
|
||||||
|
{
|
||||||
|
[self mouseMoved:event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)otherMouseDragged:(NSEvent *)event
|
||||||
|
{
|
||||||
|
[self mouseMoved:event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseMoved:(NSEvent *)event
|
||||||
|
{
|
||||||
|
NSPoint point = [event locationInWindow];
|
||||||
|
//NSPoint localPoint = [self convertPoint:point fromView:nil];
|
||||||
|
kCall(g_mouse_move_func, point.x, point.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)mouseExited:(NSEvent *)event
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
//printf("mouse exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)mouseEntered:(NSEvent *)event
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
//printf("mouse enter\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (BOOL)canBecomeKeyView
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (NSView *)nextValidKeyView
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (NSView *)previousValidKeyView
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (BOOL)acceptsFirstResponder
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)viewDidMoveToWindow
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
#include <MiniFB.h>
|
#include <MiniFB.h>
|
||||||
|
#include "MiniFB_internal.h"
|
||||||
|
#include "MiniFB_enums.h"
|
||||||
|
#include "WaylandWindowData.h"
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -10,47 +14,34 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
static struct wl
|
SWindowData g_window_data = { 0 };
|
||||||
{
|
|
||||||
struct wl_display *display;
|
|
||||||
struct wl_registry *registry;
|
|
||||||
struct wl_compositor *compositor;
|
|
||||||
struct wl_shell *shell;
|
|
||||||
struct wl_seat *seat;
|
|
||||||
struct wl_keyboard *keyboard;
|
|
||||||
struct wl_shm *shm;
|
|
||||||
struct wl_shm_pool *shm_pool;
|
|
||||||
struct wl_surface *surface;
|
|
||||||
struct wl_shell_surface *shell_surface;
|
|
||||||
|
|
||||||
uint32_t seat_version;
|
static void
|
||||||
uint32_t shm_format;
|
destroy(void)
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
uint32_t stride;
|
|
||||||
uint32_t *shm_ptr;
|
|
||||||
struct wl_buffer *buffer;
|
|
||||||
int should_close;
|
|
||||||
} wl;
|
|
||||||
|
|
||||||
static void destroy(void)
|
|
||||||
{
|
{
|
||||||
if (! wl.display)
|
if (! g_window_data.display)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#define KILL(NAME) \
|
#define KILL(NAME) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
if (wl.NAME) \
|
if (g_window_data.NAME) \
|
||||||
wl_##NAME##_destroy(wl.NAME); \
|
wl_##NAME##_destroy(g_window_data.NAME); \
|
||||||
} while (0)
|
} while (0); \
|
||||||
|
g_window_data.NAME = 0x0;
|
||||||
|
|
||||||
KILL(shell_surface);
|
KILL(shell_surface);
|
||||||
KILL(shell);
|
KILL(shell);
|
||||||
KILL(surface);
|
KILL(surface);
|
||||||
KILL(buffer);
|
//KILL(buffer);
|
||||||
|
if(g_window_data.draw_buffer) {
|
||||||
|
wl_buffer_destroy(g_window_data.draw_buffer);
|
||||||
|
g_window_data.draw_buffer = 0x0;
|
||||||
|
}
|
||||||
KILL(shm_pool);
|
KILL(shm_pool);
|
||||||
KILL(shm);
|
KILL(shm);
|
||||||
KILL(compositor);
|
KILL(compositor);
|
||||||
@ -58,62 +49,384 @@ static void destroy(void)
|
|||||||
KILL(seat);
|
KILL(seat);
|
||||||
KILL(registry);
|
KILL(registry);
|
||||||
#undef KILL
|
#undef KILL
|
||||||
wl_display_disconnect(wl.display);
|
wl_display_disconnect(g_window_data.display);
|
||||||
memset(&wl, 0, sizeof(wl));
|
memset(&g_window_data, 0, sizeof(SWindowData));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nop() {}
|
// This event provides a file descriptor to the client which can be memory-mapped
|
||||||
|
// to provide a keyboard mapping description.
|
||||||
#define NO_FUNC (void (*)()) nop
|
// format: keymap format
|
||||||
|
// fd: keymap file descriptor
|
||||||
static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard,
|
// size: keymap size, in bytes
|
||||||
uint32_t serial, uint32_t time, uint32_t key,
|
static void
|
||||||
uint32_t state)
|
keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size)
|
||||||
{
|
{
|
||||||
if (state == WL_KEYBOARD_KEY_STATE_RELEASED && key == KEY_ESC)
|
kUnused(data);
|
||||||
|
kUnused(keyboard);
|
||||||
|
kUnused(format);
|
||||||
|
kUnused(fd);
|
||||||
|
kUnused(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notification that this seat's keyboard focus is on a certain surface.
|
||||||
|
// serial: serial number of the enter event
|
||||||
|
// surface: surface gaining keyboard focus
|
||||||
|
// keys: the currently pressed keys
|
||||||
|
static void
|
||||||
|
keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(keyboard);
|
||||||
|
kUnused(serial);
|
||||||
|
kUnused(surface);
|
||||||
|
kUnused(keys);
|
||||||
|
kCall(g_active_func, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The leave notification is sent before the enter notification for the new focus.
|
||||||
|
// serial: serial number of the leave event
|
||||||
|
// surface: surface that lost keyboard focus
|
||||||
|
static void
|
||||||
|
keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(keyboard);
|
||||||
|
kUnused(serial);
|
||||||
|
kUnused(surface);
|
||||||
|
kCall(g_active_func, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A key was pressed or released. The time argument is a timestamp with
|
||||||
|
// millisecond granularity, with an undefined base.
|
||||||
|
// serial: serial number of the key event
|
||||||
|
// time: timestamp with millisecond granularity
|
||||||
|
// key: key that produced the event
|
||||||
|
// state: physical state of the key
|
||||||
|
static void
|
||||||
|
keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(keyboard);
|
||||||
|
kUnused(serial);
|
||||||
|
kUnused(time);
|
||||||
|
if(key < 512) {
|
||||||
|
Key kb_key = (Key) keycodes[key];
|
||||||
|
bool is_pressed = (bool) (state == WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||||
|
switch (kb_key)
|
||||||
{
|
{
|
||||||
wl.should_close = 1;
|
case KB_KEY_LEFT_SHIFT:
|
||||||
|
case KB_KEY_RIGHT_SHIFT:
|
||||||
|
if(is_pressed)
|
||||||
|
g_window_data.mod_keys |= KB_MOD_SHIFT;
|
||||||
|
else
|
||||||
|
g_window_data.mod_keys &= ~KB_MOD_SHIFT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_CONTROL:
|
||||||
|
case KB_KEY_RIGHT_CONTROL:
|
||||||
|
if(is_pressed)
|
||||||
|
g_window_data.mod_keys |= KB_MOD_CONTROL;
|
||||||
|
else
|
||||||
|
g_window_data.mod_keys &= ~KB_MOD_CONTROL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_ALT:
|
||||||
|
case KB_KEY_RIGHT_ALT:
|
||||||
|
if(is_pressed)
|
||||||
|
g_window_data.mod_keys |= KB_MOD_ALT;
|
||||||
|
else
|
||||||
|
g_window_data.mod_keys &= ~KB_MOD_ALT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_SUPER:
|
||||||
|
case KB_KEY_RIGHT_SUPER:
|
||||||
|
if(is_pressed)
|
||||||
|
g_window_data.mod_keys |= KB_MOD_SUPER;
|
||||||
|
else
|
||||||
|
g_window_data.mod_keys &= ~KB_MOD_SUPER;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kCall(g_keyboard_func, kb_key, (KeyMod)g_window_data.mod_keys, is_pressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notifies clients that the modifier and/or group state has changed,
|
||||||
|
// and it should update its local state.
|
||||||
|
// serial: serial number of the modifiers event
|
||||||
|
// mods_depressed: depressed modifiers
|
||||||
|
// mods_latched: latched modifiers
|
||||||
|
// mods_locked: locked modifiers
|
||||||
|
// group: keyboard layout
|
||||||
|
static void
|
||||||
|
keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(keyboard);
|
||||||
|
kUnused(serial);
|
||||||
|
kUnused(mods_depressed);
|
||||||
|
kUnused(mods_latched);
|
||||||
|
kUnused(mods_locked);
|
||||||
|
kUnused(group);
|
||||||
|
// it is not easy to identify them here :(
|
||||||
|
}
|
||||||
|
|
||||||
|
// Informs the client about the keyboard's repeat rate and delay.
|
||||||
|
// rate: the rate of repeating keys in characters per second
|
||||||
|
// delay: delay in milliseconds since key down until repeating starts
|
||||||
|
static void
|
||||||
|
keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(keyboard);
|
||||||
|
kUnused(rate);
|
||||||
|
kUnused(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_keyboard_listener keyboard_listener = {
|
static const struct wl_keyboard_listener keyboard_listener = {
|
||||||
.keymap = NO_FUNC,
|
.keymap = keyboard_keymap,
|
||||||
.enter = NO_FUNC,
|
.enter = keyboard_enter,
|
||||||
.leave = NO_FUNC,
|
.leave = keyboard_leave,
|
||||||
.key = keyboard_key,
|
.key = keyboard_key,
|
||||||
.modifiers = NO_FUNC,
|
.modifiers = keyboard_modifiers,
|
||||||
.repeat_info = NO_FUNC,
|
.repeat_info = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void seat_capabilities(void *data, struct wl_seat *seat,
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
enum wl_seat_capability caps)
|
|
||||||
|
// Notification that this seat's pointer is focused on a certain surface.
|
||||||
|
//
|
||||||
|
// When a seat's focus enters a surface, the pointer image is
|
||||||
|
// undefined and a client should respond to this event by setting
|
||||||
|
// an appropriate pointer image with the set_cursor request.
|
||||||
|
//
|
||||||
|
// serial: serial number of the enter event
|
||||||
|
// surface: surface entered by the pointer
|
||||||
|
// sx: surface-local x coordinate
|
||||||
|
// sy: surface-local y coordinate
|
||||||
|
static void
|
||||||
|
pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy)
|
||||||
{
|
{
|
||||||
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wl.keyboard)
|
kUnused(data);
|
||||||
{
|
//kUnused(pointer);
|
||||||
wl.keyboard = wl_seat_get_keyboard(seat);
|
//kUnused(serial);
|
||||||
wl_keyboard_add_listener(wl.keyboard, &keyboard_listener, NULL);
|
kUnused(surface);
|
||||||
|
kUnused(sx);
|
||||||
|
kUnused(sy);
|
||||||
|
struct wl_buffer *buffer;
|
||||||
|
struct wl_cursor_image *image;
|
||||||
|
|
||||||
|
image = g_window_data.default_cursor->images[0];
|
||||||
|
buffer = wl_cursor_image_get_buffer(image);
|
||||||
|
|
||||||
|
wl_pointer_set_cursor(pointer, serial, g_window_data.cursor_surface, image->hotspot_x, image->hotspot_y);
|
||||||
|
wl_surface_attach(g_window_data.cursor_surface, buffer, 0, 0);
|
||||||
|
wl_surface_damage(g_window_data.cursor_surface, 0, 0, image->width, image->height);
|
||||||
|
wl_surface_commit(g_window_data.cursor_surface);
|
||||||
|
//fprintf(stderr, "Pointer entered surface %p at %d %d\n", surface, sx, sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notification that this seat's pointer is no longer focused on a certain surface.
|
||||||
|
//
|
||||||
|
// The leave notification is sent before the enter notification for the new focus.
|
||||||
|
//
|
||||||
|
// serial: serial number of the leave event
|
||||||
|
// surface: surface left by the pointer
|
||||||
|
static void
|
||||||
|
pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(pointer);
|
||||||
|
kUnused(serial);
|
||||||
|
kUnused(surface);
|
||||||
|
//fprintf(stderr, "Pointer left surface %p\n", surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notification of pointer location change.
|
||||||
|
//
|
||||||
|
// The arguments sx and sy are the location relative to the focused surface.
|
||||||
|
//
|
||||||
|
// time: timestamp with millisecond granularity
|
||||||
|
// sx: surface-local x coordinate
|
||||||
|
// sy: surface-local y coordinate
|
||||||
|
static void
|
||||||
|
pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(pointer);
|
||||||
|
kUnused(time);
|
||||||
|
//printf("Pointer moved at %f %f\n", sx / 256.0f, sy / 256.0f);
|
||||||
|
kCall(g_mouse_move_func, sx >> 24, sy >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse button click and release notifications.
|
||||||
|
//
|
||||||
|
// The location of the click is given by the last motion or enter
|
||||||
|
// event. The time argument is a timestamp with millisecond
|
||||||
|
// granularity, with an undefined base.
|
||||||
|
//
|
||||||
|
// The button is a button code as defined in the Linux kernel's
|
||||||
|
// linux/input-event-codes.h header file, e.g. BTN_LEFT.
|
||||||
|
//
|
||||||
|
// Any 16-bit button code value is reserved for future additions to
|
||||||
|
// the kernel's event code list. All other button codes above
|
||||||
|
// 0xFFFF are currently undefined but may be used in future
|
||||||
|
// versions of this protocol.
|
||||||
|
//
|
||||||
|
// serial: serial number of the button event
|
||||||
|
// time: timestamp with millisecond granularity
|
||||||
|
// button: button that produced the event
|
||||||
|
// state: physical state of the button
|
||||||
|
static void
|
||||||
|
pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(pointer);
|
||||||
|
kUnused(serial);
|
||||||
|
kUnused(time);
|
||||||
|
//printf("Pointer button '%d'(%d)\n", button, state);
|
||||||
|
kCall(g_mouse_btn_func, button - BTN_MOUSE + 1, g_window_data.mod_keys, state == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll and other axis notifications.
|
||||||
|
//
|
||||||
|
// For scroll events (vertical and horizontal scroll axes), the
|
||||||
|
// value parameter is the length of a vector along the specified
|
||||||
|
// axis in a coordinate space identical to those of motion events,
|
||||||
|
// representing a relative movement along the specified axis.
|
||||||
|
//
|
||||||
|
// For devices that support movements non-parallel to axes multiple
|
||||||
|
// axis events will be emitted.
|
||||||
|
//
|
||||||
|
// When applicable, for example for touch pads, the server can
|
||||||
|
// choose to emit scroll events where the motion vector is
|
||||||
|
// equivalent to a motion event vector.
|
||||||
|
//
|
||||||
|
// When applicable, a client can transform its content relative to
|
||||||
|
// the scroll distance.
|
||||||
|
//
|
||||||
|
// time: timestamp with millisecond granularity
|
||||||
|
// axis: axis type
|
||||||
|
// value: length of vector in surface-local coordinate space
|
||||||
|
static void
|
||||||
|
pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(pointer);
|
||||||
|
kUnused(time);
|
||||||
|
kUnused(axis);
|
||||||
|
//printf("Pointer handle axis: axis: %d (0x%x)\n", axis, value);
|
||||||
|
if(axis == 0) {
|
||||||
|
kCall(g_mouse_wheel_func, g_window_data.mod_keys, 0.0f, -(value / 256.0f));
|
||||||
}
|
}
|
||||||
else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wl.keyboard)
|
else if(axis == 1) {
|
||||||
{
|
kCall(g_mouse_wheel_func, g_window_data.mod_keys, -(value / 256.0f), 0.0f);
|
||||||
wl_keyboard_destroy(wl.keyboard);
|
|
||||||
wl.keyboard = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_seat_listener seat_listener = {
|
static void
|
||||||
.capabilities = seat_capabilities, .name = NO_FUNC,
|
frame(void *data, struct wl_pointer *pointer) {
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
axis_source(void *data, struct wl_pointer *pointer, uint32_t axis_source) {
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(pointer);
|
||||||
|
kUnused(axis_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
axis_stop(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis) {
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(pointer);
|
||||||
|
kUnused(time);
|
||||||
|
kUnused(axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
axis_discrete(void *data, struct wl_pointer *pointer, uint32_t axis, int32_t discrete) {
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(pointer);
|
||||||
|
kUnused(axis);
|
||||||
|
kUnused(discrete);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_pointer_listener pointer_listener = {
|
||||||
|
.enter = pointer_enter,
|
||||||
|
.leave = pointer_leave,
|
||||||
|
.motion = pointer_motion,
|
||||||
|
.button = pointer_button,
|
||||||
|
.axis = pointer_axis,
|
||||||
|
.frame = NULL,
|
||||||
|
.axis_source = NULL,
|
||||||
|
.axis_stop = NULL,
|
||||||
|
.axis_discrete = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void shm_format(void *data, struct wl_shm *shm, uint32_t format)
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void
|
||||||
|
seat_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps)
|
||||||
{
|
{
|
||||||
if (wl.shm_format == -1u)
|
kUnused(data);
|
||||||
|
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !g_window_data.keyboard)
|
||||||
|
{
|
||||||
|
g_window_data.keyboard = wl_seat_get_keyboard(seat);
|
||||||
|
wl_keyboard_add_listener(g_window_data.keyboard, &keyboard_listener, NULL);
|
||||||
|
}
|
||||||
|
else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && g_window_data.keyboard)
|
||||||
|
{
|
||||||
|
wl_keyboard_destroy(g_window_data.keyboard);
|
||||||
|
g_window_data.keyboard = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !g_window_data.pointer)
|
||||||
|
{
|
||||||
|
g_window_data.pointer = wl_seat_get_pointer(seat);
|
||||||
|
wl_pointer_add_listener(g_window_data.pointer, &pointer_listener, NULL);
|
||||||
|
}
|
||||||
|
else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && g_window_data.pointer)
|
||||||
|
{
|
||||||
|
wl_pointer_destroy(g_window_data.pointer);
|
||||||
|
g_window_data.pointer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
seat_name(void *data, struct wl_seat *seat, const char *name) {
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(seat);
|
||||||
|
printf("Seat '%s'n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_seat_listener seat_listener = {
|
||||||
|
.capabilities = seat_capabilities,
|
||||||
|
.name = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// pixel format description
|
||||||
|
//
|
||||||
|
// Informs the client about a valid pixel format that can be used
|
||||||
|
// for buffers. Known formats include argb8888 and xrgb8888.
|
||||||
|
//
|
||||||
|
// format: buffer pixel format
|
||||||
|
static void
|
||||||
|
shm_format(void *data, struct wl_shm *shm, uint32_t format)
|
||||||
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(shm);
|
||||||
|
if (g_window_data.shm_format == -1u)
|
||||||
{
|
{
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
// We could do RGBA, but that would not be what is expected from minifb...
|
// We could do RGBA, but that would not be what is expected from minifb...
|
||||||
/* case WL_SHM_FORMAT_ARGB8888: */
|
// case WL_SHM_FORMAT_ARGB8888:
|
||||||
case WL_SHM_FORMAT_XRGB8888:
|
case WL_SHM_FORMAT_XRGB8888:
|
||||||
wl.shm_format = format;
|
g_window_data.shm_format = format;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -122,65 +435,87 @@ static void shm_format(void *data, struct wl_shm *shm, uint32_t format)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_shm_listener shm_listener = {.format = shm_format};
|
static const struct wl_shm_listener shm_listener = {
|
||||||
|
.format = shm_format
|
||||||
|
};
|
||||||
|
|
||||||
static void registry_global(void *data, struct wl_registry *registry,
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
uint32_t id, char const *iface, uint32_t version)
|
|
||||||
|
static void
|
||||||
|
registry_global(void *data, struct wl_registry *registry, uint32_t id, char const *iface, uint32_t version)
|
||||||
{
|
{
|
||||||
|
kUnused(data);
|
||||||
|
kUnused(version);
|
||||||
if (strcmp(iface, "wl_compositor") == 0)
|
if (strcmp(iface, "wl_compositor") == 0)
|
||||||
{
|
{
|
||||||
wl.compositor =
|
g_window_data.compositor = (struct wl_compositor *) wl_registry_bind(registry, id, &wl_compositor_interface, 1);
|
||||||
wl_registry_bind(registry, id, &wl_compositor_interface, 1);
|
|
||||||
}
|
}
|
||||||
else if (strcmp(iface, "wl_shm") == 0)
|
else if (strcmp(iface, "wl_shm") == 0)
|
||||||
{
|
{
|
||||||
wl.shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
g_window_data.shm = (struct wl_shm *) wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
||||||
if (wl.shm)
|
if (g_window_data.shm) {
|
||||||
wl_shm_add_listener(wl.shm, &shm_listener, NULL);
|
wl_shm_add_listener(g_window_data.shm, &shm_listener, NULL);
|
||||||
|
g_window_data.cursor_theme = wl_cursor_theme_load(NULL, 32, g_window_data.shm);
|
||||||
|
g_window_data.default_cursor = wl_cursor_theme_get_cursor(g_window_data.cursor_theme, "left_ptr");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(iface, "wl_shell") == 0)
|
else if (strcmp(iface, "wl_shell") == 0)
|
||||||
{
|
{
|
||||||
wl.shell = wl_registry_bind(registry, id, &wl_shell_interface, 1);
|
g_window_data.shell = (struct wl_shell *) wl_registry_bind(registry, id, &wl_shell_interface, 1);
|
||||||
}
|
}
|
||||||
else if (strcmp(iface, "wl_seat") == 0)
|
else if (strcmp(iface, "wl_seat") == 0)
|
||||||
{
|
{
|
||||||
wl.seat = wl_registry_bind(registry, id, &wl_seat_interface, 1);
|
g_window_data.seat = (struct wl_seat *) wl_registry_bind(registry, id, &wl_seat_interface, 1);
|
||||||
if (wl.seat)
|
if (g_window_data.seat)
|
||||||
{
|
{
|
||||||
wl_seat_add_listener(wl.seat, &seat_listener, NULL);
|
wl_seat_add_listener(g_window_data.seat, &seat_listener, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_registry_listener registry_listener = {
|
static const struct wl_registry_listener registry_listener = {
|
||||||
.global = registry_global, .global_remove = NO_FUNC,
|
.global = registry_global,
|
||||||
|
.global_remove = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
int mfb_open(const char *title, int width, int height)
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int
|
||||||
|
mfb_open_ex(const char* title, int width, int height, int flags) {
|
||||||
|
// TODO: Not yet
|
||||||
|
kUnused(flags);
|
||||||
|
return mfb_open(title, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mfb_open(const char *title, int width, int height)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
|
||||||
wl.display = wl_display_connect(NULL);
|
g_window_data.shm_format = -1u;
|
||||||
if (!wl.display)
|
|
||||||
|
g_window_data.display = wl_display_connect(NULL);
|
||||||
|
if (!g_window_data.display)
|
||||||
return -1;
|
return -1;
|
||||||
wl.registry = wl_display_get_registry(wl.display);
|
g_window_data.registry = wl_display_get_registry(g_window_data.display);
|
||||||
wl_registry_add_listener(wl.registry, ®istry_listener, NULL);
|
wl_registry_add_listener(g_window_data.registry, ®istry_listener, NULL);
|
||||||
if (wl_display_roundtrip(wl.display) == -1 ||
|
|
||||||
wl_display_roundtrip(wl.display) == -1)
|
init_keycodes();
|
||||||
|
|
||||||
|
if (wl_display_dispatch(g_window_data.display) == -1 || wl_display_roundtrip(g_window_data.display) == -1)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// did not get a format we want... meh
|
// did not get a format we want... meh
|
||||||
if (wl.shm_format == -1)
|
if (g_window_data.shm_format == -1u)
|
||||||
goto out;
|
goto out;
|
||||||
if (!wl.compositor)
|
if (!g_window_data.compositor)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
char const *xdg_rt_dir = getenv("XDG_RUNTIME_DIR");
|
char const *xdg_rt_dir = getenv("XDG_RUNTIME_DIR");
|
||||||
char shmfile[PATH_MAX];
|
char shmfile[PATH_MAX];
|
||||||
int ret = snprintf(shmfile, sizeof(shmfile), "%s/WaylandMiniFB-SHM-XXXXXX",
|
uint32_t ret = snprintf(shmfile, sizeof(shmfile), "%s/WaylandMiniFB-SHM-XXXXXX", xdg_rt_dir);
|
||||||
xdg_rt_dir);
|
|
||||||
if (ret >= sizeof(shmfile))
|
if (ret >= sizeof(shmfile))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -194,38 +529,54 @@ int mfb_open(const char *title, int width, int height)
|
|||||||
if (ftruncate(fd, length) == -1)
|
if (ftruncate(fd, length) == -1)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
wl.shm_ptr = mmap(NULL, length, PROT_WRITE, MAP_SHARED, fd, 0);
|
g_window_data.shm_ptr = (uint32_t *) mmap(NULL, length, PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
if (wl.shm_ptr == MAP_FAILED)
|
if (g_window_data.shm_ptr == MAP_FAILED)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
wl.width = width;
|
g_window_data.window_width = width;
|
||||||
wl.height = height;
|
g_window_data.window_height = height;
|
||||||
wl.stride = width * sizeof(uint32_t);
|
g_window_data.buffer_width = width;
|
||||||
wl.shm_pool = wl_shm_create_pool(wl.shm, fd, length);
|
g_window_data.buffer_height = height;
|
||||||
wl.buffer = wl_shm_pool_create_buffer(wl.shm_pool, 0, wl.width, wl.height,
|
g_window_data.buffer_stride = width * sizeof(uint32_t);
|
||||||
wl.stride, wl.shm_format);
|
g_window_data.dst_offset_x = 0;
|
||||||
|
g_window_data.dst_offset_y = 0;
|
||||||
|
g_window_data.dst_width = width;
|
||||||
|
g_window_data.dst_height = height;
|
||||||
|
|
||||||
|
g_window_data.shm_pool = wl_shm_create_pool(g_window_data.shm, fd, length);
|
||||||
|
g_window_data.draw_buffer = wl_shm_pool_create_buffer(g_window_data.shm_pool, 0,
|
||||||
|
g_window_data.buffer_width, g_window_data.buffer_height,
|
||||||
|
g_window_data.buffer_stride, g_window_data.shm_format);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
||||||
wl.surface = wl_compositor_create_surface(wl.compositor);
|
g_window_data.surface = wl_compositor_create_surface(g_window_data.compositor);
|
||||||
if (!wl.surface)
|
if (!g_window_data.surface)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
g_window_data.cursor_surface = wl_compositor_create_surface(g_window_data.compositor);
|
||||||
|
|
||||||
// There should always be a shell, right?
|
// There should always be a shell, right?
|
||||||
if (wl.shell)
|
if (g_window_data.shell)
|
||||||
{
|
{
|
||||||
wl.shell_surface = wl_shell_get_shell_surface(wl.shell, wl.surface);
|
g_window_data.shell_surface = wl_shell_get_shell_surface(g_window_data.shell, g_window_data.surface);
|
||||||
if (!wl.shell_surface)
|
if (!g_window_data.shell_surface)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
wl_shell_surface_set_title(wl.shell_surface, title);
|
wl_shell_surface_set_title(g_window_data.shell_surface, title);
|
||||||
wl_shell_surface_set_toplevel(wl.shell_surface);
|
wl_shell_surface_set_toplevel(g_window_data.shell_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_surface_attach(wl.surface, wl.buffer, 0, 0);
|
wl_surface_attach(g_window_data.surface, g_window_data.draw_buffer, g_window_data.dst_offset_x, g_window_data.dst_offset_y);
|
||||||
wl_surface_damage(wl.surface, 0, 0, width, height);
|
wl_surface_damage(g_window_data.surface, g_window_data.dst_offset_x, g_window_data.dst_offset_y, g_window_data.dst_width, g_window_data.dst_height);
|
||||||
wl_surface_commit(wl.surface);
|
wl_surface_commit(g_window_data.surface);
|
||||||
|
|
||||||
|
if (g_keyboard_func == 0x0) {
|
||||||
|
mfb_keyboard_callback(keyboard_default);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Window created using Wayland API\n");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -235,9 +586,25 @@ out:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frame_done(void *data, struct wl_callback *callback,
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
uint32_t cookie)
|
|
||||||
|
void keyboard_default(void *user_data, Key key, KeyMod mod, bool isPressed) {
|
||||||
|
kUnused(user_data);
|
||||||
|
kUnused(mod);
|
||||||
|
kUnused(isPressed);
|
||||||
|
if (key == KB_KEY_ESCAPE)
|
||||||
|
g_window_data.close = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done event
|
||||||
|
//
|
||||||
|
// Notify the client when the related request is done.
|
||||||
|
//
|
||||||
|
// callback_data: request-specific data for the callback
|
||||||
|
static void
|
||||||
|
frame_done(void *data, struct wl_callback *callback, uint32_t cookie)
|
||||||
{
|
{
|
||||||
|
kUnused(cookie);
|
||||||
wl_callback_destroy(callback);
|
wl_callback_destroy(callback);
|
||||||
*(uint32_t *)data = 1;
|
*(uint32_t *)data = 1;
|
||||||
}
|
}
|
||||||
@ -246,40 +613,203 @@ static const struct wl_callback_listener frame_listener = {
|
|||||||
.done = frame_done,
|
.done = frame_done,
|
||||||
};
|
};
|
||||||
|
|
||||||
int mfb_update(void *buffer)
|
int
|
||||||
|
mfb_update(void *buffer)
|
||||||
{
|
{
|
||||||
uint32_t done = 0;
|
uint32_t done = 0;
|
||||||
|
|
||||||
if (!wl.display || wl_display_get_error(wl.display) != 0)
|
if (!g_window_data.display || wl_display_get_error(g_window_data.display) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (wl.should_close)
|
if (g_window_data.close == true)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// update shm buffer
|
// update shm buffer
|
||||||
memcpy(wl.shm_ptr, buffer, wl.stride * wl.height);
|
memcpy(g_window_data.shm_ptr, buffer, g_window_data.buffer_stride * g_window_data.buffer_height);
|
||||||
|
|
||||||
wl_surface_attach(wl.surface, wl.buffer, 0, 0);
|
wl_surface_attach(g_window_data.surface, g_window_data.draw_buffer, g_window_data.dst_offset_x, g_window_data.dst_offset_y);
|
||||||
wl_surface_damage(wl.surface, 0, 0, wl.width, wl.height);
|
wl_surface_damage(g_window_data.surface, g_window_data.dst_offset_x, g_window_data.dst_offset_y, g_window_data.dst_width, g_window_data.dst_height);
|
||||||
|
|
||||||
struct wl_callback *frame = wl_surface_frame(wl.surface);
|
struct wl_callback *frame = wl_surface_frame(g_window_data.surface);
|
||||||
if (!frame)
|
if (!frame)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wl_callback_add_listener(frame, &frame_listener, &done);
|
wl_callback_add_listener(frame, &frame_listener, &done);
|
||||||
|
|
||||||
wl_surface_commit(wl.surface);
|
wl_surface_commit(g_window_data.surface);
|
||||||
|
|
||||||
while (!done)
|
while (!done && g_window_data.close == false) {
|
||||||
if (wl_display_dispatch(wl.display) == -1)
|
if (wl_display_dispatch(g_window_data.display) == -1 || wl_display_roundtrip(g_window_data.display) == -1)
|
||||||
{
|
{
|
||||||
wl_callback_destroy(frame);
|
wl_callback_destroy(frame);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(g_window_data.close == true) {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
//static int counter = 0;
|
||||||
|
//printf("update!: %d\n", counter++);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void mfb_close(void) { destroy(); }
|
void
|
||||||
|
mfb_close(void) {
|
||||||
|
g_window_data.close = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
extern short int keycodes[512];
|
||||||
|
|
||||||
|
void
|
||||||
|
init_keycodes(void)
|
||||||
|
{
|
||||||
|
// Clear keys
|
||||||
|
for (size_t i = 0; i < sizeof(keycodes) / sizeof(keycodes[0]); ++i)
|
||||||
|
keycodes[i] = 0;
|
||||||
|
|
||||||
|
keycodes[KEY_GRAVE] = KB_KEY_GRAVE_ACCENT;
|
||||||
|
keycodes[KEY_1] = KB_KEY_1;
|
||||||
|
keycodes[KEY_2] = KB_KEY_2;
|
||||||
|
keycodes[KEY_3] = KB_KEY_3;
|
||||||
|
keycodes[KEY_4] = KB_KEY_4;
|
||||||
|
keycodes[KEY_5] = KB_KEY_5;
|
||||||
|
keycodes[KEY_6] = KB_KEY_6;
|
||||||
|
keycodes[KEY_7] = KB_KEY_7;
|
||||||
|
keycodes[KEY_8] = KB_KEY_8;
|
||||||
|
keycodes[KEY_9] = KB_KEY_9;
|
||||||
|
keycodes[KEY_0] = KB_KEY_0;
|
||||||
|
keycodes[KEY_SPACE] = KB_KEY_SPACE;
|
||||||
|
keycodes[KEY_MINUS] = KB_KEY_MINUS;
|
||||||
|
keycodes[KEY_EQUAL] = KB_KEY_EQUAL;
|
||||||
|
keycodes[KEY_Q] = KB_KEY_Q;
|
||||||
|
keycodes[KEY_W] = KB_KEY_W;
|
||||||
|
keycodes[KEY_E] = KB_KEY_E;
|
||||||
|
keycodes[KEY_R] = KB_KEY_R;
|
||||||
|
keycodes[KEY_T] = KB_KEY_T;
|
||||||
|
keycodes[KEY_Y] = KB_KEY_Y;
|
||||||
|
keycodes[KEY_U] = KB_KEY_U;
|
||||||
|
keycodes[KEY_I] = KB_KEY_I;
|
||||||
|
keycodes[KEY_O] = KB_KEY_O;
|
||||||
|
keycodes[KEY_P] = KB_KEY_P;
|
||||||
|
keycodes[KEY_LEFTBRACE] = KB_KEY_LEFT_BRACKET;
|
||||||
|
keycodes[KEY_RIGHTBRACE] = KB_KEY_RIGHT_BRACKET;
|
||||||
|
keycodes[KEY_A] = KB_KEY_A;
|
||||||
|
keycodes[KEY_S] = KB_KEY_S;
|
||||||
|
keycodes[KEY_D] = KB_KEY_D;
|
||||||
|
keycodes[KEY_F] = KB_KEY_F;
|
||||||
|
keycodes[KEY_G] = KB_KEY_G;
|
||||||
|
keycodes[KEY_H] = KB_KEY_H;
|
||||||
|
keycodes[KEY_J] = KB_KEY_J;
|
||||||
|
keycodes[KEY_K] = KB_KEY_K;
|
||||||
|
keycodes[KEY_L] = KB_KEY_L;
|
||||||
|
keycodes[KEY_SEMICOLON] = KB_KEY_SEMICOLON;
|
||||||
|
keycodes[KEY_APOSTROPHE] = KB_KEY_APOSTROPHE;
|
||||||
|
keycodes[KEY_Z] = KB_KEY_Z;
|
||||||
|
keycodes[KEY_X] = KB_KEY_X;
|
||||||
|
keycodes[KEY_C] = KB_KEY_C;
|
||||||
|
keycodes[KEY_V] = KB_KEY_V;
|
||||||
|
keycodes[KEY_B] = KB_KEY_B;
|
||||||
|
keycodes[KEY_N] = KB_KEY_N;
|
||||||
|
keycodes[KEY_M] = KB_KEY_M;
|
||||||
|
keycodes[KEY_COMMA] = KB_KEY_COMMA;
|
||||||
|
keycodes[KEY_DOT] = KB_KEY_PERIOD;
|
||||||
|
keycodes[KEY_SLASH] = KB_KEY_SLASH;
|
||||||
|
keycodes[KEY_BACKSLASH] = KB_KEY_BACKSLASH;
|
||||||
|
keycodes[KEY_ESC] = KB_KEY_ESCAPE;
|
||||||
|
keycodes[KEY_TAB] = KB_KEY_TAB;
|
||||||
|
keycodes[KEY_LEFTSHIFT] = KB_KEY_LEFT_SHIFT;
|
||||||
|
keycodes[KEY_RIGHTSHIFT] = KB_KEY_RIGHT_SHIFT;
|
||||||
|
keycodes[KEY_LEFTCTRL] = KB_KEY_LEFT_CONTROL;
|
||||||
|
keycodes[KEY_RIGHTCTRL] = KB_KEY_RIGHT_CONTROL;
|
||||||
|
keycodes[KEY_LEFTALT] = KB_KEY_LEFT_ALT;
|
||||||
|
keycodes[KEY_RIGHTALT] = KB_KEY_RIGHT_ALT;
|
||||||
|
keycodes[KEY_LEFTMETA] = KB_KEY_LEFT_SUPER;
|
||||||
|
keycodes[KEY_RIGHTMETA] = KB_KEY_RIGHT_SUPER;
|
||||||
|
keycodes[KEY_MENU] = KB_KEY_MENU;
|
||||||
|
keycodes[KEY_NUMLOCK] = KB_KEY_NUM_LOCK;
|
||||||
|
keycodes[KEY_CAPSLOCK] = KB_KEY_CAPS_LOCK;
|
||||||
|
keycodes[KEY_PRINT] = KB_KEY_PRINT_SCREEN;
|
||||||
|
keycodes[KEY_SCROLLLOCK] = KB_KEY_SCROLL_LOCK;
|
||||||
|
keycodes[KEY_PAUSE] = KB_KEY_PAUSE;
|
||||||
|
keycodes[KEY_DELETE] = KB_KEY_DELETE;
|
||||||
|
keycodes[KEY_BACKSPACE] = KB_KEY_BACKSPACE;
|
||||||
|
keycodes[KEY_ENTER] = KB_KEY_ENTER;
|
||||||
|
keycodes[KEY_HOME] = KB_KEY_HOME;
|
||||||
|
keycodes[KEY_END] = KB_KEY_END;
|
||||||
|
keycodes[KEY_PAGEUP] = KB_KEY_PAGE_UP;
|
||||||
|
keycodes[KEY_PAGEDOWN] = KB_KEY_PAGE_DOWN;
|
||||||
|
keycodes[KEY_INSERT] = KB_KEY_INSERT;
|
||||||
|
keycodes[KEY_LEFT] = KB_KEY_LEFT;
|
||||||
|
keycodes[KEY_RIGHT] = KB_KEY_RIGHT;
|
||||||
|
keycodes[KEY_DOWN] = KB_KEY_DOWN;
|
||||||
|
keycodes[KEY_UP] = KB_KEY_UP;
|
||||||
|
keycodes[KEY_F1] = KB_KEY_F1;
|
||||||
|
keycodes[KEY_F2] = KB_KEY_F2;
|
||||||
|
keycodes[KEY_F3] = KB_KEY_F3;
|
||||||
|
keycodes[KEY_F4] = KB_KEY_F4;
|
||||||
|
keycodes[KEY_F5] = KB_KEY_F5;
|
||||||
|
keycodes[KEY_F6] = KB_KEY_F6;
|
||||||
|
keycodes[KEY_F7] = KB_KEY_F7;
|
||||||
|
keycodes[KEY_F8] = KB_KEY_F8;
|
||||||
|
keycodes[KEY_F9] = KB_KEY_F9;
|
||||||
|
keycodes[KEY_F10] = KB_KEY_F10;
|
||||||
|
keycodes[KEY_F11] = KB_KEY_F11;
|
||||||
|
keycodes[KEY_F12] = KB_KEY_F12;
|
||||||
|
keycodes[KEY_F13] = KB_KEY_F13;
|
||||||
|
keycodes[KEY_F14] = KB_KEY_F14;
|
||||||
|
keycodes[KEY_F15] = KB_KEY_F15;
|
||||||
|
keycodes[KEY_F16] = KB_KEY_F16;
|
||||||
|
keycodes[KEY_F17] = KB_KEY_F17;
|
||||||
|
keycodes[KEY_F18] = KB_KEY_F18;
|
||||||
|
keycodes[KEY_F19] = KB_KEY_F19;
|
||||||
|
keycodes[KEY_F20] = KB_KEY_F20;
|
||||||
|
keycodes[KEY_F21] = KB_KEY_F21;
|
||||||
|
keycodes[KEY_F22] = KB_KEY_F22;
|
||||||
|
keycodes[KEY_F23] = KB_KEY_F23;
|
||||||
|
keycodes[KEY_F24] = KB_KEY_F24;
|
||||||
|
keycodes[KEY_KPSLASH] = KB_KEY_KP_DIVIDE;
|
||||||
|
keycodes[KEY_KPDOT] = KB_KEY_KP_MULTIPLY;
|
||||||
|
keycodes[KEY_KPMINUS] = KB_KEY_KP_SUBTRACT;
|
||||||
|
keycodes[KEY_KPPLUS] = KB_KEY_KP_ADD;
|
||||||
|
keycodes[KEY_KP0] = KB_KEY_KP_0;
|
||||||
|
keycodes[KEY_KP1] = KB_KEY_KP_1;
|
||||||
|
keycodes[KEY_KP2] = KB_KEY_KP_2;
|
||||||
|
keycodes[KEY_KP3] = KB_KEY_KP_3;
|
||||||
|
keycodes[KEY_KP4] = KB_KEY_KP_4;
|
||||||
|
keycodes[KEY_KP5] = KB_KEY_KP_5;
|
||||||
|
keycodes[KEY_KP6] = KB_KEY_KP_6;
|
||||||
|
keycodes[KEY_KP7] = KB_KEY_KP_7;
|
||||||
|
keycodes[KEY_KP8] = KB_KEY_KP_8;
|
||||||
|
keycodes[KEY_KP9] = KB_KEY_KP_9;
|
||||||
|
keycodes[KEY_KPCOMMA] = KB_KEY_KP_DECIMAL;
|
||||||
|
keycodes[KEY_KPEQUAL] = KB_KEY_KP_EQUAL;
|
||||||
|
keycodes[KEY_KPENTER] = KB_KEY_KP_ENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool
|
||||||
|
mfb_set_viewport(unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) {
|
||||||
|
|
||||||
|
if(offset_x + width > g_window_data.window_width) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(offset_y + height > g_window_data.window_height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Not yet
|
||||||
|
// g_window_data.dst_offset_x = offset_x;
|
||||||
|
// g_window_data.dst_offset_y = offset_y;
|
||||||
|
// g_window_data.dst_width = width;
|
||||||
|
// g_window_data.dst_height = height;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
57
src/wayland/WaylandWindowData.h
Normal file
57
src/wayland/WaylandWindowData.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <MiniFB_enums.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct wl_display;
|
||||||
|
struct wl_registry;
|
||||||
|
struct wl_compositor;
|
||||||
|
struct wl_shell;
|
||||||
|
struct wl_seat;
|
||||||
|
struct wl_keyboard;
|
||||||
|
struct wl_pointer;
|
||||||
|
struct wl_callback;
|
||||||
|
struct wl_shm;
|
||||||
|
struct wl_shm_pool;
|
||||||
|
struct wl_surface;
|
||||||
|
struct wl_shell_surface;
|
||||||
|
struct wl_buffer;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wl_registry *registry;
|
||||||
|
struct wl_compositor *compositor;
|
||||||
|
struct wl_shell *shell;
|
||||||
|
struct wl_seat *seat;
|
||||||
|
struct wl_keyboard *keyboard;
|
||||||
|
|
||||||
|
struct wl_pointer *pointer;
|
||||||
|
struct wl_cursor_theme *cursor_theme;
|
||||||
|
struct wl_cursor *default_cursor;
|
||||||
|
struct wl_surface *cursor_surface;
|
||||||
|
|
||||||
|
struct wl_shm *shm;
|
||||||
|
struct wl_shm_pool *shm_pool;
|
||||||
|
struct wl_surface *surface;
|
||||||
|
struct wl_shell_surface *shell_surface;
|
||||||
|
|
||||||
|
uint32_t seat_version;
|
||||||
|
uint32_t shm_format;
|
||||||
|
uint32_t *shm_ptr;
|
||||||
|
|
||||||
|
uint32_t window_width;
|
||||||
|
uint32_t window_height;
|
||||||
|
uint32_t dst_offset_x;
|
||||||
|
uint32_t dst_offset_y;
|
||||||
|
uint32_t dst_width;
|
||||||
|
uint32_t dst_height;
|
||||||
|
|
||||||
|
struct wl_buffer *draw_buffer;
|
||||||
|
uint32_t buffer_width;
|
||||||
|
uint32_t buffer_height;
|
||||||
|
uint32_t buffer_stride;
|
||||||
|
|
||||||
|
uint32_t mod_keys;
|
||||||
|
bool close;
|
||||||
|
} SWindowData;
|
@ -1,24 +1,21 @@
|
|||||||
#include "MiniFB.h"
|
#include <MiniFB.h>
|
||||||
|
#include <MiniFB_internal.h>
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#include "WinWindowData.h"
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static WNDCLASS s_wc;
|
SWindowData g_window_data = { 0 };
|
||||||
static HWND s_wnd;
|
|
||||||
static int s_close = 0;
|
long s_window_style = WS_POPUP | WS_SYSMENU | WS_CAPTION;
|
||||||
static int s_width;
|
|
||||||
static int s_height;
|
|
||||||
static HDC s_hdc;
|
|
||||||
static void* s_buffer;
|
|
||||||
static BITMAPINFO* s_bitmapInfo;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
uint32_t translate_mod();
|
||||||
|
Key translate_key(unsigned int wParam, unsigned long lParam);
|
||||||
|
|
||||||
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
LRESULT res = 0;
|
LRESULT res = 0;
|
||||||
|
|
||||||
@ -26,10 +23,25 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l
|
|||||||
{
|
{
|
||||||
case WM_PAINT:
|
case WM_PAINT:
|
||||||
{
|
{
|
||||||
if (s_buffer)
|
if (g_window_data.draw_buffer)
|
||||||
{
|
{
|
||||||
StretchDIBits(s_hdc, 0, 0, s_width, s_height, 0, 0, s_width, s_height, s_buffer,
|
if (g_window_data.dst_offset_x > 0) {
|
||||||
s_bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
|
BitBlt(g_window_data.s_hdc, 0, g_window_data.dst_offset_y, g_window_data.dst_offset_x, g_window_data.dst_height, 0, 0, 0, BLACKNESS);
|
||||||
|
}
|
||||||
|
if (g_window_data.dst_offset_y > 0) {
|
||||||
|
BitBlt(g_window_data.s_hdc, 0, 0, g_window_data.window_width, g_window_data.dst_offset_y, 0, 0, 0, BLACKNESS);
|
||||||
|
}
|
||||||
|
uint32_t offsetY = g_window_data.dst_offset_y + g_window_data.dst_height;
|
||||||
|
if (offsetY < g_window_data.window_height) {
|
||||||
|
BitBlt(g_window_data.s_hdc, 0, offsetY, g_window_data.window_width, g_window_data.window_height-offsetY, 0, 0, 0, BLACKNESS);
|
||||||
|
}
|
||||||
|
uint32_t offsetX = g_window_data.dst_offset_x + g_window_data.dst_width;
|
||||||
|
if (offsetX < g_window_data.window_width) {
|
||||||
|
BitBlt(g_window_data.s_hdc, offsetX, g_window_data.dst_offset_y, g_window_data.window_width-offsetX, g_window_data.dst_height, 0, 0, 0, BLACKNESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
StretchDIBits(g_window_data.s_hdc, g_window_data.dst_offset_x, g_window_data.dst_offset_y, g_window_data.dst_width, g_window_data.dst_height, 0, 0, g_window_data.buffer_width, g_window_data.buffer_height, g_window_data.draw_buffer,
|
||||||
|
g_window_data.s_bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
|
||||||
|
|
||||||
ValidateRect(hWnd, NULL);
|
ValidateRect(hWnd, NULL);
|
||||||
}
|
}
|
||||||
@ -37,20 +49,134 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_KEYDOWN:
|
case WM_DESTROY:
|
||||||
{
|
|
||||||
if ((wParam&0xFF) == 27)
|
|
||||||
s_close = 1;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
{
|
{
|
||||||
s_close = 1;
|
g_window_data.close = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
{
|
||||||
|
Key kb_key = translate_key((unsigned int)wParam, (unsigned long)lParam);
|
||||||
|
int is_pressed = !((lParam >> 31) & 1);
|
||||||
|
g_window_data.mod_keys = translate_mod();
|
||||||
|
|
||||||
|
if (kb_key == KB_KEY_UNKNOWN)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
kCall(g_keyboard_func, kb_key, g_window_data.mod_keys, is_pressed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_CHAR:
|
||||||
|
case WM_SYSCHAR:
|
||||||
|
case WM_UNICHAR:
|
||||||
|
{
|
||||||
|
|
||||||
|
if(message == WM_UNICHAR && wParam == UNICODE_NOCHAR) {
|
||||||
|
// WM_UNICHAR is not sent by Windows, but is sent by some third-party input method engine
|
||||||
|
// Returning TRUE here announces support for this message
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
kCall(g_char_input_func, wParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
case WM_XBUTTONUP:
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
case WM_LBUTTONDBLCLK:
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
case WM_RBUTTONDBLCLK:
|
||||||
|
case WM_MBUTTONDOWN:
|
||||||
|
case WM_MBUTTONDBLCLK:
|
||||||
|
case WM_XBUTTONDOWN:
|
||||||
|
case WM_XBUTTONDBLCLK:
|
||||||
|
{
|
||||||
|
MouseButton button = MOUSE_BTN_0;
|
||||||
|
g_window_data.mod_keys = translate_mod();
|
||||||
|
int is_pressed = 0;
|
||||||
|
switch (message) {
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
is_pressed = 1;
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
button = MOUSE_BTN_1;
|
||||||
|
break;
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
is_pressed = 1;
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
button = MOUSE_BTN_2;
|
||||||
|
break;
|
||||||
|
case WM_MBUTTONDOWN:
|
||||||
|
is_pressed = 1;
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
button = MOUSE_BTN_3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? MOUSE_BTN_5 : MOUSE_BTN_6);
|
||||||
|
if (message == WM_XBUTTONDOWN) {
|
||||||
|
is_pressed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kCall(g_mouse_btn_func, button, g_window_data.mod_keys, is_pressed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
kCall(g_mouse_wheel_func, translate_mod(), 0.0f, (SHORT)HIWORD(wParam) / (float)WHEEL_DELTA);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOUSEHWHEEL:
|
||||||
|
// This message is only sent on Windows Vista and later
|
||||||
|
// NOTE: The X-axis is inverted for consistency with macOS and X11
|
||||||
|
kCall(g_mouse_wheel_func, translate_mod(), -((SHORT)HIWORD(wParam) / (float)WHEEL_DELTA), 0.0f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
if(g_window_data.s_mouse_inside == false) {
|
||||||
|
g_window_data.s_mouse_inside = true;
|
||||||
|
TRACKMOUSEEVENT tme;
|
||||||
|
ZeroMemory(&tme, sizeof(tme));
|
||||||
|
tme.cbSize = sizeof(tme);
|
||||||
|
tme.dwFlags = TME_LEAVE;
|
||||||
|
tme.hwndTrack = hWnd;
|
||||||
|
TrackMouseEvent(&tme);
|
||||||
|
}
|
||||||
|
kCall(g_mouse_move_func, ((int)(short)LOWORD(lParam)), ((int)(short)HIWORD(lParam)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOUSELEAVE:
|
||||||
|
g_window_data.s_mouse_inside = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
g_window_data.dst_offset_x = 0;
|
||||||
|
g_window_data.dst_offset_y = 0;
|
||||||
|
g_window_data.dst_width = LOWORD(lParam);
|
||||||
|
g_window_data.dst_height = HIWORD(lParam);
|
||||||
|
g_window_data.window_width = g_window_data.dst_width;
|
||||||
|
g_window_data.window_height = g_window_data.dst_height;
|
||||||
|
kCall(g_resize_func, g_window_data.dst_width, g_window_data.dst_height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_SETFOCUS:
|
||||||
|
kCall(g_active_func, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_KILLFOCUS:
|
||||||
|
kCall(g_active_func, false);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
res = DefWindowProc(hWnd, message, wParam, lParam);
|
res = DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
@ -62,75 +188,157 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int mfb_open(const char* title, int width, int height)
|
int mfb_open_ex(const char* title, int width, int height, int flags) {
|
||||||
{
|
|
||||||
RECT rect = { 0 };
|
RECT rect = { 0 };
|
||||||
|
int x, y;
|
||||||
|
|
||||||
s_wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
|
init_keycodes();
|
||||||
s_wc.lpfnWndProc = WndProc;
|
|
||||||
s_wc.hCursor = LoadCursor(0, IDC_ARROW);
|
g_window_data.buffer_width = width;
|
||||||
s_wc.lpszClassName = title;
|
g_window_data.buffer_height = height;
|
||||||
RegisterClass(&s_wc);
|
|
||||||
|
s_window_style = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME;
|
||||||
|
if (flags & WF_FULLSCREEN) {
|
||||||
|
flags = WF_FULLSCREEN; // Remove all other flags
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
rect.right = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
rect.bottom = GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
s_window_style = WS_POPUP & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
|
||||||
|
|
||||||
|
DEVMODE settings;
|
||||||
|
EnumDisplaySettings(0, 0, &settings);
|
||||||
|
settings.dmPelsWidth = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
settings.dmPelsHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
settings.dmBitsPerPel = 32;
|
||||||
|
settings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
||||||
|
|
||||||
|
if (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
|
||||||
|
flags = WF_FULLSCREEN_DESKTOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WF_BORDERLESS) {
|
||||||
|
s_window_style = WS_POPUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WF_RESIZABLE) {
|
||||||
|
s_window_style |= WS_MAXIMIZEBOX | WS_SIZEBOX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WF_FULLSCREEN_DESKTOP) {
|
||||||
|
s_window_style = WS_OVERLAPPEDWINDOW;
|
||||||
|
|
||||||
|
width = GetSystemMetrics(SM_CXFULLSCREEN);
|
||||||
|
height = GetSystemMetrics(SM_CYFULLSCREEN);
|
||||||
|
|
||||||
|
rect.right = width;
|
||||||
|
rect.bottom = height;
|
||||||
|
AdjustWindowRect(&rect, s_window_style, 0);
|
||||||
|
if (rect.left < 0) {
|
||||||
|
width += rect.left * 2;
|
||||||
|
rect.right += rect.left;
|
||||||
|
rect.left = 0;
|
||||||
|
}
|
||||||
|
if (rect.bottom > height) {
|
||||||
|
height -= (rect.bottom - height);
|
||||||
|
rect.bottom += (rect.bottom - height);
|
||||||
|
rect.top = 0;
|
||||||
|
}
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
else if (!(flags & WF_FULLSCREEN)) {
|
||||||
rect.right = width;
|
rect.right = width;
|
||||||
rect.bottom = height;
|
rect.bottom = height;
|
||||||
|
|
||||||
AdjustWindowRect(&rect, WS_POPUP | WS_SYSMENU | WS_CAPTION, 0);
|
AdjustWindowRect(&rect, s_window_style, 0);
|
||||||
|
|
||||||
rect.right -= rect.left;
|
rect.right -= rect.left;
|
||||||
rect.bottom -= rect.top;
|
rect.bottom -= rect.top;
|
||||||
|
|
||||||
s_width = width;
|
x = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
|
||||||
s_height = height;
|
y = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom + rect.top) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
s_wnd = CreateWindowEx(0,
|
g_window_data.s_wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
|
||||||
|
g_window_data.s_wc.lpfnWndProc = WndProc;
|
||||||
|
g_window_data.s_wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||||
|
g_window_data.s_wc.lpszClassName = title;
|
||||||
|
RegisterClass(&g_window_data.s_wc);
|
||||||
|
|
||||||
|
if (g_window_data.dst_width == 0)
|
||||||
|
g_window_data.dst_width = width;
|
||||||
|
|
||||||
|
if (g_window_data.dst_height == 0)
|
||||||
|
g_window_data.dst_height = height;
|
||||||
|
|
||||||
|
g_window_data.window_width = rect.right;
|
||||||
|
g_window_data.window_height = rect.bottom;
|
||||||
|
|
||||||
|
g_window_data.window = CreateWindowEx(
|
||||||
|
0,
|
||||||
title, title,
|
title, title,
|
||||||
WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME,
|
s_window_style,
|
||||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
x, y,
|
||||||
rect.right, rect.bottom,
|
g_window_data.window_width, g_window_data.window_height,
|
||||||
0, 0, 0, 0);
|
0, 0, 0, 0);
|
||||||
|
|
||||||
if (!s_wnd)
|
if (!g_window_data.window)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ShowWindow(s_wnd, SW_NORMAL);
|
if (flags & WF_ALWAYS_ON_TOP)
|
||||||
|
SetWindowPos(g_window_data.window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||||
|
|
||||||
s_bitmapInfo = (BITMAPINFO*)calloc(1, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 3);
|
ShowWindow(g_window_data.window, SW_NORMAL);
|
||||||
s_bitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
||||||
s_bitmapInfo->bmiHeader.biPlanes = 1;
|
|
||||||
s_bitmapInfo->bmiHeader.biBitCount = 32;
|
|
||||||
s_bitmapInfo->bmiHeader.biCompression = BI_BITFIELDS;
|
|
||||||
s_bitmapInfo->bmiHeader.biWidth = width;
|
|
||||||
s_bitmapInfo->bmiHeader.biHeight = -height;
|
|
||||||
s_bitmapInfo->bmiColors[0].rgbRed = 0xff;
|
|
||||||
s_bitmapInfo->bmiColors[1].rgbGreen = 0xff;
|
|
||||||
s_bitmapInfo->bmiColors[2].rgbBlue = 0xff;
|
|
||||||
|
|
||||||
s_hdc = GetDC(s_wnd);
|
g_window_data.s_bitmapInfo = (BITMAPINFO *) calloc(1, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 3);
|
||||||
|
g_window_data.s_bitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
g_window_data.s_bitmapInfo->bmiHeader.biPlanes = 1;
|
||||||
|
g_window_data.s_bitmapInfo->bmiHeader.biBitCount = 32;
|
||||||
|
g_window_data.s_bitmapInfo->bmiHeader.biCompression = BI_BITFIELDS;
|
||||||
|
g_window_data.s_bitmapInfo->bmiHeader.biWidth = g_window_data.buffer_width;
|
||||||
|
g_window_data.s_bitmapInfo->bmiHeader.biHeight = -(LONG)g_window_data.buffer_height;
|
||||||
|
g_window_data.s_bitmapInfo->bmiColors[0].rgbRed = 0xff;
|
||||||
|
g_window_data.s_bitmapInfo->bmiColors[1].rgbGreen = 0xff;
|
||||||
|
g_window_data.s_bitmapInfo->bmiColors[2].rgbBlue = 0xff;
|
||||||
|
|
||||||
|
g_window_data.s_hdc = GetDC(g_window_data.window);
|
||||||
|
|
||||||
|
if (g_keyboard_func == 0x0) {
|
||||||
|
mfb_keyboard_callback(keyboard_default);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mfb_open(const char* title, int width, int height) {
|
||||||
|
return mfb_open_ex(title, width, height, 0);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int mfb_update(void* buffer)
|
int mfb_update(void* buffer)
|
||||||
{
|
{
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
s_buffer = buffer;
|
if (buffer == 0x0)
|
||||||
|
return -2;
|
||||||
|
|
||||||
InvalidateRect(s_wnd, NULL, TRUE);
|
if (g_window_data.close == true)
|
||||||
SendMessage(s_wnd, WM_PAINT, 0, 0);
|
return -1;
|
||||||
|
|
||||||
while (PeekMessage(&msg, s_wnd, 0, 0, PM_REMOVE))
|
g_window_data.draw_buffer = buffer;
|
||||||
|
|
||||||
|
InvalidateRect(g_window_data.window, NULL, TRUE);
|
||||||
|
SendMessage(g_window_data.window, WM_PAINT, 0, 0);
|
||||||
|
|
||||||
|
while (g_window_data.close == false && PeekMessage(&msg, g_window_data.window, 0, 0, PM_REMOVE))
|
||||||
{
|
{
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_close == 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,9 +346,226 @@ int mfb_update(void* buffer)
|
|||||||
|
|
||||||
void mfb_close()
|
void mfb_close()
|
||||||
{
|
{
|
||||||
s_buffer = 0;
|
g_window_data.draw_buffer = 0x0;
|
||||||
free(s_bitmapInfo);
|
if (g_window_data.s_bitmapInfo != 0x0) {
|
||||||
ReleaseDC(s_wnd, s_hdc);
|
free(g_window_data.s_bitmapInfo);
|
||||||
DestroyWindow(s_wnd);
|
}
|
||||||
|
if (g_window_data.window != 0 && g_window_data.s_hdc != 0) {
|
||||||
|
ReleaseDC(g_window_data.window, g_window_data.s_hdc);
|
||||||
|
DestroyWindow(g_window_data.window);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_window_data.window = 0;
|
||||||
|
g_window_data.s_hdc = 0;
|
||||||
|
g_window_data.s_bitmapInfo = 0x0;
|
||||||
|
g_window_data.close = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void keyboard_default(void *user_data, Key key, KeyMod mod, bool isPressed) {
|
||||||
|
kUnused(user_data);
|
||||||
|
kUnused(mod);
|
||||||
|
kUnused(isPressed);
|
||||||
|
if (key == KB_KEY_ESCAPE)
|
||||||
|
g_window_data.close = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint32_t translate_mod() {
|
||||||
|
uint32_t mods = 0;
|
||||||
|
|
||||||
|
if (GetKeyState(VK_SHIFT) & 0x8000)
|
||||||
|
mods |= KB_MOD_SHIFT;
|
||||||
|
if (GetKeyState(VK_CONTROL) & 0x8000)
|
||||||
|
mods |= KB_MOD_CONTROL;
|
||||||
|
if (GetKeyState(VK_MENU) & 0x8000)
|
||||||
|
mods |= KB_MOD_ALT;
|
||||||
|
if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
|
||||||
|
mods |= KB_MOD_SUPER;
|
||||||
|
if (GetKeyState(VK_CAPITAL) & 1)
|
||||||
|
mods |= KB_MOD_CAPS_LOCK;
|
||||||
|
if (GetKeyState(VK_NUMLOCK) & 1)
|
||||||
|
mods |= KB_MOD_NUM_LOCK;
|
||||||
|
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
extern short int keycodes[512];
|
||||||
|
|
||||||
|
void init_keycodes() {
|
||||||
|
|
||||||
|
// Clear keys
|
||||||
|
for (size_t i = 0; i < sizeof(keycodes) / sizeof(keycodes[0]); ++i)
|
||||||
|
keycodes[i] = 0;
|
||||||
|
|
||||||
|
keycodes[0x00B] = KB_KEY_0;
|
||||||
|
keycodes[0x002] = KB_KEY_1;
|
||||||
|
keycodes[0x003] = KB_KEY_2;
|
||||||
|
keycodes[0x004] = KB_KEY_3;
|
||||||
|
keycodes[0x005] = KB_KEY_4;
|
||||||
|
keycodes[0x006] = KB_KEY_5;
|
||||||
|
keycodes[0x007] = KB_KEY_6;
|
||||||
|
keycodes[0x008] = KB_KEY_7;
|
||||||
|
keycodes[0x009] = KB_KEY_8;
|
||||||
|
keycodes[0x00A] = KB_KEY_9;
|
||||||
|
keycodes[0x01E] = KB_KEY_A;
|
||||||
|
keycodes[0x030] = KB_KEY_B;
|
||||||
|
keycodes[0x02E] = KB_KEY_C;
|
||||||
|
keycodes[0x020] = KB_KEY_D;
|
||||||
|
keycodes[0x012] = KB_KEY_E;
|
||||||
|
keycodes[0x021] = KB_KEY_F;
|
||||||
|
keycodes[0x022] = KB_KEY_G;
|
||||||
|
keycodes[0x023] = KB_KEY_H;
|
||||||
|
keycodes[0x017] = KB_KEY_I;
|
||||||
|
keycodes[0x024] = KB_KEY_J;
|
||||||
|
keycodes[0x025] = KB_KEY_K;
|
||||||
|
keycodes[0x026] = KB_KEY_L;
|
||||||
|
keycodes[0x032] = KB_KEY_M;
|
||||||
|
keycodes[0x031] = KB_KEY_N;
|
||||||
|
keycodes[0x018] = KB_KEY_O;
|
||||||
|
keycodes[0x019] = KB_KEY_P;
|
||||||
|
keycodes[0x010] = KB_KEY_Q;
|
||||||
|
keycodes[0x013] = KB_KEY_R;
|
||||||
|
keycodes[0x01F] = KB_KEY_S;
|
||||||
|
keycodes[0x014] = KB_KEY_T;
|
||||||
|
keycodes[0x016] = KB_KEY_U;
|
||||||
|
keycodes[0x02F] = KB_KEY_V;
|
||||||
|
keycodes[0x011] = KB_KEY_W;
|
||||||
|
keycodes[0x02D] = KB_KEY_X;
|
||||||
|
keycodes[0x015] = KB_KEY_Y;
|
||||||
|
keycodes[0x02C] = KB_KEY_Z;
|
||||||
|
|
||||||
|
keycodes[0x028] = KB_KEY_APOSTROPHE;
|
||||||
|
keycodes[0x02B] = KB_KEY_BACKSLASH;
|
||||||
|
keycodes[0x033] = KB_KEY_COMMA;
|
||||||
|
keycodes[0x00D] = KB_KEY_EQUAL;
|
||||||
|
keycodes[0x029] = KB_KEY_GRAVE_ACCENT;
|
||||||
|
keycodes[0x01A] = KB_KEY_LEFT_BRACKET;
|
||||||
|
keycodes[0x00C] = KB_KEY_MINUS;
|
||||||
|
keycodes[0x034] = KB_KEY_PERIOD;
|
||||||
|
keycodes[0x01B] = KB_KEY_RIGHT_BRACKET;
|
||||||
|
keycodes[0x027] = KB_KEY_SEMICOLON;
|
||||||
|
keycodes[0x035] = KB_KEY_SLASH;
|
||||||
|
keycodes[0x056] = KB_KEY_WORLD_2;
|
||||||
|
|
||||||
|
keycodes[0x00E] = KB_KEY_BACKSPACE;
|
||||||
|
keycodes[0x153] = KB_KEY_DELETE;
|
||||||
|
keycodes[0x14F] = KB_KEY_END;
|
||||||
|
keycodes[0x01C] = KB_KEY_ENTER;
|
||||||
|
keycodes[0x001] = KB_KEY_ESCAPE;
|
||||||
|
keycodes[0x147] = KB_KEY_HOME;
|
||||||
|
keycodes[0x152] = KB_KEY_INSERT;
|
||||||
|
keycodes[0x15D] = KB_KEY_MENU;
|
||||||
|
keycodes[0x151] = KB_KEY_PAGE_DOWN;
|
||||||
|
keycodes[0x149] = KB_KEY_PAGE_UP;
|
||||||
|
keycodes[0x045] = KB_KEY_PAUSE;
|
||||||
|
keycodes[0x146] = KB_KEY_PAUSE;
|
||||||
|
keycodes[0x039] = KB_KEY_SPACE;
|
||||||
|
keycodes[0x00F] = KB_KEY_TAB;
|
||||||
|
keycodes[0x03A] = KB_KEY_CAPS_LOCK;
|
||||||
|
keycodes[0x145] = KB_KEY_NUM_LOCK;
|
||||||
|
keycodes[0x046] = KB_KEY_SCROLL_LOCK;
|
||||||
|
keycodes[0x03B] = KB_KEY_F1;
|
||||||
|
keycodes[0x03C] = KB_KEY_F2;
|
||||||
|
keycodes[0x03D] = KB_KEY_F3;
|
||||||
|
keycodes[0x03E] = KB_KEY_F4;
|
||||||
|
keycodes[0x03F] = KB_KEY_F5;
|
||||||
|
keycodes[0x040] = KB_KEY_F6;
|
||||||
|
keycodes[0x041] = KB_KEY_F7;
|
||||||
|
keycodes[0x042] = KB_KEY_F8;
|
||||||
|
keycodes[0x043] = KB_KEY_F9;
|
||||||
|
keycodes[0x044] = KB_KEY_F10;
|
||||||
|
keycodes[0x057] = KB_KEY_F11;
|
||||||
|
keycodes[0x058] = KB_KEY_F12;
|
||||||
|
keycodes[0x064] = KB_KEY_F13;
|
||||||
|
keycodes[0x065] = KB_KEY_F14;
|
||||||
|
keycodes[0x066] = KB_KEY_F15;
|
||||||
|
keycodes[0x067] = KB_KEY_F16;
|
||||||
|
keycodes[0x068] = KB_KEY_F17;
|
||||||
|
keycodes[0x069] = KB_KEY_F18;
|
||||||
|
keycodes[0x06A] = KB_KEY_F19;
|
||||||
|
keycodes[0x06B] = KB_KEY_F20;
|
||||||
|
keycodes[0x06C] = KB_KEY_F21;
|
||||||
|
keycodes[0x06D] = KB_KEY_F22;
|
||||||
|
keycodes[0x06E] = KB_KEY_F23;
|
||||||
|
keycodes[0x076] = KB_KEY_F24;
|
||||||
|
keycodes[0x038] = KB_KEY_LEFT_ALT;
|
||||||
|
keycodes[0x01D] = KB_KEY_LEFT_CONTROL;
|
||||||
|
keycodes[0x02A] = KB_KEY_LEFT_SHIFT;
|
||||||
|
keycodes[0x15B] = KB_KEY_LEFT_SUPER;
|
||||||
|
keycodes[0x137] = KB_KEY_PRINT_SCREEN;
|
||||||
|
keycodes[0x138] = KB_KEY_RIGHT_ALT;
|
||||||
|
keycodes[0x11D] = KB_KEY_RIGHT_CONTROL;
|
||||||
|
keycodes[0x036] = KB_KEY_RIGHT_SHIFT;
|
||||||
|
keycodes[0x15C] = KB_KEY_RIGHT_SUPER;
|
||||||
|
keycodes[0x150] = KB_KEY_DOWN;
|
||||||
|
keycodes[0x14B] = KB_KEY_LEFT;
|
||||||
|
keycodes[0x14D] = KB_KEY_RIGHT;
|
||||||
|
keycodes[0x148] = KB_KEY_UP;
|
||||||
|
|
||||||
|
keycodes[0x052] = KB_KEY_KP_0;
|
||||||
|
keycodes[0x04F] = KB_KEY_KP_1;
|
||||||
|
keycodes[0x050] = KB_KEY_KP_2;
|
||||||
|
keycodes[0x051] = KB_KEY_KP_3;
|
||||||
|
keycodes[0x04B] = KB_KEY_KP_4;
|
||||||
|
keycodes[0x04C] = KB_KEY_KP_5;
|
||||||
|
keycodes[0x04D] = KB_KEY_KP_6;
|
||||||
|
keycodes[0x047] = KB_KEY_KP_7;
|
||||||
|
keycodes[0x048] = KB_KEY_KP_8;
|
||||||
|
keycodes[0x049] = KB_KEY_KP_9;
|
||||||
|
keycodes[0x04E] = KB_KEY_KP_ADD;
|
||||||
|
keycodes[0x053] = KB_KEY_KP_DECIMAL;
|
||||||
|
keycodes[0x135] = KB_KEY_KP_DIVIDE;
|
||||||
|
keycodes[0x11C] = KB_KEY_KP_ENTER;
|
||||||
|
keycodes[0x037] = KB_KEY_KP_MULTIPLY;
|
||||||
|
keycodes[0x04A] = KB_KEY_KP_SUBTRACT;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Key translate_key(unsigned int wParam, unsigned long lParam) {
|
||||||
|
if (wParam == VK_CONTROL) {
|
||||||
|
MSG next;
|
||||||
|
DWORD time;
|
||||||
|
|
||||||
|
if (lParam & 0x01000000)
|
||||||
|
return KB_KEY_RIGHT_CONTROL;
|
||||||
|
|
||||||
|
time = GetMessageTime();
|
||||||
|
if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
|
||||||
|
if (next.message == WM_KEYDOWN || next.message == WM_SYSKEYDOWN || next.message == WM_KEYUP || next.message == WM_SYSKEYUP)
|
||||||
|
if (next.wParam == VK_MENU && (next.lParam & 0x01000000) && next.time == time)
|
||||||
|
return KB_KEY_UNKNOWN;
|
||||||
|
|
||||||
|
return KB_KEY_LEFT_CONTROL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wParam == VK_PROCESSKEY)
|
||||||
|
return KB_KEY_UNKNOWN;
|
||||||
|
|
||||||
|
return (Key) keycodes[HIWORD(lParam) & 0x1FF];
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool mfb_set_viewport(unsigned offset_x, unsigned offset_y, unsigned width, unsigned height)
|
||||||
|
{
|
||||||
|
if(offset_x + width > g_window_data.window_width) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(offset_y + height > g_window_data.window_height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_window_data.dst_offset_x = offset_x;
|
||||||
|
g_window_data.dst_offset_y = offset_y;
|
||||||
|
|
||||||
|
g_window_data.dst_width = width;
|
||||||
|
g_window_data.dst_height = height;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
30
src/windows/WinWindowData.h
Normal file
30
src/windows/WinWindowData.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <MiniFB_enums.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HWND window;
|
||||||
|
WNDCLASS s_wc;
|
||||||
|
HDC s_hdc;
|
||||||
|
BITMAPINFO *s_bitmapInfo;
|
||||||
|
bool s_mouse_inside;
|
||||||
|
|
||||||
|
uint32_t window_width;
|
||||||
|
uint32_t window_height;
|
||||||
|
|
||||||
|
uint32_t dst_offset_x;
|
||||||
|
uint32_t dst_offset_y;
|
||||||
|
uint32_t dst_width;
|
||||||
|
uint32_t dst_height;
|
||||||
|
|
||||||
|
void *draw_buffer;
|
||||||
|
uint32_t buffer_width;
|
||||||
|
uint32_t buffer_height;
|
||||||
|
|
||||||
|
uint32_t mod_keys;
|
||||||
|
bool close;
|
||||||
|
} SWindowData;
|
@ -1,42 +1,44 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/cursorfont.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <MiniFB.h>
|
#include <MiniFB.h>
|
||||||
|
#include <MiniFB_internal.h>
|
||||||
|
#include "X11WindowData.h"
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define KEY_FUNCTION 0xFF
|
SWindowData g_window_data = { 0 };
|
||||||
#define KEY_ESC 0x1B
|
|
||||||
|
extern void
|
||||||
|
stretch_image(uint32_t *srcImage, uint32_t srcX, uint32_t srcY, uint32_t srcWidth, uint32_t srcHeight, uint32_t srcPitch,
|
||||||
|
uint32_t *dstImage, uint32_t dstX, uint32_t dstY, uint32_t dstWidth, uint32_t dstHeight, uint32_t dstPitch);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static Display* s_display;
|
int mfb_open_ex(const char* title, int width, int height, int flags) {
|
||||||
static int s_screen;
|
|
||||||
static int s_width;
|
|
||||||
static int s_height;
|
|
||||||
static Window s_window;
|
|
||||||
static GC s_gc;
|
|
||||||
static XImage *s_ximage;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int mfb_open(const char* title, int width, int height)
|
|
||||||
{
|
|
||||||
int depth, i, formatCount, convDepth = -1;
|
int depth, i, formatCount, convDepth = -1;
|
||||||
XPixmapFormatValues* formats;
|
XPixmapFormatValues* formats;
|
||||||
XSetWindowAttributes windowAttributes;
|
XSetWindowAttributes windowAttributes;
|
||||||
XSizeHints sizeHints;
|
XSizeHints sizeHints;
|
||||||
Visual* visual;
|
Visual* visual;
|
||||||
|
|
||||||
s_display = XOpenDisplay(0);
|
g_window_data.display = XOpenDisplay(0);
|
||||||
|
if (!g_window_data.display)
|
||||||
if (!s_display)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
s_screen = DefaultScreen(s_display);
|
init_keycodes();
|
||||||
visual = DefaultVisual(s_display, s_screen);
|
|
||||||
formats = XListPixmapFormats(s_display, &formatCount);
|
g_window_data.screen = DefaultScreen(g_window_data.display);
|
||||||
depth = DefaultDepth(s_display, s_screen);
|
|
||||||
Window defaultRootWindow = DefaultRootWindow(s_display);
|
visual = DefaultVisual(g_window_data.display, g_window_data.screen);
|
||||||
|
formats = XListPixmapFormats(g_window_data.display, &formatCount);
|
||||||
|
depth = DefaultDepth(g_window_data.display, g_window_data.screen);
|
||||||
|
|
||||||
|
Window defaultRootWindow = DefaultRootWindow(g_window_data.display);
|
||||||
|
|
||||||
for (i = 0; i < formatCount; ++i)
|
for (i = 0; i < formatCount; ++i)
|
||||||
{
|
{
|
||||||
@ -52,71 +54,227 @@ int mfb_open(const char* title, int width, int height)
|
|||||||
// We only support 32-bit right now
|
// We only support 32-bit right now
|
||||||
if (convDepth != 32)
|
if (convDepth != 32)
|
||||||
{
|
{
|
||||||
XCloseDisplay(s_display);
|
XCloseDisplay(g_window_data.display);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int screenWidth = DisplayWidth(s_display, s_screen);
|
int screenWidth = DisplayWidth(g_window_data.display, g_window_data.screen);
|
||||||
int screenHeight = DisplayHeight(s_display, s_screen);
|
int screenHeight = DisplayHeight(g_window_data.display, g_window_data.screen);
|
||||||
|
|
||||||
windowAttributes.border_pixel = BlackPixel(s_display, s_screen);
|
windowAttributes.border_pixel = BlackPixel(g_window_data.display, g_window_data.screen);
|
||||||
windowAttributes.background_pixel = BlackPixel(s_display, s_screen);
|
windowAttributes.background_pixel = BlackPixel(g_window_data.display, g_window_data.screen);
|
||||||
windowAttributes.backing_store = NotUseful;
|
windowAttributes.backing_store = NotUseful;
|
||||||
|
|
||||||
s_window = XCreateWindow(s_display, defaultRootWindow, (screenWidth - width) / 2,
|
int posX, posY;
|
||||||
(screenHeight - height) / 2, width, height, 0, depth, InputOutput,
|
int windowWidth, windowHeight;
|
||||||
visual, CWBackPixel | CWBorderPixel | CWBackingStore,
|
|
||||||
|
g_window_data.window_width = width;
|
||||||
|
g_window_data.window_height = height;
|
||||||
|
g_window_data.buffer_width = width;
|
||||||
|
g_window_data.buffer_height = height;
|
||||||
|
g_window_data.dst_offset_x = 0;
|
||||||
|
g_window_data.dst_offset_y = 0;
|
||||||
|
g_window_data.dst_width = width;
|
||||||
|
g_window_data.dst_height = height;
|
||||||
|
|
||||||
|
if (flags & WF_FULLSCREEN_DESKTOP) {
|
||||||
|
posX = 0;
|
||||||
|
posY = 0;
|
||||||
|
windowWidth = screenWidth;
|
||||||
|
windowHeight = screenHeight;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
posX = (screenWidth - width) / 2;
|
||||||
|
posY = (screenHeight - height) / 2;
|
||||||
|
windowWidth = width;
|
||||||
|
windowHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_window_data.window = XCreateWindow(
|
||||||
|
g_window_data.display,
|
||||||
|
defaultRootWindow,
|
||||||
|
posX, posY,
|
||||||
|
windowWidth, windowHeight,
|
||||||
|
0,
|
||||||
|
depth,
|
||||||
|
InputOutput,
|
||||||
|
visual,
|
||||||
|
CWBackPixel | CWBorderPixel | CWBackingStore,
|
||||||
&windowAttributes);
|
&windowAttributes);
|
||||||
if (!s_window)
|
if (!g_window_data.window)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
XSelectInput(s_display, s_window, KeyPressMask | KeyReleaseMask);
|
XSelectInput(g_window_data.display, g_window_data.window,
|
||||||
XStoreName(s_display, s_window, title);
|
KeyPressMask | KeyReleaseMask
|
||||||
|
| ButtonPressMask | ButtonReleaseMask | PointerMotionMask
|
||||||
|
| StructureNotifyMask | ExposureMask
|
||||||
|
| FocusChangeMask
|
||||||
|
| EnterWindowMask | LeaveWindowMask
|
||||||
|
);
|
||||||
|
|
||||||
|
XStoreName(g_window_data.display, g_window_data.window, title);
|
||||||
|
|
||||||
|
if (flags & WF_BORDERLESS) {
|
||||||
|
struct StyleHints {
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned long functions;
|
||||||
|
unsigned long decorations;
|
||||||
|
long inputMode;
|
||||||
|
unsigned long status;
|
||||||
|
} sh = {
|
||||||
|
.flags = 2,
|
||||||
|
.functions = 0,
|
||||||
|
.decorations = 0,
|
||||||
|
.inputMode = 0,
|
||||||
|
.status = 0,
|
||||||
|
};
|
||||||
|
Atom sh_p = XInternAtom(g_window_data.display, "_MOTIF_WM_HINTS", True);
|
||||||
|
XChangeProperty(g_window_data.display, g_window_data.window, sh_p, sh_p, 32, PropModeReplace, (unsigned char*)&sh, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WF_ALWAYS_ON_TOP) {
|
||||||
|
Atom sa_p = XInternAtom(g_window_data.display, "_NET_WM_STATE_ABOVE", False);
|
||||||
|
XChangeProperty(g_window_data.display, g_window_data.window, XInternAtom(g_window_data.display, "_NET_WM_STATE", False), XA_ATOM, 32, PropModeReplace, (unsigned char *)&sa_p, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WF_FULLSCREEN) {
|
||||||
|
Atom sf_p = XInternAtom(g_window_data.display, "_NET_WM_STATE_FULLSCREEN", True);
|
||||||
|
XChangeProperty(g_window_data.display, g_window_data.window, XInternAtom(g_window_data.display, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char*)&sf_p, 1);
|
||||||
|
}
|
||||||
|
|
||||||
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.min_height = height;
|
sizeHints.min_height = height;
|
||||||
|
if(flags & WF_RESIZABLE) {
|
||||||
|
sizeHints.max_width = screenWidth;
|
||||||
|
sizeHints.max_height = screenHeight;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sizeHints.max_width = width;
|
||||||
sizeHints.max_height = height;
|
sizeHints.max_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
XSetWMNormalHints(s_display, s_window, &sizeHints);
|
XSetWMNormalHints(g_window_data.display, g_window_data.window, &sizeHints);
|
||||||
XClearWindow(s_display, s_window);
|
XClearWindow(g_window_data.display, g_window_data.window);
|
||||||
XMapRaised(s_display, s_window);
|
XMapRaised(g_window_data.display, g_window_data.window);
|
||||||
XFlush(s_display);
|
XFlush(g_window_data.display);
|
||||||
|
|
||||||
s_gc = DefaultGC(s_display, s_screen);
|
g_window_data.gc = DefaultGC(g_window_data.display, g_window_data.screen);
|
||||||
|
|
||||||
s_ximage = XCreateImage(s_display, CopyFromParent, depth, ZPixmap, 0, NULL, width, height, 32, width * 4);
|
g_window_data.image = XCreateImage(g_window_data.display, CopyFromParent, depth, ZPixmap, 0, NULL, width, height, 32, width * 4);
|
||||||
|
|
||||||
s_width = width;
|
if (g_keyboard_func == 0x0) {
|
||||||
s_height = height;
|
mfb_keyboard_callback(keyboard_default);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Window created using X11 API\n");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mfb_open(const char* title, int width, int height)
|
||||||
|
{
|
||||||
|
return mfb_open_ex(title, width, height, 0);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int translate_key(int scancode);
|
||||||
|
int translate_mod(int state);
|
||||||
|
int translate_mod_ex(int key, int state, int is_pressed);
|
||||||
|
|
||||||
static int processEvents()
|
static int processEvents()
|
||||||
{
|
{
|
||||||
XEvent event;
|
XEvent event;
|
||||||
KeySym sym;
|
|
||||||
|
|
||||||
if (!XPending(s_display))
|
while ((g_window_data.close == false) && XPending(g_window_data.display)) {
|
||||||
return 0;
|
XNextEvent(g_window_data.display, &event);
|
||||||
|
|
||||||
XNextEvent(s_display, &event);
|
switch (event.type) {
|
||||||
|
case KeyPress:
|
||||||
|
case KeyRelease:
|
||||||
|
{
|
||||||
|
int kb_key = translate_key(event.xkey.keycode);
|
||||||
|
int is_pressed = (event.type == KeyPress);
|
||||||
|
g_window_data.mod_keys = translate_mod_ex(kb_key, event.xkey.state, is_pressed);
|
||||||
|
|
||||||
if (event.type != KeyPress)
|
kCall(g_keyboard_func, kb_key, g_window_data.mod_keys, is_pressed);
|
||||||
return 0;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
sym = XLookupKeysym(&event.xkey, 0);
|
case ButtonPress:
|
||||||
|
case ButtonRelease:
|
||||||
|
{
|
||||||
|
MouseButton button = event.xbutton.button;
|
||||||
|
int is_pressed = (event.type == ButtonPress);
|
||||||
|
g_window_data.mod_keys = translate_mod(event.xkey.state);
|
||||||
|
switch (button) {
|
||||||
|
case Button1:
|
||||||
|
case Button2:
|
||||||
|
case Button3:
|
||||||
|
kCall(g_mouse_btn_func, button, g_window_data.mod_keys, is_pressed);
|
||||||
|
break;
|
||||||
|
|
||||||
if ((sym >> 8) != KEY_FUNCTION)
|
case Button4:
|
||||||
return 0;
|
kCall(g_mouse_wheel_func, g_window_data.mod_keys, 0.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case Button5:
|
||||||
|
kCall(g_mouse_wheel_func, g_window_data.mod_keys, 0.0f, -1.0f);
|
||||||
|
break;
|
||||||
|
|
||||||
if ((sym & 0xFF) == KEY_ESC)
|
case 6:
|
||||||
|
kCall(g_mouse_wheel_func, g_window_data.mod_keys, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
kCall(g_mouse_wheel_func, g_window_data.mod_keys, -1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
kCall(g_mouse_btn_func, button - 4, g_window_data.mod_keys, is_pressed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionNotify:
|
||||||
|
kCall(g_mouse_move_func, event.xmotion.x, event.xmotion.y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ConfigureNotify:
|
||||||
|
{
|
||||||
|
g_window_data.window_width = event.xconfigure.width;
|
||||||
|
g_window_data.window_height = event.xconfigure.height;
|
||||||
|
g_window_data.dst_offset_x = 0;
|
||||||
|
g_window_data.dst_offset_y = 0;
|
||||||
|
g_window_data.dst_width = g_window_data.window_width;
|
||||||
|
g_window_data.dst_height = g_window_data.window_height;
|
||||||
|
|
||||||
|
XClearWindow(g_window_data.display, g_window_data.window);
|
||||||
|
kCall(g_resize_func, g_window_data.window_width, g_window_data.window_height);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EnterNotify:
|
||||||
|
case LeaveNotify:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FocusIn:
|
||||||
|
kCall(g_active_func, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FocusOut:
|
||||||
|
kCall(g_active_func, false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DestroyNotify:
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(g_window_data.close == true)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -126,10 +284,38 @@ static int processEvents()
|
|||||||
|
|
||||||
int mfb_update(void* buffer)
|
int mfb_update(void* buffer)
|
||||||
{
|
{
|
||||||
s_ximage->data = (char*)buffer;
|
if (buffer == 0x0) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
XPutImage(s_display, s_window, s_gc, s_ximage, 0, 0, 0, 0, s_width, s_height);
|
if (g_window_data.buffer_width != g_window_data.dst_width || g_window_data.buffer_height != g_window_data.dst_height) {
|
||||||
XFlush(s_display);
|
if(g_window_data.image_scaler_width != g_window_data.dst_width || g_window_data.image_scaler_height != g_window_data.dst_height) {
|
||||||
|
if(g_window_data.image_scaler != 0x0) {
|
||||||
|
g_window_data.image_scaler->data = 0x0;
|
||||||
|
XDestroyImage(g_window_data.image_scaler);
|
||||||
|
}
|
||||||
|
if(g_window_data.image_buffer != 0x0) {
|
||||||
|
free(g_window_data.image_buffer);
|
||||||
|
g_window_data.image_buffer = 0x0;
|
||||||
|
}
|
||||||
|
int depth = DefaultDepth(g_window_data.display, g_window_data.screen);
|
||||||
|
g_window_data.image_buffer = malloc(g_window_data.dst_width * g_window_data.dst_height * 4);
|
||||||
|
g_window_data.image_scaler_width = g_window_data.dst_width;
|
||||||
|
g_window_data.image_scaler_height = g_window_data.dst_height;
|
||||||
|
g_window_data.image_scaler = XCreateImage(g_window_data.display, CopyFromParent, depth, ZPixmap, 0, NULL, g_window_data.image_scaler_width, g_window_data.image_scaler_height, 32, g_window_data.image_scaler_width * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(g_window_data.image_scaler != 0x0) {
|
||||||
|
stretch_image(buffer, 0, 0, g_window_data.buffer_width, g_window_data.buffer_height, g_window_data.buffer_width, g_window_data.image_buffer, 0, 0, g_window_data.dst_width, g_window_data.dst_height, g_window_data.dst_width);
|
||||||
|
g_window_data.image_scaler->data = g_window_data.image_buffer;
|
||||||
|
XPutImage(g_window_data.display, g_window_data.window, g_window_data.gc, g_window_data.image_scaler, 0, 0, g_window_data.dst_offset_x, g_window_data.dst_offset_y, g_window_data.dst_width, g_window_data.dst_height);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g_window_data.image->data = (char *) buffer;
|
||||||
|
XPutImage(g_window_data.display, g_window_data.window, g_window_data.gc, g_window_data.image, 0, 0, g_window_data.dst_offset_x, g_window_data.dst_offset_y, g_window_data.dst_width, g_window_data.dst_height);
|
||||||
|
}
|
||||||
|
XFlush(g_window_data.display);
|
||||||
|
|
||||||
if (processEvents() < 0)
|
if (processEvents() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -139,10 +325,308 @@ int mfb_update(void* buffer)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void mfb_close (void)
|
void mfb_close(void)
|
||||||
{
|
{
|
||||||
s_ximage->data = NULL;
|
if(g_window_data.image != 0x0) {
|
||||||
XDestroyImage(s_ximage);
|
g_window_data.image->data = 0x0;
|
||||||
XDestroyWindow(s_display, s_window);
|
XDestroyImage(g_window_data.image);
|
||||||
XCloseDisplay(s_display);
|
XDestroyWindow(g_window_data.display, g_window_data.window);
|
||||||
|
XCloseDisplay(g_window_data.display);
|
||||||
|
|
||||||
|
g_window_data.image = 0x0;
|
||||||
|
g_window_data.display = 0x0;
|
||||||
|
g_window_data.window = 0;
|
||||||
|
}
|
||||||
|
g_window_data.close = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
extern short int keycodes[512];
|
||||||
|
|
||||||
|
static int translateKeyCodeB(int keySym) {
|
||||||
|
|
||||||
|
switch (keySym)
|
||||||
|
{
|
||||||
|
case XK_KP_0: return KB_KEY_KP_0;
|
||||||
|
case XK_KP_1: return KB_KEY_KP_1;
|
||||||
|
case XK_KP_2: return KB_KEY_KP_2;
|
||||||
|
case XK_KP_3: return KB_KEY_KP_3;
|
||||||
|
case XK_KP_4: return KB_KEY_KP_4;
|
||||||
|
case XK_KP_5: return KB_KEY_KP_5;
|
||||||
|
case XK_KP_6: return KB_KEY_KP_6;
|
||||||
|
case XK_KP_7: return KB_KEY_KP_7;
|
||||||
|
case XK_KP_8: return KB_KEY_KP_8;
|
||||||
|
case XK_KP_9: return KB_KEY_KP_9;
|
||||||
|
case XK_KP_Separator:
|
||||||
|
case XK_KP_Decimal: return KB_KEY_KP_DECIMAL;
|
||||||
|
case XK_KP_Equal: return KB_KEY_KP_EQUAL;
|
||||||
|
case XK_KP_Enter: return KB_KEY_KP_ENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KB_KEY_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int translateKeyCodeA(int keySym) {
|
||||||
|
switch (keySym)
|
||||||
|
{
|
||||||
|
case XK_Escape: return KB_KEY_ESCAPE;
|
||||||
|
case XK_Tab: return KB_KEY_TAB;
|
||||||
|
case XK_Shift_L: return KB_KEY_LEFT_SHIFT;
|
||||||
|
case XK_Shift_R: return KB_KEY_RIGHT_SHIFT;
|
||||||
|
case XK_Control_L: return KB_KEY_LEFT_CONTROL;
|
||||||
|
case XK_Control_R: return KB_KEY_RIGHT_CONTROL;
|
||||||
|
case XK_Meta_L:
|
||||||
|
case XK_Alt_L: return KB_KEY_LEFT_ALT;
|
||||||
|
case XK_Mode_switch: // Mapped to Alt_R on many keyboards
|
||||||
|
case XK_ISO_Level3_Shift: // AltGr on at least some machines
|
||||||
|
case XK_Meta_R:
|
||||||
|
case XK_Alt_R: return KB_KEY_RIGHT_ALT;
|
||||||
|
case XK_Super_L: return KB_KEY_LEFT_SUPER;
|
||||||
|
case XK_Super_R: return KB_KEY_RIGHT_SUPER;
|
||||||
|
case XK_Menu: return KB_KEY_MENU;
|
||||||
|
case XK_Num_Lock: return KB_KEY_NUM_LOCK;
|
||||||
|
case XK_Caps_Lock: return KB_KEY_CAPS_LOCK;
|
||||||
|
case XK_Print: return KB_KEY_PRINT_SCREEN;
|
||||||
|
case XK_Scroll_Lock: return KB_KEY_SCROLL_LOCK;
|
||||||
|
case XK_Pause: return KB_KEY_PAUSE;
|
||||||
|
case XK_Delete: return KB_KEY_DELETE;
|
||||||
|
case XK_BackSpace: return KB_KEY_BACKSPACE;
|
||||||
|
case XK_Return: return KB_KEY_ENTER;
|
||||||
|
case XK_Home: return KB_KEY_HOME;
|
||||||
|
case XK_End: return KB_KEY_END;
|
||||||
|
case XK_Page_Up: return KB_KEY_PAGE_UP;
|
||||||
|
case XK_Page_Down: return KB_KEY_PAGE_DOWN;
|
||||||
|
case XK_Insert: return KB_KEY_INSERT;
|
||||||
|
case XK_Left: return KB_KEY_LEFT;
|
||||||
|
case XK_Right: return KB_KEY_RIGHT;
|
||||||
|
case XK_Down: return KB_KEY_DOWN;
|
||||||
|
case XK_Up: return KB_KEY_UP;
|
||||||
|
case XK_F1: return KB_KEY_F1;
|
||||||
|
case XK_F2: return KB_KEY_F2;
|
||||||
|
case XK_F3: return KB_KEY_F3;
|
||||||
|
case XK_F4: return KB_KEY_F4;
|
||||||
|
case XK_F5: return KB_KEY_F5;
|
||||||
|
case XK_F6: return KB_KEY_F6;
|
||||||
|
case XK_F7: return KB_KEY_F7;
|
||||||
|
case XK_F8: return KB_KEY_F8;
|
||||||
|
case XK_F9: return KB_KEY_F9;
|
||||||
|
case XK_F10: return KB_KEY_F10;
|
||||||
|
case XK_F11: return KB_KEY_F11;
|
||||||
|
case XK_F12: return KB_KEY_F12;
|
||||||
|
case XK_F13: return KB_KEY_F13;
|
||||||
|
case XK_F14: return KB_KEY_F14;
|
||||||
|
case XK_F15: return KB_KEY_F15;
|
||||||
|
case XK_F16: return KB_KEY_F16;
|
||||||
|
case XK_F17: return KB_KEY_F17;
|
||||||
|
case XK_F18: return KB_KEY_F18;
|
||||||
|
case XK_F19: return KB_KEY_F19;
|
||||||
|
case XK_F20: return KB_KEY_F20;
|
||||||
|
case XK_F21: return KB_KEY_F21;
|
||||||
|
case XK_F22: return KB_KEY_F22;
|
||||||
|
case XK_F23: return KB_KEY_F23;
|
||||||
|
case XK_F24: return KB_KEY_F24;
|
||||||
|
case XK_F25: return KB_KEY_F25;
|
||||||
|
|
||||||
|
// Numeric keypad
|
||||||
|
case XK_KP_Divide: return KB_KEY_KP_DIVIDE;
|
||||||
|
case XK_KP_Multiply: return KB_KEY_KP_MULTIPLY;
|
||||||
|
case XK_KP_Subtract: return KB_KEY_KP_SUBTRACT;
|
||||||
|
case XK_KP_Add: return KB_KEY_KP_ADD;
|
||||||
|
|
||||||
|
// These should have been detected in secondary keysym test above!
|
||||||
|
case XK_KP_Insert: return KB_KEY_KP_0;
|
||||||
|
case XK_KP_End: return KB_KEY_KP_1;
|
||||||
|
case XK_KP_Down: return KB_KEY_KP_2;
|
||||||
|
case XK_KP_Page_Down: return KB_KEY_KP_3;
|
||||||
|
case XK_KP_Left: return KB_KEY_KP_4;
|
||||||
|
case XK_KP_Right: return KB_KEY_KP_6;
|
||||||
|
case XK_KP_Home: return KB_KEY_KP_7;
|
||||||
|
case XK_KP_Up: return KB_KEY_KP_8;
|
||||||
|
case XK_KP_Page_Up: return KB_KEY_KP_9;
|
||||||
|
case XK_KP_Delete: return KB_KEY_KP_DECIMAL;
|
||||||
|
case XK_KP_Equal: return KB_KEY_KP_EQUAL;
|
||||||
|
case XK_KP_Enter: return KB_KEY_KP_ENTER;
|
||||||
|
|
||||||
|
// Last resort: Check for printable keys (should not happen if the XKB
|
||||||
|
// extension is available). This will give a layout dependent mapping
|
||||||
|
// (which is wrong, and we may miss some keys, especially on non-US
|
||||||
|
// keyboards), but it's better than nothing...
|
||||||
|
case XK_a: return KB_KEY_A;
|
||||||
|
case XK_b: return KB_KEY_B;
|
||||||
|
case XK_c: return KB_KEY_C;
|
||||||
|
case XK_d: return KB_KEY_D;
|
||||||
|
case XK_e: return KB_KEY_E;
|
||||||
|
case XK_f: return KB_KEY_F;
|
||||||
|
case XK_g: return KB_KEY_G;
|
||||||
|
case XK_h: return KB_KEY_H;
|
||||||
|
case XK_i: return KB_KEY_I;
|
||||||
|
case XK_j: return KB_KEY_J;
|
||||||
|
case XK_k: return KB_KEY_K;
|
||||||
|
case XK_l: return KB_KEY_L;
|
||||||
|
case XK_m: return KB_KEY_M;
|
||||||
|
case XK_n: return KB_KEY_N;
|
||||||
|
case XK_o: return KB_KEY_O;
|
||||||
|
case XK_p: return KB_KEY_P;
|
||||||
|
case XK_q: return KB_KEY_Q;
|
||||||
|
case XK_r: return KB_KEY_R;
|
||||||
|
case XK_s: return KB_KEY_S;
|
||||||
|
case XK_t: return KB_KEY_T;
|
||||||
|
case XK_u: return KB_KEY_U;
|
||||||
|
case XK_v: return KB_KEY_V;
|
||||||
|
case XK_w: return KB_KEY_W;
|
||||||
|
case XK_x: return KB_KEY_X;
|
||||||
|
case XK_y: return KB_KEY_Y;
|
||||||
|
case XK_z: return KB_KEY_Z;
|
||||||
|
case XK_1: return KB_KEY_1;
|
||||||
|
case XK_2: return KB_KEY_2;
|
||||||
|
case XK_3: return KB_KEY_3;
|
||||||
|
case XK_4: return KB_KEY_4;
|
||||||
|
case XK_5: return KB_KEY_5;
|
||||||
|
case XK_6: return KB_KEY_6;
|
||||||
|
case XK_7: return KB_KEY_7;
|
||||||
|
case XK_8: return KB_KEY_8;
|
||||||
|
case XK_9: return KB_KEY_9;
|
||||||
|
case XK_0: return KB_KEY_0;
|
||||||
|
case XK_space: return KB_KEY_SPACE;
|
||||||
|
case XK_minus: return KB_KEY_MINUS;
|
||||||
|
case XK_equal: return KB_KEY_EQUAL;
|
||||||
|
case XK_bracketleft: return KB_KEY_LEFT_BRACKET;
|
||||||
|
case XK_bracketright: return KB_KEY_RIGHT_BRACKET;
|
||||||
|
case XK_backslash: return KB_KEY_BACKSLASH;
|
||||||
|
case XK_semicolon: return KB_KEY_SEMICOLON;
|
||||||
|
case XK_apostrophe: return KB_KEY_APOSTROPHE;
|
||||||
|
case XK_grave: return KB_KEY_GRAVE_ACCENT;
|
||||||
|
case XK_comma: return KB_KEY_COMMA;
|
||||||
|
case XK_period: return KB_KEY_PERIOD;
|
||||||
|
case XK_slash: return KB_KEY_SLASH;
|
||||||
|
case XK_less: return KB_KEY_WORLD_1; // At least in some layouts...
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KB_KEY_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_keycodes() {
|
||||||
|
size_t i;
|
||||||
|
int keySym;
|
||||||
|
|
||||||
|
// Clear keys
|
||||||
|
for (i = 0; i < sizeof(keycodes) / sizeof(keycodes[0]); ++i)
|
||||||
|
keycodes[i] = KB_KEY_UNKNOWN;
|
||||||
|
|
||||||
|
// Valid key code range is [8,255], according to the Xlib manual
|
||||||
|
for(int i=8; i<=255; ++i) {
|
||||||
|
// Try secondary keysym, for numeric keypad keys
|
||||||
|
keySym = XkbKeycodeToKeysym(g_window_data.display, i, 0, 1);
|
||||||
|
keycodes[i] = translateKeyCodeB(keySym);
|
||||||
|
if(keycodes[i] == KB_KEY_UNKNOWN) {
|
||||||
|
keySym = XkbKeycodeToKeysym(g_window_data.display, i, 0, 0);
|
||||||
|
keycodes[i] = translateKeyCodeA(keySym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int translate_key(int scancode) {
|
||||||
|
if (scancode < 0 || scancode > 255)
|
||||||
|
return KB_KEY_UNKNOWN;
|
||||||
|
|
||||||
|
return keycodes[scancode];
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int translate_mod(int state) {
|
||||||
|
int mod_keys = 0;
|
||||||
|
|
||||||
|
if (state & ShiftMask)
|
||||||
|
mod_keys |= KB_MOD_SHIFT;
|
||||||
|
if (state & ControlMask)
|
||||||
|
mod_keys |= KB_MOD_CONTROL;
|
||||||
|
if (state & Mod1Mask)
|
||||||
|
mod_keys |= KB_MOD_ALT;
|
||||||
|
if (state & Mod4Mask)
|
||||||
|
mod_keys |= KB_MOD_SUPER;
|
||||||
|
if (state & LockMask)
|
||||||
|
mod_keys |= KB_MOD_CAPS_LOCK;
|
||||||
|
if (state & Mod2Mask)
|
||||||
|
mod_keys |= KB_MOD_NUM_LOCK;
|
||||||
|
|
||||||
|
return mod_keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int translate_mod_ex(int key, int state, int is_pressed) {
|
||||||
|
int mod_keys = 0;
|
||||||
|
|
||||||
|
mod_keys = translate_mod(state);
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case KB_KEY_LEFT_SHIFT:
|
||||||
|
case KB_KEY_RIGHT_SHIFT:
|
||||||
|
if(is_pressed)
|
||||||
|
mod_keys |= KB_MOD_SHIFT;
|
||||||
|
else
|
||||||
|
mod_keys &= ~KB_MOD_SHIFT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_CONTROL:
|
||||||
|
case KB_KEY_RIGHT_CONTROL:
|
||||||
|
if(is_pressed)
|
||||||
|
mod_keys |= KB_MOD_CONTROL;
|
||||||
|
else
|
||||||
|
mod_keys &= ~KB_MOD_CONTROL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_ALT:
|
||||||
|
case KB_KEY_RIGHT_ALT:
|
||||||
|
if(is_pressed)
|
||||||
|
mod_keys |= KB_MOD_ALT;
|
||||||
|
else
|
||||||
|
mod_keys &= ~KB_MOD_ALT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KB_KEY_LEFT_SUPER:
|
||||||
|
case KB_KEY_RIGHT_SUPER:
|
||||||
|
if(is_pressed)
|
||||||
|
mod_keys |= KB_MOD_SUPER;
|
||||||
|
else
|
||||||
|
mod_keys &= ~KB_MOD_SUPER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mod_keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void keyboard_default(void *user_data, Key key, KeyMod mod, bool isPressed) {
|
||||||
|
kUnused(user_data);
|
||||||
|
kUnused(mod);
|
||||||
|
kUnused(isPressed);
|
||||||
|
if (key == KB_KEY_ESCAPE) {
|
||||||
|
g_window_data.close = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool mfb_set_viewport(unsigned offset_x, unsigned offset_y, unsigned width, unsigned height)
|
||||||
|
{
|
||||||
|
if(offset_x + width > g_window_data.window_width) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(offset_y + height > g_window_data.window_height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_window_data.dst_offset_x = offset_x;
|
||||||
|
g_window_data.dst_offset_y = offset_y;
|
||||||
|
g_window_data.dst_width = width;
|
||||||
|
g_window_data.dst_height = height;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
34
src/x11/X11WindowData.h
Normal file
34
src/x11/X11WindowData.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <MiniFB_enums.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Window window;
|
||||||
|
uint32_t window_width;
|
||||||
|
uint32_t window_height;
|
||||||
|
|
||||||
|
uint32_t dst_offset_x;
|
||||||
|
uint32_t dst_offset_y;
|
||||||
|
uint32_t dst_width;
|
||||||
|
uint32_t dst_height;
|
||||||
|
|
||||||
|
void *draw_buffer;
|
||||||
|
uint32_t buffer_width;
|
||||||
|
uint32_t buffer_height;
|
||||||
|
|
||||||
|
uint32_t mod_keys;
|
||||||
|
bool close;
|
||||||
|
|
||||||
|
Display *display;
|
||||||
|
int screen;
|
||||||
|
GC gc;
|
||||||
|
XImage *image;
|
||||||
|
|
||||||
|
void *image_buffer;
|
||||||
|
XImage *image_scaler;
|
||||||
|
uint32_t image_scaler_width;
|
||||||
|
uint32_t image_scaler_height;
|
||||||
|
} SWindowData;
|
123
tests/noise.c
123
tests/noise.c
@ -1,16 +1,137 @@
|
|||||||
#include <MiniFB.h>
|
#include <MiniFB.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define kUnused(var) (void) var;
|
||||||
|
|
||||||
#define WIDTH 800
|
#define WIDTH 800
|
||||||
#define HEIGHT 600
|
#define HEIGHT 600
|
||||||
static unsigned int s_buffer[WIDTH * HEIGHT];
|
static unsigned int s_buffer[WIDTH * HEIGHT];
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
// C interface
|
||||||
|
//-------------------------------------
|
||||||
|
void active(void *user_data, bool isActive) {
|
||||||
|
kUnused(user_data);
|
||||||
|
fprintf(stdout, "active: %d\n", isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(void *user_data, int width, int height) {
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
|
||||||
|
kUnused(user_data);
|
||||||
|
fprintf(stdout, "resize: %d, %d\n", width, height);
|
||||||
|
if(width > WIDTH) {
|
||||||
|
x = (width - WIDTH) >> 1;
|
||||||
|
width = WIDTH;
|
||||||
|
}
|
||||||
|
if(height > HEIGHT) {
|
||||||
|
y = (height - HEIGHT) >> 1;
|
||||||
|
height = HEIGHT;
|
||||||
|
}
|
||||||
|
mfb_set_viewport(x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard(void *user_data, Key key, KeyMod mod, bool isPressed) {
|
||||||
|
kUnused(user_data);
|
||||||
|
fprintf(stdout, "keyboard: key: %s (pressed: %d) [KeyMod: %x]\n", mfb_get_key_name(key), isPressed, mod);
|
||||||
|
if(key == KB_KEY_ESCAPE) {
|
||||||
|
mfb_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void char_input(void *user_data, unsigned int charCode) {
|
||||||
|
kUnused(user_data);
|
||||||
|
fprintf(stdout, "charCode: %d\n", charCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_btn(void *user_data, MouseButton button, KeyMod mod, bool isPressed) {
|
||||||
|
kUnused(user_data);
|
||||||
|
fprintf(stdout, "mouse_btn: button: %d (pressed: %d) [KeyMod: %x]\n", button, isPressed, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_move(void *user_data, int x, int y) {
|
||||||
|
kUnused(user_data);
|
||||||
|
kUnused(x);
|
||||||
|
kUnused(y);
|
||||||
|
//fprintf(stdout, "mouse_move: %d, %d\n", x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_scroll(void *user_data, KeyMod mod, float deltaX, float deltaY) {
|
||||||
|
kUnused(user_data);
|
||||||
|
fprintf(stdout, "mouse_scroll: x: %f, y: %f [KeyMod: %x]\n", deltaX, deltaY, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
// C++ interface (calling C functions)
|
||||||
|
//-------------------------------------
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
|
||||||
|
class Events {
|
||||||
|
public:
|
||||||
|
void active(void *user_data, bool isActive) {
|
||||||
|
::active(user_data, isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(void *user_data, int width, int height) {
|
||||||
|
::resize(user_data, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard(void *user_data, Key key, KeyMod mod, bool isPressed) {
|
||||||
|
::keyboard(user_data, key, mod, isPressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void char_input(void *user_data, unsigned int charCode) {
|
||||||
|
::char_input(user_data, charCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_btn(void *user_data, MouseButton button, KeyMod mod, bool isPressed) {
|
||||||
|
::mouse_btn(user_data, button, mod, isPressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_move(void *user_data, int x, int y) {
|
||||||
|
::mouse_move(user_data, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_scroll(void *user_data, KeyMod mod, float deltaX, float deltaY) {
|
||||||
|
::mouse_scroll(user_data, mod, deltaX, deltaY);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
int noise, carry, seed = 0xbeef;
|
int noise, carry, seed = 0xbeef;
|
||||||
|
|
||||||
if (!mfb_open("Noise Test", WIDTH, HEIGHT))
|
#if defined(__cplusplus)
|
||||||
|
|
||||||
|
Events e;
|
||||||
|
|
||||||
|
mfb_active_callback(&e, &Events::active);
|
||||||
|
mfb_resize_callback(&e, &Events::resize);
|
||||||
|
mfb_keyboard_callback(&e, &Events::keyboard);
|
||||||
|
mfb_char_input_callback(&e, &Events::char_input);
|
||||||
|
mfb_mouse_button_callback(&e, &Events::mouse_btn);
|
||||||
|
mfb_mouse_move_callback(&e, &Events::mouse_move);
|
||||||
|
mfb_mouse_scroll_callback(&e, &Events::mouse_scroll);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
mfb_active_callback(active);
|
||||||
|
mfb_resize_callback(resize);
|
||||||
|
mfb_keyboard_callback(keyboard);
|
||||||
|
mfb_char_input_callback(char_input);
|
||||||
|
mfb_mouse_button_callback(mouse_btn);
|
||||||
|
mfb_mouse_move_callback(mouse_move);
|
||||||
|
mfb_mouse_scroll_callback(mouse_scroll);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!mfb_open_ex("Noise Test", WIDTH, HEIGHT, WF_RESIZABLE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
Loading…
Reference in New Issue
Block a user