diff --git a/CMakeLists.txt b/CMakeLists.txt index b286d7a..aec5d34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,75 +1,76 @@ -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() +cmake_minimum_required(VERSION 2.8.11) +project (noise) + +include_directories(include src) + +file(GLOB SrcLib "src/*.c" + "src/*.cpp" + "src/*.h" + "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 -pedantic -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() diff --git a/include/MiniFB.h b/include/MiniFB.h index 6f302b0..81a62c6 100644 --- a/include/MiniFB.h +++ b/include/MiniFB.h @@ -9,43 +9,35 @@ extern "C" { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#define MFB_RGB(r, g, b) (((unsigned int)r) << 16) | (((unsigned int)g) << 8) | b +#define MFB_RGB(r, g, b) (((unsigned int) r) << 16) | (((unsigned int) g) << 8) | (b) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 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_ex(const char* name, int width, int height, int flags); +struct Window *mfb_open(const char *title, int width, int height); +struct Window *mfb_open_ex(const char *title, 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 -// Will return -1 when ESC key is pressed (later on will return keycode and -1 on other close signal) -int mfb_update(void* buffer); +// Will return a negative status if something went wrong or the user want to exit. +UpdateState mfb_update(struct Window *window, void* buffer); // Close the window -void mfb_close(); +void mfb_close(struct Window *window); // Set user data -void mfb_set_user_data(void *user_data); +void mfb_set_user_data(struct Window *window, void *user_data); +void *mfb_get_user_data(struct Window *window); // Set viewport (useful when resize) -bool mfb_set_viewport(unsigned offset_x, unsigned offset_y, unsigned width, unsigned height); +bool mfb_set_viewport(struct Window *window, 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); +void mfb_active_callback(struct Window *window, mfb_active_func callback); +void mfb_resize_callback(struct Window *window, mfb_resize_func callback); +void mfb_keyboard_callback(struct Window *window, mfb_keyboard_func callback); +void mfb_char_input_callback(struct Window *window, mfb_char_input_func callback); +void mfb_mouse_button_callback(struct Window *window, mfb_mouse_btn_func callback); +void mfb_mouse_move_callback(struct Window *window, mfb_mouse_move_func callback); +void mfb_mouse_scroll_callback(struct Window *window, mfb_mouse_scroll_func callback); const char *mfb_get_key_name(Key key); diff --git a/include/MiniFB_cpp.h b/include/MiniFB_cpp.h index f665a0b..c8247d6 100755 --- a/include/MiniFB_cpp.h +++ b/include/MiniFB_cpp.h @@ -6,119 +6,129 @@ #include "MiniFB.h" template -void mfb_active_callback(T *obj, void (T::*method)(void *, bool)); +void mfb_active_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, bool)); template -void mfb_resize_callback(T *obj, void (T::*method)(void *, int, int)); +void mfb_resize_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, int, int)); template -void mfb_keyboard_callback(T *obj, void (T::*method)(void *, Key, KeyMod, bool)); +void mfb_keyboard_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, Key, KeyMod, bool)); template -void mfb_char_input_callback(T *obj, void (T::*method)(void *, unsigned int)); +void mfb_char_input_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, unsigned int)); template -void mfb_mouse_button_callback(T *obj, void (T::*method)(void *, MouseButton, KeyMod, bool)); +void mfb_mouse_button_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, MouseButton, KeyMod, bool)); template -void mfb_mouse_move_callback(T *obj, void (T::*method)(void *, int, int)); +void mfb_mouse_move_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, int, int)); template -void mfb_mouse_scroll_callback(T *obj, void (T::*method)(void *, KeyMod, float, float)); +void mfb_mouse_scroll_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, KeyMod, float, float)); //------------------------------------- // To avoid clumsy hands //------------------------------------- class Stub { template - friend void mfb_active_callback(T *obj, void (T::*method)(void *, bool)); + friend void mfb_active_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, bool)); template - friend void mfb_resize_callback(T *obj, void (T::*method)(void *, int, int)); + friend void mfb_resize_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, int, int)); template - friend void mfb_mouse_button_callback(T *obj, void (T::*method)(void *, MouseButton, KeyMod, bool)); + friend void mfb_mouse_button_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, MouseButton, KeyMod, bool)); template - friend void mfb_keyboard_callback(T *obj, void (T::*method)(void *, Key, KeyMod, bool)); + friend void mfb_keyboard_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, Key, KeyMod, bool)); template - friend void mfb_char_input_callback(T *obj, void (T::*method)(void *, unsigned int)); + friend void mfb_char_input_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, unsigned int)); template - friend void mfb_mouse_button_callback(T *obj, void (T::*method)(void *, MouseButton, KeyMod, bool)); + friend void mfb_mouse_button_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, MouseButton, KeyMod, bool)); template - friend void mfb_mouse_move_callback(T *obj, void (T::*method)(void *, int, int)); + friend void mfb_mouse_move_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, int, int)); template - friend void mfb_mouse_scroll_callback(T *obj, void (T::*method)(void *, KeyMod, float, float)); + friend void mfb_mouse_scroll_callback(struct Window *window, T *obj, void (T::*method)(struct Window *, 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 Stub *GetInstance(struct Window *window); - static std::function m_active; - static std::function m_resize; - static std::function m_keyboard; - static std::function m_char_input; - static std::function m_mouse_btn; - static std::function m_mouse_move; - static std::function m_scroll; + static void active_stub(struct Window *window, bool isActive); + static void resize_stub(struct Window *window, int width, int height); + static void keyboard_stub(struct Window *window, Key key, KeyMod mod, bool isPressed); + static void char_input_stub(struct Window *window, unsigned int); + static void mouse_btn_stub(struct Window *window, MouseButton button, KeyMod mod, bool isPressed); + static void mouse_move_stub(struct Window *window, int x, int y); + static void scroll_stub(struct Window *window, KeyMod mod, float deltaX, float deltaY); + + struct Window *m_window; + std::function m_active; + std::function m_resize; + std::function m_keyboard; + std::function m_char_input; + std::function m_mouse_btn; + std::function m_mouse_move; + std::function m_scroll; }; //------------------------------------- template -inline void mfb_active_callback(T *obj, void (T::*method)(void *user_data, bool)) { +inline void mfb_active_callback(struct Window *window, T *obj, void (T::*method)(struct Window *window, bool)) { using namespace std::placeholders; - Stub::m_active = std::bind(method, obj, _1, _2); - mfb_active_callback(Stub::active_stub); + Stub *stub = Stub::GetInstance(window); + stub->m_active = std::bind(method, obj, _1, _2); + mfb_active_callback(window, Stub::active_stub); } template -inline void mfb_resize_callback(T *obj, void (T::*method)(void *user_data, int, int)) { +inline void mfb_resize_callback(struct Window *window, T *obj, void (T::*method)(struct Window *window, int, int)) { using namespace std::placeholders; - Stub::m_resize = std::bind(method, obj, _1, _2, _3); - mfb_resize_callback(Stub::resize_stub); + Stub *stub = Stub::GetInstance(window); + stub->m_resize = std::bind(method, obj, _1, _2, _3); + mfb_resize_callback(window, Stub::resize_stub); } template -inline void mfb_keyboard_callback(T *obj, void (T::*method)(void *user_data, Key, KeyMod, bool)) { +inline void mfb_keyboard_callback(struct Window *window, T *obj, void (T::*method)(struct Window *window, Key, KeyMod, bool)) { using namespace std::placeholders; - Stub::m_keyboard = std::bind(method, obj, _1, _2, _3, _4); - mfb_keyboard_callback(Stub::keyboard_stub); + Stub *stub = Stub::GetInstance(window); + stub->m_keyboard = std::bind(method, obj, _1, _2, _3, _4); + mfb_keyboard_callback(window, Stub::keyboard_stub); } template -inline void mfb_char_input_callback(T *obj, void (T::*method)(void *user_data, unsigned int)) { +inline void mfb_char_input_callback(struct Window *window, T *obj, void (T::*method)(struct Window *window, unsigned int)) { using namespace std::placeholders; - Stub::m_char_input = std::bind(method, obj, _1, _2); - mfb_char_input_callback(Stub::char_input_stub); + Stub *stub = Stub::GetInstance(window); + stub->m_char_input = std::bind(method, obj, _1, _2); + mfb_char_input_callback(window, Stub::char_input_stub); } template -inline void mfb_mouse_button_callback(T *obj, void (T::*method)(void *user_data, MouseButton, KeyMod, bool)) { +inline void mfb_mouse_button_callback(struct Window *window, T *obj, void (T::*method)(struct Window *window, 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); + Stub *stub = Stub::GetInstance(window); + stub->m_mouse_btn = std::bind(method, obj, _1, _2, _3, _4); + mfb_mouse_button_callback(window, Stub::mouse_btn_stub); } template -inline void mfb_mouse_move_callback(T *obj, void (T::*method)(void *user_data, int, int)) { +inline void mfb_mouse_move_callback(struct Window *window, T *obj, void (T::*method)(struct Window *window, 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); + Stub *stub = Stub::GetInstance(window); + stub->m_mouse_move = std::bind(method, obj, _1, _2, _3); + mfb_mouse_move_callback(window, Stub::mouse_move_stub); } template -inline void mfb_mouse_scroll_callback(T *obj, void (T::*method)(void *user_data, KeyMod, float, float)) { +inline void mfb_mouse_scroll_callback(struct Window *window, T *obj, void (T::*method)(struct Window *window, 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); + Stub *stub = Stub::GetInstance(window); + stub->m_scroll = std::bind(method, obj, _1, _2, _3, _4); + mfb_mouse_scroll_callback(window, Stub::scroll_stub); } #endif diff --git a/include/MiniFB_enums.h b/include/MiniFB_enums.h index cc7b6fd..4d4058e 100755 --- a/include/MiniFB_enums.h +++ b/include/MiniFB_enums.h @@ -2,6 +2,15 @@ #include +// Enums +typedef enum { + STATE_OK = 0, + STATE_EXIT = -1, + STATE_INVALID_WINDOW = -2, + STATE_INVALID_BUFFER = -3, + STATE_INTERNAL_ERROR = -4, +} UpdateState; + typedef enum { MOUSE_BTN_0, // No mouse button MOUSE_BTN_1, @@ -161,3 +170,16 @@ typedef enum { WF_BORDERLESS = 0x08, WF_ALWAYS_ON_TOP = 0x10, } WindowFlags; + +// Opaque pointer +struct Window; + +// Event callbacks +typedef void(*mfb_active_func)(struct Window *window, bool isActive); +typedef void(*mfb_resize_func)(struct Window *window, int width, int height); +typedef void(*mfb_keyboard_func)(struct Window *window, Key key, KeyMod mod, bool isPressed); +typedef void(*mfb_char_input_func)(struct Window *window, unsigned int code); +typedef void(*mfb_mouse_btn_func)(struct Window *window, MouseButton button, KeyMod mod, bool isPressed); +typedef void(*mfb_mouse_move_func)(struct Window *window, int x, int y); +typedef void(*mfb_mouse_scroll_func)(struct Window *window, KeyMod mod, float deltaX, float deltaY); + diff --git a/src/MiniFB_common.c b/src/MiniFB_common.c index 3e24254..4941b1a 100755 --- a/src/MiniFB_common.c +++ b/src/MiniFB_common.c @@ -1,56 +1,101 @@ #include "MiniFB.h" +#include "WindowData.h" +#include //------------------------------------- -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_active_callback(struct Window *window, mfb_active_func callback) { + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + window_data->active_func = callback; + } } //------------------------------------- -void mfb_resize_callback(mfb_resize_func callback) { - g_resize_func = callback; +void mfb_resize_callback(struct Window *window, mfb_resize_func callback) { + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + window_data->resize_func = callback; + } } //------------------------------------- -void mfb_keyboard_callback(mfb_keyboard_func callback) { - g_keyboard_func = callback; +void mfb_keyboard_callback(struct Window *window, mfb_keyboard_func callback) { + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + window_data->keyboard_func = callback; + } } //------------------------------------- -void mfb_char_input_callback(mfb_char_input_func callback) { - g_char_input_func = callback; +void mfb_char_input_callback(struct Window *window, mfb_char_input_func callback) { + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + window_data->char_input_func = callback; + } } //------------------------------------- -void mfb_mouse_button_callback(mfb_mouse_btn_func callback) { - g_mouse_btn_func = callback; +void mfb_mouse_button_callback(struct Window *window, mfb_mouse_btn_func callback) { + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + window_data->mouse_btn_func = callback; + } } //------------------------------------- -void mfb_mouse_move_callback(mfb_mouse_move_func callback) { - g_mouse_move_func = callback; +void mfb_mouse_move_callback(struct Window *window, mfb_mouse_move_func callback) { + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + window_data->mouse_move_func = callback; + } } //------------------------------------- -void mfb_mouse_scroll_callback(mfb_mouse_scroll_func callback) { - g_mouse_wheel_func = callback; +void mfb_mouse_scroll_callback(struct Window *window, mfb_mouse_scroll_func callback) { + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + window_data->mouse_wheel_func = callback; + } } //------------------------------------- -void mfb_set_user_data(void *user_data) { - g_user_data = user_data; +void mfb_set_user_data(struct Window *window, void *user_data) { + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + window_data->user_data = user_data; + } } +//------------------------------------- +void *mfb_get_user_data(struct Window *window) { + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + return window_data->user_data; + } + + return 0x0; +} + +//------------------------------------- +void mfb_close(struct Window *window) +{ + if(window != 0x0) { + SWindowData *window_data = (SWindowData *) window; + window_data->close = true; + } +} + +//------------------------------------- +void keyboard_default(struct Window *window, Key key, KeyMod mod, bool isPressed) { + kUnused(mod); + kUnused(isPressed); + if (key == KB_KEY_ESCAPE) { + SWindowData *window_data = (SWindowData *) window; + window_data->close = true; + } +} + + //------------------------------------- const char *mfb_get_key_name(Key key) { @@ -418,4 +463,4 @@ const char *mfb_get_key_name(Key key) { } return "Unknown"; -} \ No newline at end of file +} diff --git a/src/MiniFB_cpp.cpp b/src/MiniFB_cpp.cpp index eb38303..bfaf56a 100755 --- a/src/MiniFB_cpp.cpp +++ b/src/MiniFB_cpp.cpp @@ -1,38 +1,54 @@ #include #include +#include -std::function Stub::m_active; -std::function Stub::m_resize; -std::function Stub::m_keyboard; -std::function Stub::m_char_input; -std::function Stub::m_mouse_btn; -std::function Stub::m_mouse_move; -std::function Stub::m_scroll; +Stub * +Stub::GetInstance(struct Window *window) { + static std::vector s_instances; -void Stub::active_stub(void *user_data, bool isActive) { - m_active(user_data, isActive); + for(Stub *instance : s_instances) { + if(instance->m_window == window) { + return instance; + } + } + + s_instances.push_back(new Stub); + s_instances.back()->m_window = window; + + return s_instances.back(); } -void Stub::resize_stub(void *user_data, int width, int height) { - m_resize(user_data, width, height); +void Stub::active_stub(struct Window *window, bool isActive) { + Stub *stub = Stub::GetInstance(window); + stub->m_active(window, isActive); } -void Stub::keyboard_stub(void *user_data, Key key, KeyMod mod, bool isPressed) { - m_keyboard(user_data, key, mod, isPressed); +void Stub::resize_stub(struct Window *window, int width, int height) { + Stub *stub = Stub::GetInstance(window); + stub->m_resize(window, width, height); } -void Stub::char_input_stub(void *user_data, unsigned int code) { - m_char_input(user_data, code); +void Stub::keyboard_stub(struct Window *window, Key key, KeyMod mod, bool isPressed) { + Stub *stub = Stub::GetInstance(window); + stub->m_keyboard(window, key, mod, isPressed); } -void Stub::mouse_btn_stub(void *user_data, MouseButton button, KeyMod mod, bool isPressed) { - m_mouse_btn(user_data, button, mod, isPressed); +void Stub::char_input_stub(struct Window *window, unsigned int code) { + Stub *stub = Stub::GetInstance(window); + stub->m_char_input(window, code); } -void Stub::mouse_move_stub(void *user_data, int x, int y) { - m_mouse_move(user_data, x, y); +void Stub::mouse_btn_stub(struct Window *window, MouseButton button, KeyMod mod, bool isPressed) { + Stub *stub = Stub::GetInstance(window); + stub->m_mouse_btn(window, button, mod, isPressed); } -void Stub::scroll_stub(void *user_data, KeyMod mod, float deltaX, float deltaY) { - m_scroll(user_data, mod, deltaX, deltaY); +void Stub::mouse_move_stub(struct Window *window, int x, int y) { + Stub *stub = Stub::GetInstance(window); + stub->m_mouse_move(window, x, y); +} + +void Stub::scroll_stub(struct Window *window, KeyMod mod, float deltaX, float deltaY) { + Stub *stub = Stub::GetInstance(window); + stub->m_scroll(window, mod, deltaX, deltaY); } diff --git a/src/MiniFB_internal.c b/src/MiniFB_internal.c index 5b74a3b..ed23e8e 100644 --- a/src/MiniFB_internal.c +++ b/src/MiniFB_internal.c @@ -72,4 +72,4 @@ void stretch_image(uint32_t *srcImage, uint32_t srcX, uint32_t srcY, uint32_t sr } dstImage += dstPitch; } -} \ No newline at end of file +} diff --git a/src/MiniFB_internal.h b/src/MiniFB_internal.h index f7b2010..c82148b 100755 --- a/src/MiniFB_internal.h +++ b/src/MiniFB_internal.h @@ -1,11 +1,10 @@ #pragma once #include "MiniFB.h" +#include "MiniFB_enums.h" -extern void *g_user_data; - -#define kCall(f, ...) if((f)) (f)(g_user_data, __VA_ARGS__); -#define kUnused(var) (void) var; +#define kCall(func, ...) if(window_data && window_data->func) window_data->func((struct Window *) window_data, __VA_ARGS__); +#define kUnused(var) (void) var; #if defined(__cplusplus) extern "C" { @@ -13,15 +12,7 @@ extern "C" { 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; + void keyboard_default(struct Window *window, Key key, KeyMod mod, bool isPressed); #if defined(__cplusplus) } diff --git a/src/WindowData.h b/src/WindowData.h new file mode 100644 index 0000000..79ffcb8 --- /dev/null +++ b/src/WindowData.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +typedef struct { + void *specific; + void *user_data; + + mfb_active_func active_func; + mfb_resize_func resize_func; + mfb_keyboard_func keyboard_func; + mfb_char_input_func char_input_func; + mfb_mouse_btn_func mouse_btn_func; + mfb_mouse_move_func mouse_move_func; + mfb_mouse_scroll_func mouse_wheel_func; + + 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 buffer_stride; + uint32_t mod_keys; + bool close; +} SWindowData; diff --git a/src/macosx/MacMiniFB.m b/src/macosx/MacMiniFB.m index a990b70..8cecd81 100644 --- a/src/macosx/MacMiniFB.m +++ b/src/macosx/MacMiniFB.m @@ -1,6 +1,6 @@ #include "OSXWindow.h" #include "OSXWindowFrameView.h" -#include "OSXWindowData.h" +#include "WindowData_OSX.h" #include #include #include @@ -11,15 +11,11 @@ #endif #include -SWindowData g_window_data = { 0 }; - void init_keycodes(); #if defined(USE_METAL_API) -extern id g_metal_device; -extern id g_command_queue; -extern id g_library; -extern id g_pipeline_state; +id g_metal_device; +id g_library; Vertex gVertices[4] = { {-1.0, -1.0, 0, 1}, @@ -32,93 +28,93 @@ Vertex gVertices[4] = { NSString* g_shadersSrc = @ " #include \n" - "using namespace metal;\n" + "using namespace metal;\n" - "struct VertexOutput {\n" - "float4 pos [[position]];\n" - "float2 texcoord;\n" - "};\n" + "struct VertexOutput {\n" + "float4 pos [[position]];\n" + "float2 texcoord;\n" + "};\n" - "vertex VertexOutput vertFunc(unsigned int vID[[vertex_id]])\n" - "{\n" - "VertexOutput out;\n" + "vertex VertexOutput vertFunc(unsigned int vID[[vertex_id]])\n" + "{\n" + "VertexOutput out;\n" - "out.pos.x = (float)(vID / 2) * 4.0 - 1.0;\n" - "out.pos.y = (float)(vID % 2) * 4.0 - 1.0;\n" - "out.pos.z = 0.0;\n" - "out.pos.w = 1.0;\n" + "out.pos.x = (float)(vID / 2) * 4.0 - 1.0;\n" + "out.pos.y = (float)(vID % 2) * 4.0 - 1.0;\n" + "out.pos.z = 0.0;\n" + "out.pos.w = 1.0;\n" - "out.texcoord.x = (float)(vID / 2) * 2.0;\n" - "out.texcoord.y = 1.0 - (float)(vID % 2) * 2.0;\n" + "out.texcoord.x = (float)(vID / 2) * 2.0;\n" + "out.texcoord.y = 1.0 - (float)(vID % 2) * 2.0;\n" - "return out;\n" - "}\n" + "return out;\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" + "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.pos = pos[vID].position;\n" - "out.texcoord.x = (float)(vID / 2);\n" - "out.texcoord.y = 1.0 - (float)(vID % 2);\n" + "out.texcoord.x = (float)(vID / 2);\n" + "out.texcoord.y = 1.0 - (float)(vID % 2);\n" - "return out;\n" - "}\n" + "return out;\n" + "}\n" - "fragment float4 fragFunc(VertexOutput input [[stage_in]],\n" - "texture2d colorTexture [[ texture(0) ]])\n" - "{\n" - "constexpr sampler textureSampler(mag_filter::nearest, min_filter::nearest);\n" + "fragment float4 fragFunc(VertexOutput input [[stage_in]],\n" + "texture2d colorTexture [[ texture(0) ]])\n" + "{\n" + "constexpr sampler textureSampler(mag_filter::nearest, min_filter::nearest);\n" - // Sample the texture to obtain a color - "const half4 colorSample = colorTexture.sample(textureSampler, input.texcoord);\n" + // Sample the texture to obtain a color + "const half4 colorSample = colorTexture.sample(textureSampler, input.texcoord);\n" - // We return the color of the texture - "return float4(colorSample);\n" - //"return float4(input.texcoord.x, input.texcoord.y, 0.0, 1.0);\n" - "}\n"; + // We return the color of the texture + "return float4(colorSample);\n" + //"return float4(input.texcoord.x, input.texcoord.y, 0.0, 1.0);\n" + "}\n"; #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #if defined(USE_METAL_API) -static bool create_shaders() { - // Error - NSError* nsError = NULL; - NSError** nsErrorPtr = &nsError; +static bool create_shaders(SWindowData_OSX *window_data_osx) { + // Error + NSError* nsError = 0x0; + NSError** nsErrorPtr = &nsError; - id library = [g_metal_device newLibraryWithSource:g_shadersSrc - options:[[MTLCompileOptions alloc] init] - error:nsErrorPtr]; + id library = [g_metal_device newLibraryWithSource:g_shadersSrc + options:[[MTLCompileOptions alloc] init] + error:nsErrorPtr]; - // Error update - if (nsError || !library) { - NSLog(@"Unable to create shaders %@", nsError); - return false; - } + // Error update + if (nsError || !library) { + NSLog(@"Unable to create shaders %@", nsError); + return false; + } - g_library = library; - NSLog(@"Names %@", [g_library functionNames]); + g_library = library; + NSLog(@"Names %@", [g_library functionNames]); - id vertex_shader_func = [g_library newFunctionWithName:@"vertFunc2"]; - id fragment_shader_func = [g_library newFunctionWithName:@"fragFunc"]; + id vertex_shader_func = [g_library newFunctionWithName:@"vertFunc2"]; + id fragment_shader_func = [g_library newFunctionWithName:@"fragFunc"]; - if (!vertex_shader_func) { - printf("Unable to get vertFunc!\n"); - return false; - } + if (!vertex_shader_func) { + printf("Unable to get vertFunc!\n"); + return false; + } - if (!fragment_shader_func) { - printf("Unable to get fragFunc!\n"); - return false; - } + if (!fragment_shader_func) { + printf("Unable to get fragFunc!\n"); + return false; + } // Create a reusable pipeline state MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; @@ -127,100 +123,108 @@ static bool create_shaders() { pipelineStateDescriptor.fragmentFunction = fragment_shader_func; pipelineStateDescriptor.colorAttachments[0].pixelFormat = 80; //bgra8Unorm; - NSError *error = NULL; - g_pipeline_state = [g_metal_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error]; - if (!g_pipeline_state) + NSError *error = 0x0; + window_data_osx->metal.pipeline_state = [g_metal_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error]; + if (!window_data_osx->metal.pipeline_state) { NSLog(@"Failed to created pipeline state, error %@", error); } - return true; + return true; } #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int mfb_open(const char* name, int width, int height) +struct Window *mfb_open(const char *title, int width, int height) { - return mfb_open_ex(name, width, height, 0); + return mfb_open_ex(title, width, height, 0); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int mfb_open_ex(const char* name, int width, int height, int flags) +struct Window *mfb_open_ex(const char *title, int width, int height, int flags) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; init_keycodes(); - g_window_data.window_width = width; - g_window_data.window_height = height; + SWindowData *window_data = malloc(sizeof(SWindowData)); + memset(window_data, 0, sizeof(SWindowData)); - g_window_data.dst_width = width; - g_window_data.dst_height = height; + SWindowData_OSX *window_data_osx = malloc(sizeof(SWindowData_OSX)); + memset(window_data_osx, 0, sizeof(SWindowData_OSX)); + window_data->specific = window_data_osx; - g_window_data.buffer_width = width; - g_window_data.buffer_height = height; + window_data->window_width = width; + window_data->window_height = height; - [NSApplication sharedApplication]; - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + window_data->dst_width = width; + window_data->dst_height = height; + + window_data->buffer_width = width; + window_data->buffer_height = height; + window_data->buffer_stride = width * 4; + + [NSApplication sharedApplication]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; #if defined(USE_METAL_API) - g_metal_device = MTLCreateSystemDefaultDevice(); + g_metal_device = MTLCreateSystemDefaultDevice(); - if (!g_metal_device) { - printf("Your device/OS doesn't support Metal."); - return -1; - } + if (!g_metal_device) { + printf("Your device/OS doesn't support Metal."); + return 0x0; + } - if (!create_shaders()) { - return -2; - } + if (!create_shaders((SWindowData_OSX *) window_data->specific)) { + return 0x0; + } #endif - NSWindowStyleMask styles = NSWindowStyleMaskClosable | NSWindowStyleMaskTitled; + NSWindowStyleMask styles = NSWindowStyleMaskClosable | NSWindowStyleMaskTitled; - if (flags & WF_BORDERLESS) - styles |= NSWindowStyleMaskBorderless; + if (flags & WF_BORDERLESS) + styles |= NSWindowStyleMaskBorderless; - if (flags & WF_RESIZABLE) - styles |= NSWindowStyleMaskResizable; + if (flags & WF_RESIZABLE) + styles |= NSWindowStyleMaskResizable; - NSRect rectangle = NSMakeRect(0, 0, width, height); - g_window_data.window = [[OSXWindow alloc] initWithContentRect:rectangle styleMask:styles backing:NSBackingStoreBuffered defer:NO]; - if (!g_window_data.window) - return -3; + NSRect rectangle = NSMakeRect(0, 0, width, height); + window_data_osx->window = [[OSXWindow alloc] initWithContentRect:rectangle styleMask:styles backing:NSBackingStoreBuffered defer:NO windowData:window_data]; + if (!window_data_osx->window) + return 0x0; #if defined(USE_METAL_API) - g_window_data.draw_buffer = malloc(width * height * 4); + window_data->draw_buffer = malloc(width * height * 4); - if (!g_window_data.draw_buffer) - return -4; + if (!window_data->draw_buffer) + return 0x0; - // Setup command queue - g_command_queue = [g_metal_device newCommandQueue]; + // Setup command queue + window_data_osx->metal.command_queue = [g_metal_device newCommandQueue]; WindowViewController* viewController = [WindowViewController new]; - MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init]; + MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init]; - // Indicate that each pixel has a blue, green, red, and alpha channel, where each channel is - // an 8-bit unsigned normalized value (i.e. 0 maps to 0.0 and 255 maps to 1.0) - textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm; + // Indicate that each pixel has a blue, green, red, and alpha channel, where each channel is + // an 8-bit unsigned normalized value (i.e. 0 maps to 0.0 and 255 maps to 1.0) + textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm; - // Set the pixel dimensions of the texture - textureDescriptor.width = width; - textureDescriptor.height = height; + // Set the pixel dimensions of the texture + textureDescriptor.width = width; + textureDescriptor.height = height; - // Create the texture from the device by using the descriptor - - for (int i = 0; i < MaxBuffersInFlight; ++i) { - viewController->m_texture_buffers[i] = [g_metal_device newTextureWithDescriptor:textureDescriptor]; - } + // Create the texture from the device by using the descriptor + + for (int i = 0; i < MaxBuffersInFlight; ++i) { + viewController->m_texture_buffers[i] = [g_metal_device newTextureWithDescriptor:textureDescriptor]; + } - // Used for syncing the CPU and GPU - viewController->m_semaphore = dispatch_semaphore_create(MaxBuffersInFlight); - viewController->m_draw_buffer = g_window_data.draw_buffer; + // Used for syncing the CPU and GPU + viewController->m_semaphore = dispatch_semaphore_create(MaxBuffersInFlight); + viewController->m_draw_buffer = window_data->draw_buffer; viewController->m_width = width; viewController->m_height = height; @@ -228,30 +232,29 @@ int mfb_open_ex(const char* name, int width, int height, int flags) view.device = g_metal_device; view.delegate = viewController; view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - [g_window_data.window.contentView addSubview:view]; + [window_data_osx->window.contentView addSubview:view]; - g_window_data.buffer_width = width; - g_window_data.buffer_height = height; + //window_data->buffer_width = width; + //window_data->buffer_height = height; + //window_data->buffer_stride = width * 4; - //[g_window_data.window updateSize]; + //[window_data->window updateSize]; #endif - [g_window_data.window setTitle:[NSString stringWithUTF8String:name]]; - [g_window_data.window setReleasedWhenClosed:NO]; - [g_window_data.window performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:nil waitUntilDone:YES]; - [g_window_data.window setAcceptsMouseMovedEvents:YES]; + [window_data_osx->window setTitle:[NSString stringWithUTF8String:title]]; + [window_data_osx->window setReleasedWhenClosed:NO]; + [window_data_osx->window performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:nil waitUntilDone:YES]; + [window_data_osx->window setAcceptsMouseMovedEvents:YES]; - [g_window_data.window center]; + [window_data_osx->window center]; - [NSApp activateIgnoringOtherApps:YES]; + [NSApp activateIgnoringOtherApps:YES]; #if defined(USE_METAL_API) - [NSApp finishLaunching]; + [NSApp finishLaunching]; #endif - if (g_keyboard_func == 0x0) { - mfb_keyboard_callback(keyboard_default); - } + mfb_keyboard_callback((struct Window *) window_data, keyboard_default); #if defined(USE_METAL_API) NSLog(@"Window created using Metal API"); @@ -259,41 +262,42 @@ int mfb_open_ex(const char* name, int width, int height, int flags) NSLog(@"Window created using Cocoa API"); #endif - [pool drain]; + [pool drain]; - return 1; + return (struct Window *) window_data; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -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() +static void destroy_window_data(SWindowData *window_data) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + if(window_data == 0x0) + return; - g_window_data.close = true; - if (g_window_data.window) - [g_window_data.window close]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window_data->specific; + if(window_data_osx != 0x0) { + OSXWindow *window = window_data_osx->window; + [window removeWindowData]; + [window performClose:nil]; - [pool drain]; + memset(window_data_osx, 0, sizeof(SWindowData_OSX)); + free(window_data_osx); + } + memset(window_data, 0, sizeof(SWindowData)); + free(window_data); + + [pool drain]; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static int update_events() +static void update_events(SWindowData *window_data) { - NSEvent* event; + NSEvent* event; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; do { event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; @@ -301,57 +305,67 @@ static int update_events() [NSApp sendEvent:event]; } } - while ((g_window_data.close == false) && event); + while ((window_data->close == false) && event); - [pool release]; - - if(g_window_data.close == true) - return -1; - - return 0; + [pool release]; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int mfb_update(void* buffer) +UpdateState mfb_update(struct Window *window, void* buffer) { - if(buffer == 0x0) - return -2; + if(window == 0x0) { + return STATE_INVALID_WINDOW; + } + + SWindowData *window_data = (SWindowData *) window; + if(window_data->close) { + destroy_window_data(window_data); + return STATE_EXIT; + } + + if(buffer == 0x0) { + return STATE_INVALID_BUFFER; + } #if defined(USE_METAL_API) - memcpy(g_window_data.draw_buffer, buffer, g_window_data.buffer_width * g_window_data.buffer_height * 4); + memcpy(window_data->draw_buffer, buffer, window_data->buffer_width * window_data->buffer_height * 4); #else - g_window_data.draw_buffer = buffer; + window_data->draw_buffer = buffer; #endif - int state = update_events(); - if(g_window_data.close == false) - [[g_window_data.window contentView] setNeedsDisplay:YES]; + update_events(window_data); + if(window_data->close == false) { + SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window_data->specific; + [[window_data_osx->window contentView] setNeedsDisplay:YES]; + } - return state; + return STATE_OK; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool mfb_set_viewport(unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) +bool mfb_set_viewport(struct Window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) { - if(offset_x + width > g_window_data.window_width) { + SWindowData *window_data = (SWindowData *) window; + + if(offset_x + width > window_data->window_width) { return false; } - if(offset_y + height > g_window_data.window_height) { + if(offset_y + height > 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; + window_data->dst_offset_x = offset_x; + window_data->dst_offset_y = offset_y; + window_data->dst_width = width; + 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; + float x1 = ((float) offset_x / window_data->window_width) * 2.0f - 1.0f; + float x2 = (((float) offset_x + width) / window_data->window_width) * 2.0f - 1.0f; + float y1 = ((float) offset_y / window_data->window_height) * 2.0f - 1.0f; + float y2 = (((float) offset_y + height) / window_data->window_height) * 2.0f - 1.0f; gVertices[0].x = x1; gVertices[0].y = y1; diff --git a/src/macosx/OSXWindow.h b/src/macosx/OSXWindow.h index 61a92e7..4dd0ba7 100644 --- a/src/macosx/OSXWindow.h +++ b/src/macosx/OSXWindow.h @@ -1,10 +1,18 @@ #import - +#include // @class OSXWindowFrameView; @interface OSXWindow : NSWindow { - NSView *childContentView; + NSView *childContentView; + @public SWindowData *window_data; } +- (id)initWithContentRect:(NSRect)contentRect + styleMask:(NSWindowStyleMask)windowStyle + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)deferCreation + windowData:(SWindowData *) windowData; + +- (void) removeWindowData; @end diff --git a/src/macosx/OSXWindow.m b/src/macosx/OSXWindow.m index 9b1a4ab..c618a58 100644 --- a/src/macosx/OSXWindow.m +++ b/src/macosx/OSXWindow.m @@ -1,22 +1,20 @@ #import "OSXWindow.h" #import "OSXWindowFrameView.h" -#include "OSXWindowData.h" +#include "WindowData_OSX.h" #include #include -extern SWindowData g_window_data; extern short int g_keycodes[512]; -bool gActive = false; - @implementation OSXWindow /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - (id)initWithContentRect:(NSRect)contentRect - styleMask:(NSWindowStyleMask)windowStyle - backing:(NSBackingStoreType)bufferingType - defer:(BOOL)deferCreation + styleMask:(NSWindowStyleMask)windowStyle + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)deferCreation + windowData:(SWindowData *) windowData { self = [super initWithContentRect:contentRect @@ -30,12 +28,24 @@ bool gActive = false; [self setBackgroundColor:[NSColor clearColor]]; self.delegate = self; + + self->window_data = windowData; + OSXWindowFrameView *view = (OSXWindowFrameView *) self->childContentView.superview; + view->window_data = windowData; } return self; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +- (void) removeWindowData { + self->window_data = 0x0; + OSXWindowFrameView *view = (OSXWindowFrameView *) self->childContentView.superview; + view->window_data = 0x0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + - (void)dealloc { [[NSNotificationCenter defaultCenter] @@ -62,7 +72,7 @@ bool gActive = false; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// --(void)flagsChanged:(NSEvent *)event +- (void)flagsChanged:(NSEvent *)event { const uint32_t flags = [event modifierFlags]; uint32_t mod_keys = 0, mod_keys_aux = 0; @@ -88,32 +98,31 @@ bool gActive = false; mod_keys |= KB_MOD_NUM_LOCK; } - if(mod_keys != g_window_data.mod_keys) { + if(mod_keys != 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; + mod_keys_aux = mod_keys ^ 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); + kCall(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); + kCall(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); + kCall(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); + kCall(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); + kCall(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); + kCall(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); + window_data->mod_keys = mod_keys; [super flagsChanged:event]; } @@ -123,7 +132,7 @@ bool gActive = false; - (void)keyDown:(NSEvent *)event { short int keyCode = keycodes[[event keyCode] & 0x1ff]; - kCall(g_keyboard_func, keyCode, g_window_data.mod_keys, true); + kCall(keyboard_func, keyCode, window_data->mod_keys, true); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -131,7 +140,7 @@ bool gActive = false; - (void)keyUp:(NSEvent *)event { short int keyCode = keycodes[[event keyCode] & 0x1ff]; - kCall(g_keyboard_func, keyCode, g_window_data.mod_keys, false); + kCall(keyboard_func, keyCode, window_data->mod_keys, false); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -155,7 +164,7 @@ bool gActive = false; if ((code & 0xff00) == 0xf700) continue; - kCall(g_char_input_func, code); + kCall(char_input_func, code); } } @@ -165,9 +174,10 @@ bool gActive = false; { kUnused(notification); - if(gActive == true) { - gActive = false; - kCall(g_active_func, false); + SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window_data->specific; + if(window_data_osx->active == true) { + window_data_osx->active = false; + kCall(active_func, false); } } @@ -217,18 +227,20 @@ bool gActive = false; - (void)windowDidBecomeKey:(NSNotification *)notification { kUnused(notification); - kCall(g_active_func, true); + kCall(active_func, true); } - (void)windowDidResignKey:(NSNotification *)notification { kUnused(notification); - kCall(g_active_func, false); + kCall(active_func, false); } - (void)windowWillClose:(NSNotification *)notification { kUnused(notification); - g_window_data.close = true; + if(window_data) { + window_data->close = true; + } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -258,7 +270,7 @@ bool gActive = false; - (void)willClose { - g_window_data.close = true; + window_data->close = true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -267,10 +279,10 @@ bool gActive = false; kUnused(notification); CGSize size = [self contentRectForFrameRect:[self frame]].size; - g_window_data.window_width = size.width; - g_window_data.window_height = size.height; + window_data->window_width = size.width; + window_data->window_height = size.height; - kCall(g_resize_func, size.width, size.height); + kCall(resize_func, size.width, size.height); } @end diff --git a/src/macosx/OSXWindowData.h b/src/macosx/OSXWindowData.h deleted file mode 100644 index b0ebc0b..0000000 --- a/src/macosx/OSXWindowData.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -@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; diff --git a/src/macosx/OSXWindowFrameView.h b/src/macosx/OSXWindowFrameView.h index 93e6173..d887b17 100644 --- a/src/macosx/OSXWindowFrameView.h +++ b/src/macosx/OSXWindowFrameView.h @@ -1,5 +1,7 @@ #import +#include "WindowData.h" + #if defined(USE_METAL_API) #import @@ -8,19 +10,19 @@ typedef struct Vertex { } Vertex; // Number of textures in flight (tripple buffered) -static const int MaxBuffersInFlight = 3; +enum { MaxBuffersInFlight = 3 }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @interface WindowViewController : NSViewController { - @public id m_texture_buffers[MaxBuffersInFlight]; - @public int m_current_buffer; - @public void* m_draw_buffer; - @public int m_width; - @public int m_height; - // Used for syncing with CPU/GPU - @public dispatch_semaphore_t m_semaphore; + @public id m_texture_buffers[MaxBuffersInFlight]; + @public int m_current_buffer; + @public void* m_draw_buffer; + @public int m_width; + @public int m_height; + // Used for syncing with CPU/GPU + @public dispatch_semaphore_t m_semaphore; } @end @@ -30,8 +32,9 @@ static const int MaxBuffersInFlight = 3; @interface OSXWindowFrameView : NSView { + @public SWindowData *window_data; #if defined(USE_METAL_API) - @private NSTrackingArea* trackingArea; + @private NSTrackingArea* trackingArea; #endif } diff --git a/src/macosx/OSXWindowFrameView.m b/src/macosx/OSXWindowFrameView.m index fc278ec..78c039c 100644 --- a/src/macosx/OSXWindowFrameView.m +++ b/src/macosx/OSXWindowFrameView.m @@ -1,31 +1,32 @@ #import "OSXWindowFrameView.h" #import "OSXWindow.h" -#include "OSXWindowData.h" +#include "WindowData_OSX.h" #include -extern SWindowData g_window_data; - #if defined(USE_METAL_API) #import -id g_metal_device; -id g_command_queue; -id g_library; -id g_pipeline_state; +extern id g_metal_device; +extern id g_library; extern Vertex gVertices[4]; @implementation WindowViewController --(void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size +- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { (void)view; (void)size; // resize } --(void)drawInMTKView:(nonnull MTKView *)view +- (void)drawInMTKView:(nonnull MTKView *)view { + OSXWindow *window = (OSXWindow *) view.window; + if(window->window_data == 0x0) { + return; + } + // Wait to ensure only MaxBuffersInFlight number of frames are getting proccessed // by any stage in the Metal pipeline (App, Metal, Drivers, GPU, etc) dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER); @@ -42,7 +43,8 @@ extern Vertex gVertices[4]; mipmapLevel:0 withBytes:m_draw_buffer bytesPerRow:bytesPerRow]; // Create a new command buffer for each render pass to the current drawable - id commandBuffer = [g_command_queue commandBuffer]; + SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window->window_data->specific; + id commandBuffer = [window_data_osx->metal.command_queue commandBuffer]; commandBuffer.label = @"minifb_command_buffer"; // Add completion hander which signals _inFlightSemaphore when Metal and the GPU has fully @@ -69,7 +71,9 @@ extern Vertex gVertices[4]; renderEncoder.label = @"minifb_command_encoder"; // Set render command encoder state - [renderEncoder setRenderPipelineState:g_pipeline_state]; + OSXWindow *window = (OSXWindow *) view.window; + SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window->window_data->specific; + [renderEncoder setRenderPipelineState:window_data_osx->metal.pipeline_state]; [renderEncoder setVertexBytes:gVertices length:sizeof(gVertices) @@ -103,7 +107,7 @@ extern Vertex gVertices[4]; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #if defined(USE_METAL_API) --(void)updateTrackingAreas +- (void)updateTrackingAreas { if(trackingArea != nil) { [self removeTrackingArea:trackingArea]; @@ -142,16 +146,20 @@ extern Vertex gVertices[4]; { (void)rect; - if (!g_window_data.window || !g_window_data.draw_buffer) + if(!window_data) + return; + + SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window_data->specific; + if (!window_data_osx || !window_data_osx->window || !window_data->draw_buffer) return; CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); - CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, g_window_data.draw_buffer, g_window_data.buffer_width * g_window_data.buffer_height * 4, NULL); + CGDataProviderRef provider = CGDataProviderCreateWithData(0x0, window_data->draw_buffer, window_data->buffer_width * window_data->buffer_height * 4, 0x0); - 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); + CGImageRef img = CGImageCreate(window_data->buffer_width, window_data->buffer_height, 8, 32, window_data->buffer_width * 4, space, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little, + provider, 0x0, false, kCGRenderingIntentDefault); const CGFloat components[] = {0.0f, 0.0f, 0.0f, 1.0f}; const CGColorRef black = CGColorCreate(space, components); @@ -159,12 +167,12 @@ extern Vertex gVertices[4]; CGColorSpaceRelease(space); CGDataProviderRelease(provider); - 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) { + if(window_data->dst_offset_x != 0 || window_data->dst_offset_y != 0 || window_data->dst_width != window_data->window_width || window_data->dst_height != window_data->window_height) { CGContextSetFillColorWithColor(context, black); - CGContextFillRect(context, CGRectMake(0, 0, g_window_data.window_width, g_window_data.window_height)); + CGContextFillRect(context, CGRectMake(0, 0, window_data->window_width, 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); + CGContextDrawImage(context, CGRectMake(window_data->dst_offset_x, window_data->dst_offset_y, window_data->dst_width, window_data->dst_height), img); CGImageRelease(img); } @@ -183,7 +191,7 @@ extern Vertex gVertices[4]; - (void)mouseDown:(NSEvent*)event { (void)event; - kCall(g_mouse_btn_func, MOUSE_BTN_1, g_window_data.mod_keys, true); + kCall(mouse_btn_func, MOUSE_BTN_1, window_data->mod_keys, true); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -191,7 +199,7 @@ extern Vertex gVertices[4]; - (void)mouseUp:(NSEvent*)event { (void)event; - kCall(g_mouse_btn_func, MOUSE_BTN_1, g_window_data.mod_keys, false); + kCall(mouse_btn_func, MOUSE_BTN_1, window_data->mod_keys, false); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -199,7 +207,7 @@ extern Vertex gVertices[4]; - (void)rightMouseDown:(NSEvent*)event { (void)event; - kCall(g_mouse_btn_func, MOUSE_BTN_2, g_window_data.mod_keys, true); + kCall(mouse_btn_func, MOUSE_BTN_2, window_data->mod_keys, true); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -207,7 +215,7 @@ extern Vertex gVertices[4]; - (void)rightMouseUp:(NSEvent*)event { (void)event; - kCall(g_mouse_btn_func, MOUSE_BTN_1, g_window_data.mod_keys, false); + kCall(mouse_btn_func, MOUSE_BTN_1, window_data->mod_keys, false); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -215,7 +223,7 @@ extern Vertex gVertices[4]; - (void)otherMouseDown:(NSEvent *)event { (void)event; - kCall(g_mouse_btn_func, [event buttonNumber], g_window_data.mod_keys, true); + kCall(mouse_btn_func, [event buttonNumber], window_data->mod_keys, true); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -223,14 +231,14 @@ extern Vertex gVertices[4]; - (void)otherMouseUp:(NSEvent *)event { (void)event; - kCall(g_mouse_btn_func, [event buttonNumber], g_window_data.mod_keys, false); + kCall(mouse_btn_func, [event buttonNumber], window_data->mod_keys, false); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - (void)scrollWheel:(NSEvent *)event { - kCall(g_mouse_wheel_func, g_window_data.mod_keys, [event deltaX], [event deltaY]); + kCall(mouse_wheel_func, window_data->mod_keys, [event deltaX], [event deltaY]); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -254,7 +262,7 @@ extern Vertex gVertices[4]; { NSPoint point = [event locationInWindow]; //NSPoint localPoint = [self convertPoint:point fromView:nil]; - kCall(g_mouse_move_func, point.x, point.y); + kCall(mouse_move_func, point.x, point.y); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/macosx/WindowData_OSX.h b/src/macosx/WindowData_OSX.h new file mode 100644 index 0000000..4948315 --- /dev/null +++ b/src/macosx/WindowData_OSX.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#if defined(USE_METAL_API) +#include +#endif + +@class OSXWindow; + +typedef struct { + OSXWindow *window; +#if defined(USE_METAL_API) + struct { + id command_queue; + id pipeline_state; + } metal; +#endif + bool active; +} SWindowData_OSX; diff --git a/src/wayland/WaylandMiniFB.c b/src/wayland/WaylandMiniFB.c index 73db7b5..c76560e 100644 --- a/src/wayland/WaylandMiniFB.c +++ b/src/wayland/WaylandMiniFB.c @@ -1,7 +1,8 @@ #include #include "MiniFB_internal.h" #include "MiniFB_enums.h" -#include "WaylandWindowData.h" +#include "WindowData.h" +#include "WindowData_Way.h" #include #include @@ -18,29 +19,48 @@ #include -SWindowData g_window_data = { 0 }; - static void -destroy(void) +destroy_window_data(SWindowData *window_data) { - if (! g_window_data.display) + if(window_data == 0x0) return; -#define KILL(NAME) \ - do \ - { \ - if (g_window_data.NAME) \ - wl_##NAME##_destroy(g_window_data.NAME); \ - } while (0); \ - g_window_data.NAME = 0x0; + SWindowData_Way *window_data_way = (SWindowData_Way *) window_data->specific; + if(window_data_way != 0x0) { + memset(window_data_way, 0, sizeof(SWindowData_Way)); + free(window_data_way); + } + memset(window_data, 0, sizeof(SWindowData)); + free(window_data); +} + +static void +destroy(SWindowData *window_data) +{ + if(window_data == 0x0) + return; + + SWindowData_Way *window_data_way = (SWindowData_Way *) window_data->specific; + if (window_data_way == 0x0 || window_data_way->display == 0x0) { + destroy_window_data(window_data); + return; + } + +#define KILL(NAME) \ + do \ + { \ + if (window_data_way->NAME) \ + wl_##NAME##_destroy(window_data_way->NAME); \ + } while (0); \ + window_data_way->NAME = 0x0; KILL(shell_surface); KILL(shell); KILL(surface); //KILL(buffer); - if(g_window_data.draw_buffer) { - wl_buffer_destroy(g_window_data.draw_buffer); - g_window_data.draw_buffer = 0x0; + if(window_data_way->draw_buffer) { + wl_buffer_destroy(window_data_way->draw_buffer); + window_data_way->draw_buffer = 0x0; } KILL(shm_pool); KILL(shm); @@ -49,8 +69,9 @@ destroy(void) KILL(seat); KILL(registry); #undef KILL - wl_display_disconnect(g_window_data.display); - memset(&g_window_data, 0, sizeof(SWindowData)); + wl_display_disconnect(window_data_way->display); + + destroy_window_data(window_data); } // This event provides a file descriptor to the client which can be memory-mapped @@ -75,12 +96,13 @@ keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int f 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); + + SWindowData *window_data = (SWindowData *) data; + kCall(active_func, true); } // The leave notification is sent before the enter notification for the new focus. @@ -89,11 +111,12 @@ keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct 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); + + SWindowData *window_data = (SWindowData *) data; + kCall(active_func, false); } // A key was pressed or released. The time argument is a timestamp with @@ -105,10 +128,11 @@ keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct 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); + + SWindowData *window_data = (SWindowData *) data; if(key < 512) { Key kb_key = (Key) keycodes[key]; bool is_pressed = (bool) (state == WL_KEYBOARD_KEY_STATE_PRESSED); @@ -117,37 +141,37 @@ keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t case KB_KEY_LEFT_SHIFT: case KB_KEY_RIGHT_SHIFT: if(is_pressed) - g_window_data.mod_keys |= KB_MOD_SHIFT; + window_data->mod_keys |= KB_MOD_SHIFT; else - g_window_data.mod_keys &= ~KB_MOD_SHIFT; + 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; + window_data->mod_keys |= KB_MOD_CONTROL; else - g_window_data.mod_keys &= ~KB_MOD_CONTROL; + 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; + window_data->mod_keys |= KB_MOD_ALT; else - g_window_data.mod_keys &= ~KB_MOD_ALT; + 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; + window_data->mod_keys |= KB_MOD_SUPER; else - g_window_data.mod_keys &= ~KB_MOD_SUPER; + window_data->mod_keys &= ~KB_MOD_SUPER; break; } - kCall(g_keyboard_func, kb_key, (KeyMod)g_window_data.mod_keys, is_pressed); + kCall(keyboard_func, kb_key, (KeyMod)window_data->mod_keys, is_pressed); } } @@ -189,7 +213,7 @@ static const struct wl_keyboard_listener keyboard_listener = { .leave = keyboard_leave, .key = keyboard_key, .modifiers = keyboard_modifiers, - .repeat_info = NULL, + .repeat_info = 0x0, }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -207,7 +231,6 @@ static const struct wl_keyboard_listener keyboard_listener = { 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) { - kUnused(data); //kUnused(pointer); //kUnused(serial); kUnused(surface); @@ -216,13 +239,16 @@ pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl struct wl_buffer *buffer; struct wl_cursor_image *image; - image = g_window_data.default_cursor->images[0]; + SWindowData *window_data = (SWindowData *) data; + SWindowData_Way *window_data_way = (SWindowData_Way *) window_data->specific; + + image = window_data_way->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); + wl_pointer_set_cursor(pointer, serial, window_data_way->cursor_surface, image->hotspot_x, image->hotspot_y); + wl_surface_attach(window_data_way->cursor_surface, buffer, 0, 0); + wl_surface_damage(window_data_way->cursor_surface, 0, 0, image->width, image->height); + wl_surface_commit(window_data_way->cursor_surface); //fprintf(stderr, "Pointer entered surface %p at %d %d\n", surface, sx, sy); } @@ -239,6 +265,7 @@ pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl kUnused(pointer); kUnused(serial); kUnused(surface); + //fprintf(stderr, "Pointer left surface %p\n", surface); } @@ -252,11 +279,12 @@ pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl 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); + SWindowData *window_data = (SWindowData *) data; + kCall(mouse_move_func, sx >> 24, sy >> 24); } // Mouse button click and release notifications. @@ -280,12 +308,13 @@ pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t 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); + SWindowData *window_data = (SWindowData *) data; + kCall(mouse_btn_func, button - BTN_MOUSE + 1, window_data->mod_keys, state == 1); } // Scroll and other axis notifications. @@ -311,16 +340,17 @@ pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t 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); + SWindowData *window_data = (SWindowData *) data; if(axis == 0) { - kCall(g_mouse_wheel_func, g_window_data.mod_keys, 0.0f, -(value / 256.0f)); + kCall(mouse_wheel_func, window_data->mod_keys, 0.0f, -(value / 256.0f)); } else if(axis == 1) { - kCall(g_mouse_wheel_func, g_window_data.mod_keys, -(value / 256.0f), 0.0f); + kCall(mouse_wheel_func, window_data->mod_keys, -(value / 256.0f), 0.0f); } } @@ -359,10 +389,10 @@ static const struct wl_pointer_listener pointer_listener = { .motion = pointer_motion, .button = pointer_button, .axis = pointer_axis, - .frame = NULL, - .axis_source = NULL, - .axis_stop = NULL, - .axis_discrete = NULL, + .frame = 0x0, + .axis_source = 0x0, + .axis_stop = 0x0, + .axis_discrete = 0x0, }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -371,26 +401,29 @@ static void seat_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps) { kUnused(data); - if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !g_window_data.keyboard) + + SWindowData *window_data = (SWindowData *) data; + SWindowData_Way *window_data_way = (SWindowData_Way *) window_data->specific; + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !window_data_way->keyboard) { - g_window_data.keyboard = wl_seat_get_keyboard(seat); - wl_keyboard_add_listener(g_window_data.keyboard, &keyboard_listener, NULL); + window_data_way->keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_add_listener(window_data_way->keyboard, &keyboard_listener, window_data); } - else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && g_window_data.keyboard) + else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && window_data_way->keyboard) { - wl_keyboard_destroy(g_window_data.keyboard); - g_window_data.keyboard = NULL; + wl_keyboard_destroy(window_data_way->keyboard); + window_data_way->keyboard = 0x0; } - if ((caps & WL_SEAT_CAPABILITY_POINTER) && !g_window_data.pointer) + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !window_data_way->pointer) { - g_window_data.pointer = wl_seat_get_pointer(seat); - wl_pointer_add_listener(g_window_data.pointer, &pointer_listener, NULL); + window_data_way->pointer = wl_seat_get_pointer(seat); + wl_pointer_add_listener(window_data_way->pointer, &pointer_listener, window_data); } - else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && g_window_data.pointer) + else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && window_data_way->pointer) { - wl_pointer_destroy(g_window_data.pointer); - g_window_data.pointer = NULL; + wl_pointer_destroy(window_data_way->pointer); + window_data_way->pointer = 0x0; } } @@ -403,7 +436,7 @@ seat_name(void *data, struct wl_seat *seat, const char *name) { static const struct wl_seat_listener seat_listener = { .capabilities = seat_capabilities, - .name = NULL, + .name = 0x0, }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -417,16 +450,18 @@ static const struct wl_seat_listener seat_listener = { static void shm_format(void *data, struct wl_shm *shm, uint32_t format) { - kUnused(data); kUnused(shm); - if (g_window_data.shm_format == -1u) + + SWindowData *window_data = (SWindowData *) data; + SWindowData_Way *window_data_way = (SWindowData_Way *) window_data->specific; + if (window_data_way->shm_format == -1u) { switch (format) { // We could do RGBA, but that would not be what is expected from minifb... // case WL_SHM_FORMAT_ARGB8888: case WL_SHM_FORMAT_XRGB8888: - g_window_data.shm_format = format; + window_data_way->shm_format = format; break; default: @@ -444,73 +479,112 @@ static const struct wl_shm_listener shm_listener = { static void registry_global(void *data, struct wl_registry *registry, uint32_t id, char const *iface, uint32_t version) { - kUnused(data); kUnused(version); + + SWindowData *window_data = (SWindowData *) data; + SWindowData_Way *window_data_way = (SWindowData_Way *) window_data->specific; if (strcmp(iface, "wl_compositor") == 0) { - g_window_data.compositor = (struct wl_compositor *) wl_registry_bind(registry, id, &wl_compositor_interface, 1); + window_data_way->compositor = (struct wl_compositor *) wl_registry_bind(registry, id, &wl_compositor_interface, 1); } else if (strcmp(iface, "wl_shm") == 0) { - g_window_data.shm = (struct wl_shm *) wl_registry_bind(registry, id, &wl_shm_interface, 1); - if (g_window_data.shm) { - 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"); + window_data_way->shm = (struct wl_shm *) wl_registry_bind(registry, id, &wl_shm_interface, 1); + if (window_data_way->shm) { + wl_shm_add_listener(window_data_way->shm, &shm_listener, window_data); + window_data_way->cursor_theme = wl_cursor_theme_load(0x0, 32, window_data_way->shm); + window_data_way->default_cursor = wl_cursor_theme_get_cursor(window_data_way->cursor_theme, "left_ptr"); } } else if (strcmp(iface, "wl_shell") == 0) { - g_window_data.shell = (struct wl_shell *) wl_registry_bind(registry, id, &wl_shell_interface, 1); + window_data_way->shell = (struct wl_shell *) wl_registry_bind(registry, id, &wl_shell_interface, 1); } else if (strcmp(iface, "wl_seat") == 0) { - g_window_data.seat = (struct wl_seat *) wl_registry_bind(registry, id, &wl_seat_interface, 1); - if (g_window_data.seat) + window_data_way->seat = (struct wl_seat *) wl_registry_bind(registry, id, &wl_seat_interface, 1); + if (window_data_way->seat) { - wl_seat_add_listener(g_window_data.seat, &seat_listener, NULL); + wl_seat_add_listener(window_data_way->seat, &seat_listener, window_data); } } } static const struct wl_registry_listener registry_listener = { .global = registry_global, - .global_remove = NULL, + .global_remove = 0x0, +}; + +static void +handle_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial) +{ + kUnused(data); + wl_shell_surface_pong(shell_surface, serial); +} + +static void +handle_configure(void *data, struct wl_shell_surface *shell_surface, uint32_t edges, int32_t width, int32_t height) +{ + kUnused(data); + kUnused(shell_surface); + kUnused(edges); + kUnused(width); + kUnused(height); +} + +static void +handle_popup_done(void *data, struct wl_shell_surface *shell_surface) +{ + kUnused(data); + kUnused(shell_surface); +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + handle_ping, + handle_configure, + handle_popup_done }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int -mfb_open_ex(const char* title, int width, int height, int flags) { +struct Window * +mfb_open_ex(const char *title, int width, int height, int flags) { // TODO: Not yet kUnused(flags); return mfb_open(title, width, height); } -int +struct Window * mfb_open(const char *title, int width, int height) { int fd = -1; - g_window_data.shm_format = -1u; + SWindowData *window_data = malloc(sizeof(SWindowData)); + memset(window_data, 0, sizeof(SWindowData)); - g_window_data.display = wl_display_connect(NULL); - if (!g_window_data.display) - return -1; - g_window_data.registry = wl_display_get_registry(g_window_data.display); - wl_registry_add_listener(g_window_data.registry, ®istry_listener, NULL); + SWindowData_Way *window_data_way = malloc(sizeof(SWindowData_Way)); + memset(window_data_way, 0, sizeof(SWindowData_Way)); + window_data->specific = window_data_way; + + window_data_way->shm_format = -1u; + + window_data_way->display = wl_display_connect(0x0); + if (!window_data_way->display) + return 0x0; + window_data_way->registry = wl_display_get_registry(window_data_way->display); + wl_registry_add_listener(window_data_way->registry, ®istry_listener, window_data); init_keycodes(); - if (wl_display_dispatch(g_window_data.display) == -1 || wl_display_roundtrip(g_window_data.display) == -1) + if (wl_display_dispatch(window_data_way->display) == -1 || wl_display_roundtrip(window_data_way->display) == -1) { - return -1; + return 0x0; } // did not get a format we want... meh - if (g_window_data.shm_format == -1u) + if (window_data_way->shm_format == -1u) goto out; - if (!g_window_data.compositor) + if (!window_data_way->compositor) goto out; char const *xdg_rt_dir = getenv("XDG_RUNTIME_DIR"); @@ -529,71 +603,60 @@ mfb_open(const char *title, int width, int height) if (ftruncate(fd, length) == -1) goto out; - g_window_data.shm_ptr = (uint32_t *) mmap(NULL, length, PROT_WRITE, MAP_SHARED, fd, 0); - if (g_window_data.shm_ptr == MAP_FAILED) + window_data_way->shm_ptr = (uint32_t *) mmap(0x0, length, PROT_WRITE, MAP_SHARED, fd, 0); + if (window_data_way->shm_ptr == MAP_FAILED) goto out; - 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.buffer_stride = width * sizeof(uint32_t); - 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; + window_data->window_width = width; + window_data->window_height = height; + window_data->buffer_width = width; + window_data->buffer_height = height; + window_data->buffer_stride = width * sizeof(uint32_t); + window_data->dst_offset_x = 0; + window_data->dst_offset_y = 0; + window_data->dst_width = width; + 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); + window_data_way->shm_pool = wl_shm_create_pool(window_data_way->shm, fd, length); + window_data->draw_buffer = wl_shm_pool_create_buffer(window_data_way->shm_pool, 0, + window_data->buffer_width, window_data->buffer_height, + window_data->buffer_stride, window_data_way->shm_format); close(fd); fd = -1; - g_window_data.surface = wl_compositor_create_surface(g_window_data.compositor); - if (!g_window_data.surface) + window_data_way->surface = wl_compositor_create_surface(window_data_way->compositor); + if (!window_data_way->surface) goto out; - g_window_data.cursor_surface = wl_compositor_create_surface(g_window_data.compositor); + window_data_way->cursor_surface = wl_compositor_create_surface(window_data_way->compositor); // There should always be a shell, right? - if (g_window_data.shell) + if (window_data_way->shell) { - g_window_data.shell_surface = wl_shell_get_shell_surface(g_window_data.shell, g_window_data.surface); - if (!g_window_data.shell_surface) + window_data_way->shell_surface = wl_shell_get_shell_surface(window_data_way->shell, window_data_way->surface); + if (!window_data_way->shell_surface) goto out; - wl_shell_surface_set_title(g_window_data.shell_surface, title); - wl_shell_surface_set_toplevel(g_window_data.shell_surface); + wl_shell_surface_set_title(window_data_way->shell_surface, title); + wl_shell_surface_add_listener(window_data_way->shell_surface, &shell_surface_listener, 0x0); + wl_shell_surface_set_toplevel(window_data_way->shell_surface); } - 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(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(g_window_data.surface); + wl_surface_attach(window_data_way->surface, window_data->draw_buffer, window_data->dst_offset_x, window_data->dst_offset_y); + wl_surface_damage(window_data_way->surface, window_data->dst_offset_x, window_data->dst_offset_y, window_data->dst_width, window_data->dst_height); + wl_surface_commit(window_data_way->surface); - if (g_keyboard_func == 0x0) { - mfb_keyboard_callback(keyboard_default); - } + mfb_keyboard_callback((struct Window *) window_data, keyboard_default); printf("Window created using Wayland API\n"); - return 1; + return (struct Window *) window_data; out: close(fd); - destroy(); - return 0; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -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; + destroy(window_data); + return 0x0; } // done event @@ -606,6 +669,7 @@ frame_done(void *data, struct wl_callback *callback, uint32_t cookie) { kUnused(cookie); wl_callback_destroy(callback); + *(uint32_t *)data = 1; } @@ -613,53 +677,50 @@ static const struct wl_callback_listener frame_listener = { .done = frame_done, }; -int -mfb_update(void *buffer) +UpdateState +mfb_update(struct Window *window, void *buffer) { uint32_t done = 0; - if (!g_window_data.display || wl_display_get_error(g_window_data.display) != 0) - return -1; + if(window == 0x0) { + return STATE_INVALID_WINDOW; + } - if (g_window_data.close == true) - return -1; + SWindowData *window_data = (SWindowData *) window; + if(window_data->close) { + destroy(window_data); + return STATE_EXIT; + } + + if(buffer == 0x0) { + return STATE_INVALID_BUFFER; + } + + SWindowData_Way *window_data_way = (SWindowData_Way *) window_data->specific; + if (!window_data_way->display || wl_display_get_error(window_data_way->display) != 0) + return STATE_INTERNAL_ERROR; // update shm buffer - memcpy(g_window_data.shm_ptr, buffer, g_window_data.buffer_stride * g_window_data.buffer_height); + memcpy(window_data_way->shm_ptr, buffer, window_data->buffer_stride * window_data->buffer_height); - 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(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_attach(window_data_way->surface, window_data->draw_buffer, window_data->dst_offset_x, window_data->dst_offset_y); + wl_surface_damage(window_data_way->surface, window_data->dst_offset_x, window_data->dst_offset_y, window_data->dst_width, window_data->dst_height); + struct wl_callback *frame_callback = wl_surface_frame(window_data_way->surface); + if (!frame_callback) { + return STATE_INTERNAL_ERROR; + } + wl_callback_add_listener(frame_callback, &frame_listener, &done); + wl_surface_commit(window_data_way->surface); - struct wl_callback *frame = wl_surface_frame(g_window_data.surface); - if (!frame) - return -1; - - wl_callback_add_listener(frame, &frame_listener, &done); - - wl_surface_commit(g_window_data.surface); - - while (!done && g_window_data.close == false) { - if (wl_display_dispatch(g_window_data.display) == -1 || wl_display_roundtrip(g_window_data.display) == -1) + while (!done && window_data->close == false) { + if (wl_display_dispatch(window_data_way->display) == -1 || wl_display_roundtrip(window_data_way->display) == -1) { - wl_callback_destroy(frame); - return -1; + wl_callback_destroy(frame_callback); + return STATE_INTERNAL_ERROR; } } - if(g_window_data.close == true) { - destroy(); - } - //static int counter = 0; - //printf("update!: %d\n", counter++); - - return 0; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void -mfb_close(void) { - g_window_data.close = true; + return STATE_OK; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -795,20 +856,22 @@ init_keycodes(void) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool -mfb_set_viewport(unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) { +mfb_set_viewport(struct Window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) { - if(offset_x + width > g_window_data.window_width) { + SWindowData *window_data = (SWindowData *) window; + + if(offset_x + width > window_data->window_width) { return false; } - if(offset_y + height > g_window_data.window_height) { + if(offset_y + height > 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; + // window_data->dst_offset_x = offset_x; + // window_data->dst_offset_y = offset_y; + // window_data->dst_width = width; + // window_data->dst_height = height; return false; } diff --git a/src/wayland/WaylandWindowData.h b/src/wayland/WindowData_Way.h similarity index 98% rename from src/wayland/WaylandWindowData.h rename to src/wayland/WindowData_Way.h index bfd4c7d..888c4d6 100644 --- a/src/wayland/WaylandWindowData.h +++ b/src/wayland/WindowData_Way.h @@ -54,4 +54,4 @@ typedef struct uint32_t mod_keys; bool close; -} SWindowData; +} SWindowData_Way; diff --git a/src/windows/WinMiniFB.c b/src/windows/WinMiniFB.c index 1a2059a..84ed0cb 100644 --- a/src/windows/WinMiniFB.c +++ b/src/windows/WinMiniFB.c @@ -1,49 +1,55 @@ #include #include -#include "WinWindowData.h" +#include +#include "WindowData_Win.h" #include /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SWindowData g_window_data = { 0 }; - -long s_window_style = WS_POPUP | WS_SYSMENU | WS_CAPTION; +long s_window_style = WS_POPUP | WS_SYSMENU | WS_CAPTION; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// uint32_t translate_mod(); Key translate_key(unsigned int wParam, unsigned long lParam); +void destroy_window_data(SWindowData *window_data); LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT res = 0; + SWindowData *window_data = (SWindowData *) GetWindowLongPtr(hWnd, GWL_USERDATA); + SWindowData_Win *window_data_win = 0x0; + if(window_data != 0x0) { + window_data_win = (SWindowData_Win *) window_data->specific; + } + switch (message) { case WM_PAINT: { - if (g_window_data.draw_buffer) + if (window_data && window_data->draw_buffer && window_data_win) { - if (g_window_data.dst_offset_x > 0) { - 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); - } + //if(window_data->dst_offset_x > 0) { + // BitBlt(window_data_win->hdc, 0, window_data->dst_offset_y, window_data->dst_offset_x, window_data->dst_height, 0, 0, 0, BLACKNESS); + //} + //if(window_data->dst_offset_y > 0) { + // BitBlt(window_data_win->hdc, 0, 0, window_data->window_width, window_data->dst_offset_y, 0, 0, 0, BLACKNESS); + //} + //uint32_t offsetY = window_data->dst_offset_y + window_data->dst_height; + //if(offsetY < window_data->window_height) { + // BitBlt(window_data_win->hdc, 0, offsetY, window_data->window_width, window_data->window_height - offsetY, 0, 0, 0, BLACKNESS); + //} + //uint32_t offsetX = window_data->dst_offset_x + window_data->dst_width; + //if(offsetX < window_data->window_width) { + // BitBlt(window_data_win->hdc, offsetX, window_data->dst_offset_y, window_data->window_width - offsetX, 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); + StretchDIBits(window_data_win->hdc, window_data->dst_offset_x, window_data->dst_offset_y, window_data->dst_width, window_data->dst_height, 0, 0, window_data->buffer_width, window_data->buffer_height, window_data->draw_buffer, + window_data_win->bitmapInfo, DIB_RGB_COLORS, SRCCOPY); - ValidateRect(hWnd, NULL); + ValidateRect(hWnd, 0x0); } break; @@ -52,7 +58,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_DESTROY: case WM_CLOSE: { - g_window_data.close = true; + if(window_data) { + window_data->close = true; + } break; } @@ -61,14 +69,16 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 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(window_data) { + Key kb_key = translate_key((unsigned int)wParam, (unsigned long)lParam); + int is_pressed = !((lParam >> 31) & 1); + window_data->mod_keys = translate_mod(); - if (kb_key == KB_KEY_UNKNOWN) - return FALSE; + if (kb_key == KB_KEY_UNKNOWN) + return FALSE; - kCall(g_keyboard_func, kb_key, g_window_data.mod_keys, is_pressed); + kCall(keyboard_func, kb_key, window_data->mod_keys, is_pressed); + } break; } @@ -77,13 +87,15 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 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; - } + if(window_data) { + 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); + kCall(char_input_func, wParam); + } break; } @@ -100,10 +112,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: { - MouseButton button = MOUSE_BTN_0; - g_window_data.mod_keys = translate_mod(); - int is_pressed = 0; - switch (message) { + if(window_data) { + MouseButton button = MOUSE_BTN_0; + window_data->mod_keys = translate_mod(); + int is_pressed = 0; + switch(message) { case WM_LBUTTONDOWN: is_pressed = 1; case WM_LBUTTONUP: @@ -122,59 +135,73 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) default: button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? MOUSE_BTN_5 : MOUSE_BTN_6); - if (message == WM_XBUTTONDOWN) { + if(message == WM_XBUTTONDOWN) { is_pressed = 1; } + } + kCall(mouse_btn_func, button, window_data->mod_keys, is_pressed); } - 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); + if(window_data) { + kCall(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); + if(window_data) { + kCall(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); + if(window_data) { + if(window_data_win->mouse_inside == false) { + window_data_win->mouse_inside = true; + TRACKMOUSEEVENT tme; + ZeroMemory(&tme, sizeof(tme)); + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + TrackMouseEvent(&tme); + } + kCall(mouse_move_func, ((int)(short)LOWORD(lParam)), ((int)(short)HIWORD(lParam))); } - kCall(g_mouse_move_func, ((int)(short)LOWORD(lParam)), ((int)(short)HIWORD(lParam))); break; case WM_MOUSELEAVE: - g_window_data.s_mouse_inside = false; + if(window_data) { + window_data_win->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); + if(window_data) { + window_data->dst_offset_x = 0; + window_data->dst_offset_y = 0; + window_data->dst_width = LOWORD(lParam); + window_data->dst_height = HIWORD(lParam); + window_data->window_width = window_data->dst_width; + window_data->window_height = window_data->dst_height; + BitBlt(window_data_win->hdc, 0, 0, window_data->window_width, window_data->window_height, 0, 0, 0, BLACKNESS); + kCall(resize_func, window_data->dst_width, window_data->dst_height); + } break; - } case WM_SETFOCUS: - kCall(g_active_func, true); + if(window_data) { + kCall(active_func, true); + } break; case WM_KILLFOCUS: - kCall(g_active_func, false); + if(window_data) { + kCall(active_func, false); + } break; default: @@ -188,14 +215,22 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int mfb_open_ex(const char* title, int width, int height, int flags) { +struct Window *mfb_open_ex(const char *title, int width, int height, int flags) { RECT rect = { 0 }; int x, y; init_keycodes(); - g_window_data.buffer_width = width; - g_window_data.buffer_height = height; + SWindowData *window_data = malloc(sizeof(SWindowData)); + memset(window_data, 0, sizeof(SWindowData)); + + SWindowData_Win *window_data_win = malloc(sizeof(SWindowData_Win)); + memset(window_data_win, 0, sizeof(SWindowData_Win)); + window_data->specific = window_data_win; + + window_data->buffer_width = width; + window_data->buffer_height = height; + window_data->buffer_stride = width * 4; s_window_style = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME; if (flags & WF_FULLSCREEN) { @@ -261,114 +296,117 @@ int mfb_open_ex(const char* title, int width, int height, int flags) { y = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom + rect.top) / 2; } - 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); + window_data_win->wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW; + window_data_win->wc.lpfnWndProc = WndProc; + window_data_win->wc.hCursor = LoadCursor(0, IDC_ARROW); + window_data_win->wc.lpszClassName = title; + RegisterClass(&window_data_win->wc); - if (g_window_data.dst_width == 0) - g_window_data.dst_width = width; + if (window_data->dst_width == 0) + window_data->dst_width = width; - if (g_window_data.dst_height == 0) - g_window_data.dst_height = height; + if (window_data->dst_height == 0) + window_data->dst_height = height; - g_window_data.window_width = rect.right; - g_window_data.window_height = rect.bottom; + window_data->window_width = rect.right; + window_data->window_height = rect.bottom; - g_window_data.window = CreateWindowEx( + window_data_win->window = CreateWindowEx( 0, title, title, s_window_style, x, y, - g_window_data.window_width, g_window_data.window_height, + window_data->window_width, window_data->window_height, 0, 0, 0, 0); - if (!g_window_data.window) - return 0; + if (!window_data_win->window) + return 0x0; + + SetWindowLongPtr(window_data_win->window, GWLP_USERDATA, (LONG_PTR) window_data); if (flags & WF_ALWAYS_ON_TOP) - SetWindowPos(g_window_data.window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + SetWindowPos(window_data_win->window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - ShowWindow(g_window_data.window, SW_NORMAL); + ShowWindow(window_data_win->window, SW_NORMAL); - 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; + window_data_win->bitmapInfo = (BITMAPINFO *) calloc(1, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 3); + window_data_win->bitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + window_data_win->bitmapInfo->bmiHeader.biPlanes = 1; + window_data_win->bitmapInfo->bmiHeader.biBitCount = 32; + window_data_win->bitmapInfo->bmiHeader.biCompression = BI_BITFIELDS; + window_data_win->bitmapInfo->bmiHeader.biWidth = window_data->buffer_width; + window_data_win->bitmapInfo->bmiHeader.biHeight = -(LONG)window_data->buffer_height; + window_data_win->bitmapInfo->bmiColors[0].rgbRed = 0xff; + window_data_win->bitmapInfo->bmiColors[1].rgbGreen = 0xff; + window_data_win->bitmapInfo->bmiColors[2].rgbBlue = 0xff; - g_window_data.s_hdc = GetDC(g_window_data.window); + window_data_win->hdc = GetDC(window_data_win->window); - if (g_keyboard_func == 0x0) { - mfb_keyboard_callback(keyboard_default); - } + mfb_keyboard_callback((struct Window *) window_data, keyboard_default); - return 1; + return (struct Window *) window_data; } -int mfb_open(const char* title, int width, int height) { +struct Window *mfb_open(const char *title, int width, int height) { return mfb_open_ex(title, width, height, 0); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int mfb_update(void* buffer) +UpdateState mfb_update(struct Window *window, void* buffer) { MSG msg; - if (buffer == 0x0) - return -2; + if(window == 0x0) { + return STATE_INVALID_WINDOW; + } - if (g_window_data.close == true) - return -1; + SWindowData *window_data = (SWindowData *)window; + if(window_data->close) { + destroy_window_data(window_data); + return STATE_EXIT; + } - g_window_data.draw_buffer = buffer; + if(buffer == 0x0) { + return STATE_INVALID_BUFFER; + } - InvalidateRect(g_window_data.window, NULL, TRUE); - SendMessage(g_window_data.window, WM_PAINT, 0, 0); + window_data->draw_buffer = buffer; - while (g_window_data.close == false && PeekMessage(&msg, g_window_data.window, 0, 0, PM_REMOVE)) + SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific; + InvalidateRect(window_data_win->window, 0x0, TRUE); + SendMessage(window_data_win->window, WM_PAINT, 0, 0); + + while (window_data->close == false && PeekMessage(&msg, window_data_win->window, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } - return 0; + return STATE_OK; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void mfb_close() -{ - g_window_data.draw_buffer = 0x0; - if (g_window_data.s_bitmapInfo != 0x0) { - free(g_window_data.s_bitmapInfo); +void destroy_window_data(SWindowData *window_data) { + if(window_data == 0x0) + return; + + SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific; + + window_data->draw_buffer = 0x0; + if(window_data_win->bitmapInfo != 0x0) { + free(window_data_win->bitmapInfo); } - 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); + if(window_data_win->window != 0 && window_data_win->hdc != 0) { + ReleaseDC(window_data_win->window, window_data_win->hdc); + DestroyWindow(window_data_win->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; + window_data_win->window = 0; + window_data_win->hdc = 0; + window_data_win->bitmapInfo = 0x0; + window_data->close = true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -536,7 +574,7 @@ Key translate_key(unsigned int wParam, unsigned long lParam) { return KB_KEY_RIGHT_CONTROL; time = GetMessageTime(); - if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE)) + if (PeekMessageW(&next, 0x0, 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; @@ -552,20 +590,22 @@ Key translate_key(unsigned int wParam, unsigned long lParam) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool mfb_set_viewport(unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) +bool mfb_set_viewport(struct Window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) { - if(offset_x + width > g_window_data.window_width) { + SWindowData *window_data = (SWindowData *) window; + + if(offset_x + width > window_data->window_width) { return false; } - if(offset_y + height > g_window_data.window_height) { + if(offset_y + height > window_data->window_height) { return false; } - g_window_data.dst_offset_x = offset_x; - g_window_data.dst_offset_y = offset_y; + window_data->dst_offset_x = offset_x; + window_data->dst_offset_y = offset_y; - g_window_data.dst_width = width; - g_window_data.dst_height = height; + window_data->dst_width = width; + window_data->dst_height = height; return true; } diff --git a/src/windows/WinWindowData.h b/src/windows/WinWindowData.h deleted file mode 100644 index 57d5a8f..0000000 --- a/src/windows/WinWindowData.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include -#define WIN32_LEAN_AND_MEAN -#include - - -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; diff --git a/src/windows/WindowData_Win.h b/src/windows/WindowData_Win.h new file mode 100644 index 0000000..fb8b8c1 --- /dev/null +++ b/src/windows/WindowData_Win.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#define WIN32_LEAN_AND_MEAN +#include + + +typedef struct { + HWND window; + WNDCLASS wc; + HDC hdc; + BITMAPINFO *bitmapInfo; + bool mouse_inside; +} SWindowData_Win; diff --git a/src/x11/X11WindowData.h b/src/x11/WindowData_X11.h similarity index 51% rename from src/x11/X11WindowData.h rename to src/x11/WindowData_X11.h index e09ac30..fb3490f 100644 --- a/src/x11/X11WindowData.h +++ b/src/x11/WindowData_X11.h @@ -7,20 +7,6 @@ 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; @@ -31,4 +17,4 @@ typedef struct { XImage *image_scaler; uint32_t image_scaler_width; uint32_t image_scaler_height; -} SWindowData; +} SWindowData_X11; diff --git a/src/x11/X11MiniFB.c b/src/x11/X11MiniFB.c index 0c0b413..26e7f61 100644 --- a/src/x11/X11MiniFB.c +++ b/src/x11/X11MiniFB.c @@ -4,41 +4,50 @@ #include #include #include +#include #include +#include #include #include -#include "X11WindowData.h" +#include "WindowData.h" +#include "WindowData_X11.h" /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -SWindowData g_window_data = { 0 }; - 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); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int mfb_open_ex(const char* title, int width, int height, int flags) { +struct Window * +mfb_open_ex(const char *title, int width, int height, int flags) { int depth, i, formatCount, convDepth = -1; XPixmapFormatValues* formats; XSetWindowAttributes windowAttributes; XSizeHints sizeHints; Visual* visual; - g_window_data.display = XOpenDisplay(0); - if (!g_window_data.display) - return -1; + SWindowData *window_data = (SWindowData *) malloc(sizeof(SWindowData)); + memset(window_data, 0, sizeof(SWindowData)); + + SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) malloc(sizeof(SWindowData_X11)); + memset(window_data_x11, 0, sizeof(SWindowData_X11)); + window_data->specific = window_data_x11; + + window_data_x11->display = XOpenDisplay(0); + if (!window_data_x11->display) + return 0x0; - init_keycodes(); + init_keycodes(window_data_x11); - g_window_data.screen = DefaultScreen(g_window_data.display); + window_data_x11->screen = DefaultScreen(window_data_x11->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); + visual = DefaultVisual(window_data_x11->display, window_data_x11->screen); + formats = XListPixmapFormats(window_data_x11->display, &formatCount); + depth = DefaultDepth(window_data_x11->display, window_data_x11->screen); - Window defaultRootWindow = DefaultRootWindow(g_window_data.display); + Window defaultRootWindow = DefaultRootWindow(window_data_x11->display); for (i = 0; i < formatCount; ++i) { @@ -54,28 +63,29 @@ int mfb_open_ex(const char* title, int width, int height, int flags) { // We only support 32-bit right now if (convDepth != 32) { - XCloseDisplay(g_window_data.display); - return -1; + XCloseDisplay(window_data_x11->display); + return 0x0; } - int screenWidth = DisplayWidth(g_window_data.display, g_window_data.screen); - int screenHeight = DisplayHeight(g_window_data.display, g_window_data.screen); + int screenWidth = DisplayWidth(window_data_x11->display, window_data_x11->screen); + int screenHeight = DisplayHeight(window_data_x11->display, window_data_x11->screen); - windowAttributes.border_pixel = BlackPixel(g_window_data.display, g_window_data.screen); - windowAttributes.background_pixel = BlackPixel(g_window_data.display, g_window_data.screen); + windowAttributes.border_pixel = BlackPixel(window_data_x11->display, window_data_x11->screen); + windowAttributes.background_pixel = BlackPixel(window_data_x11->display, window_data_x11->screen); windowAttributes.backing_store = NotUseful; int posX, posY; int windowWidth, windowHeight; - 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; + window_data->window_width = width; + window_data->window_height = height; + window_data->buffer_width = width; + window_data->buffer_height = height; + window_data->buffer_stride = width * 4; + window_data->dst_offset_x = 0; + window_data->dst_offset_y = 0; + window_data->dst_width = width; + window_data->dst_height = height; if (flags & WF_FULLSCREEN_DESKTOP) { posX = 0; @@ -90,8 +100,8 @@ int mfb_open_ex(const char* title, int width, int height, int flags) { windowHeight = height; } - g_window_data.window = XCreateWindow( - g_window_data.display, + window_data_x11->window = XCreateWindow( + window_data_x11->display, defaultRootWindow, posX, posY, windowWidth, windowHeight, @@ -101,10 +111,10 @@ int mfb_open_ex(const char* title, int width, int height, int flags) { visual, CWBackPixel | CWBorderPixel | CWBackingStore, &windowAttributes); - if (!g_window_data.window) - return 0; + if (!window_data_x11->window) + return 0x0; - XSelectInput(g_window_data.display, g_window_data.window, + XSelectInput(window_data_x11->display, window_data_x11->window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | ExposureMask @@ -112,7 +122,7 @@ int mfb_open_ex(const char* title, int width, int height, int flags) { | EnterWindowMask | LeaveWindowMask ); - XStoreName(g_window_data.display, g_window_data.window, title); + XStoreName(window_data_x11->display, window_data_x11->window, title); if (flags & WF_BORDERLESS) { struct StyleHints { @@ -128,18 +138,18 @@ int mfb_open_ex(const char* title, int width, int height, int flags) { .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); + Atom sh_p = XInternAtom(window_data_x11->display, "_MOTIF_WM_HINTS", True); + XChangeProperty(window_data_x11->display, window_data_x11->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); + Atom sa_p = XInternAtom(window_data_x11->display, "_NET_WM_STATE_ABOVE", False); + XChangeProperty(window_data_x11->display, window_data_x11->window, XInternAtom(window_data_x11->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); + Atom sf_p = XInternAtom(window_data_x11->display, "_NET_WM_STATE_FULLSCREEN", True); + XChangeProperty(window_data_x11->display, window_data_x11->window, XInternAtom(window_data_x11->display, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char*)&sf_p, 1); } sizeHints.flags = PPosition | PMinSize | PMaxSize; @@ -156,25 +166,24 @@ int mfb_open_ex(const char* title, int width, int height, int flags) { sizeHints.max_height = height; } - XSetWMNormalHints(g_window_data.display, g_window_data.window, &sizeHints); - XClearWindow(g_window_data.display, g_window_data.window); - XMapRaised(g_window_data.display, g_window_data.window); - XFlush(g_window_data.display); + XSetWMNormalHints(window_data_x11->display, window_data_x11->window, &sizeHints); + XClearWindow(window_data_x11->display, window_data_x11->window); + XMapRaised(window_data_x11->display, window_data_x11->window); + XFlush(window_data_x11->display); - g_window_data.gc = DefaultGC(g_window_data.display, g_window_data.screen); + window_data_x11->gc = DefaultGC(window_data_x11->display, window_data_x11->screen); - g_window_data.image = XCreateImage(g_window_data.display, CopyFromParent, depth, ZPixmap, 0, NULL, width, height, 32, width * 4); + window_data_x11->image = XCreateImage(window_data_x11->display, CopyFromParent, depth, ZPixmap, 0, 0x0, width, height, 32, width * 4); - if (g_keyboard_func == 0x0) { - mfb_keyboard_callback(keyboard_default); - } + mfb_keyboard_callback((struct Window *) window_data, keyboard_default); printf("Window created using X11 API\n"); - return 1; + return (struct Window *) window_data; } -int mfb_open(const char* title, int width, int height) +struct Window * +mfb_open(const char *title, int width, int height) { return mfb_open_ex(title, width, height, 0); } @@ -185,74 +194,75 @@ 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 void processEvents(SWindowData *window_data) { - XEvent event; + XEvent event; + SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific; - while ((g_window_data.close == false) && XPending(g_window_data.display)) { - XNextEvent(g_window_data.display, &event); + while ((window_data->close == false) && XPending(window_data_x11->display)) { + XNextEvent(window_data_x11->display, &event); switch (event.type) { case KeyPress: case KeyRelease: { - int kb_key = translate_key(event.xkey.keycode); + Key kb_key = (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); + window_data->mod_keys = translate_mod_ex(kb_key, event.xkey.state, is_pressed); - kCall(g_keyboard_func, kb_key, g_window_data.mod_keys, is_pressed); + kCall(keyboard_func, kb_key, (KeyMod) window_data->mod_keys, is_pressed); } break; case ButtonPress: case ButtonRelease: { - MouseButton button = event.xbutton.button; + MouseButton button = (MouseButton) event.xbutton.button; int is_pressed = (event.type == ButtonPress); - g_window_data.mod_keys = translate_mod(event.xkey.state); + 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); + kCall(mouse_btn_func, button, (KeyMod) window_data->mod_keys, is_pressed); break; case Button4: - kCall(g_mouse_wheel_func, g_window_data.mod_keys, 0.0f, 1.0f); + kCall(mouse_wheel_func, (KeyMod) 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); + kCall(mouse_wheel_func, (KeyMod) window_data->mod_keys, 0.0f, -1.0f); break; case 6: - kCall(g_mouse_wheel_func, g_window_data.mod_keys, 1.0f, 0.0f); + kCall(mouse_wheel_func, (KeyMod) 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); + kCall(mouse_wheel_func, (KeyMod) window_data->mod_keys, -1.0f, 0.0f); break; default: - kCall(g_mouse_btn_func, button - 4, g_window_data.mod_keys, is_pressed); + kCall(mouse_btn_func, (MouseButton) (button - 4), (KeyMod) window_data->mod_keys, is_pressed); break; } } break; case MotionNotify: - kCall(g_mouse_move_func, event.xmotion.x, event.xmotion.y); + kCall(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; + window_data->window_width = event.xconfigure.width; + window_data->window_height = event.xconfigure.height; + window_data->dst_offset_x = 0; + window_data->dst_offset_y = 0; + window_data->dst_width = window_data->window_width; + window_data->dst_height = 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); + XClearWindow(window_data_x11->display, window_data_x11->window); + kCall(resize_func, window_data->window_width, window_data->window_height); } break; @@ -261,83 +271,95 @@ static int processEvents() break; case FocusIn: - kCall(g_active_func, true); + kCall(active_func, true); break; case FocusOut: - kCall(g_active_func, false); + kCall(active_func, false); break; case DestroyNotify: - return -1; + window_data->close = true; + return; break; } } - - if(g_window_data.close == true) - return -1; - - return 0; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int mfb_update(void* buffer) +void destroy(SWindowData *window_data); + +UpdateState mfb_update(struct Window *window, void* buffer) { - if (buffer == 0x0) { - return -2; + if(window == 0x0) { + return STATE_INVALID_WINDOW; } - if (g_window_data.buffer_width != g_window_data.dst_width || g_window_data.buffer_height != g_window_data.dst_height) { - 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); + SWindowData *window_data = (SWindowData *) window; + if(window_data->close) { + destroy(window_data); + return STATE_EXIT; + } + + if(buffer == 0x0) { + return STATE_INVALID_BUFFER; + } + + SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific; + + if (window_data->buffer_width != window_data->dst_width || window_data->buffer_height != window_data->dst_height) { + if(window_data_x11->image_scaler_width != window_data->dst_width || window_data_x11->image_scaler_height != window_data->dst_height) { + if(window_data_x11->image_scaler != 0x0) { + window_data_x11->image_scaler->data = 0x0; + XDestroyImage(window_data_x11->image_scaler); } - if(g_window_data.image_buffer != 0x0) { - free(g_window_data.image_buffer); - g_window_data.image_buffer = 0x0; + if(window_data_x11->image_buffer != 0x0) { + free(window_data_x11->image_buffer); + window_data_x11->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); + int depth = DefaultDepth(window_data_x11->display, window_data_x11->screen); + window_data_x11->image_buffer = malloc(window_data->dst_width * window_data->dst_height * 4); + window_data_x11->image_scaler_width = window_data->dst_width; + window_data_x11->image_scaler_height = window_data->dst_height; + window_data_x11->image_scaler = XCreateImage(window_data_x11->display, CopyFromParent, depth, ZPixmap, 0, 0x0, window_data_x11->image_scaler_width, window_data_x11->image_scaler_height, 32, window_data_x11->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); + if(window_data_x11->image_scaler != 0x0) { + stretch_image((uint32_t *) buffer, 0, 0, window_data->buffer_width, window_data->buffer_height, window_data->buffer_width, (uint32_t *) window_data_x11->image_buffer, 0, 0, window_data->dst_width, window_data->dst_height, window_data->dst_width); + window_data_x11->image_scaler->data = (char *) window_data_x11->image_buffer; + XPutImage(window_data_x11->display, window_data_x11->window, window_data_x11->gc, window_data_x11->image_scaler, 0, 0, window_data->dst_offset_x, window_data->dst_offset_y, window_data->dst_width, 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); + window_data_x11->image->data = (char *) buffer; + XPutImage(window_data_x11->display, window_data_x11->window, window_data_x11->gc, window_data_x11->image, 0, 0, window_data->dst_offset_x, window_data->dst_offset_y, window_data->dst_width, window_data->dst_height); } - XFlush(g_window_data.display); - - if (processEvents() < 0) - return -1; - - return 0; + XFlush(window_data_x11->display); + processEvents(window_data); + + return STATE_OK; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void mfb_close(void) +void destroy(SWindowData *window_data) { - if(g_window_data.image != 0x0) { - g_window_data.image->data = 0x0; - XDestroyImage(g_window_data.image); - 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; + if(window_data != 0x0) { + if(window_data->specific != 0x0) { + SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific; + if(window_data_x11->image != 0x0) { + window_data_x11->image->data = 0x0; + XDestroyImage(window_data_x11->image); + XDestroyWindow(window_data_x11->display, window_data_x11->window); + XCloseDisplay(window_data_x11->display); + } + memset(window_data_x11, 0, sizeof(SWindowData_X11)); + free(window_data_x11); + } + memset(window_data, 0, sizeof(SWindowData)); + free(window_data); + } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -507,7 +529,7 @@ static int translateKeyCodeA(int keySym) { return KB_KEY_UNKNOWN; } -void init_keycodes() { +void init_keycodes(SWindowData_X11 *window_data_x11) { size_t i; int keySym; @@ -518,10 +540,10 @@ void init_keycodes() { // 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); + keySym = XkbKeycodeToKeysym(window_data_x11->display, i, 0, 1); keycodes[i] = translateKeyCodeB(keySym); if(keycodes[i] == KB_KEY_UNKNOWN) { - keySym = XkbKeycodeToKeysym(g_window_data.display, i, 0, 0); + keySym = XkbKeycodeToKeysym(window_data_x11->display, i, 0, 0); keycodes[i] = translateKeyCodeA(keySym); } } @@ -604,29 +626,20 @@ int translate_mod_ex(int key, int state, int is_pressed) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -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) +bool mfb_set_viewport(struct Window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) { - if(offset_x + width > g_window_data.window_width) { + SWindowData *window_data = (SWindowData *) window; + + if(offset_x + width > window_data->window_width) { return false; } - if(offset_y + height > g_window_data.window_height) { + if(offset_y + height > 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; + window_data->dst_offset_x = offset_x; + window_data->dst_offset_y = offset_y; + window_data->dst_width = width; + window_data->dst_height = height; return true; } diff --git a/tests/noise.c b/tests/noise.c index 0fe3b53..51cf936 100644 --- a/tests/noise.c +++ b/tests/noise.c @@ -4,63 +4,140 @@ #define kUnused(var) (void) var; -#define WIDTH 800 -#define HEIGHT 600 -static unsigned int s_buffer[WIDTH * HEIGHT]; +#define WIDTH_A 800 +#define HEIGHT_A 600 +static unsigned int g_buffer1[WIDTH_A * HEIGHT_A]; + +#define WIDTH_B 240 +#define HEIGHT_B 120 +static unsigned int g_buffer2[WIDTH_B * HEIGHT_B]; //------------------------------------- // C interface //------------------------------------- -void active(void *user_data, bool isActive) { - kUnused(user_data); - fprintf(stdout, "active: %d\n", isActive); +void active(struct Window *window, bool isActive) { + int id = 0; + if(window) { + id = *(int *) mfb_get_user_data(window); + } + fprintf(stdout, "active %d: %d\n", id, isActive); } -void resize(void *user_data, int width, int height) { +void resize(struct Window *window, int width, int height) { uint32_t x = 0; uint32_t y = 0; + int id = 0; + if(window) { + id = *(int *) mfb_get_user_data(window); + } - kUnused(user_data); - fprintf(stdout, "resize: %d, %d\n", width, height); - if(width > WIDTH) { - x = (width - WIDTH) >> 1; - width = WIDTH; + fprintf(stdout, "resize %d: %d, %d\n", id, width, height); + if(width > WIDTH_A) { + x = (width - WIDTH_A) >> 1; + width = WIDTH_A; } - if(height > HEIGHT) { - y = (height - HEIGHT) >> 1; - height = HEIGHT; + if(height > HEIGHT_A) { + y = (height - HEIGHT_A) >> 1; + height = HEIGHT_A; } - mfb_set_viewport(x, y, width, height); + mfb_set_viewport(window, 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); +void keyboard(struct Window *window, Key key, KeyMod mod, bool isPressed) { + int id = 0; + if(window) { + id = *(int *) mfb_get_user_data(window); + } + fprintf(stdout, "keyboard %d: key: %s (pressed: %d) [KeyMod: %x]\n", id, mfb_get_key_name(key), isPressed, mod); if(key == KB_KEY_ESCAPE) { - mfb_close(); + mfb_close(window); } } -void char_input(void *user_data, unsigned int charCode) { - kUnused(user_data); - fprintf(stdout, "charCode: %d\n", charCode); +void char_input(struct Window *window, unsigned int charCode) { + int id = 0; + if(window) { + id = *(int *) mfb_get_user_data(window); + } + fprintf(stdout, "charCode %d: %d\n", id, 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_btn(struct Window *window, MouseButton button, KeyMod mod, bool isPressed) { + int id = 0; + if(window) { + id = *(int *) mfb_get_user_data(window); + } + fprintf(stdout, "mouse_btn %d: button: %d (pressed: %d) [KeyMod: %x]\n", id, button, isPressed, mod); } -void mouse_move(void *user_data, int x, int y) { - kUnused(user_data); +void mouse_move(struct Window *window, int x, int y) { + kUnused(window); + kUnused(x); + kUnused(y); + // int id = 0; + // if(window) { + // id = *(int *) mfb_get_user_data(window); + // } + //fprintf(stdout, "mouse_move %d: %d, %d\n", id, x, y); +} + +void mouse_scroll(struct Window *window, KeyMod mod, float deltaX, float deltaY) { + int id = 0; + if(window) { + id = *(int *) mfb_get_user_data(window); + } + fprintf(stdout, "mouse_scroll %d: x: %f, y: %f [KeyMod: %x]\n", id, deltaX, deltaY, mod); +} + +//-- +void active2(struct Window *window, bool isActive) { + kUnused(window); + fprintf(stdout, "active 2: %d\n", isActive); +} + +void resize2(struct Window *window, int width, int height) { + uint32_t x = 0; + uint32_t y = 0; + + fprintf(stdout, "resize 2: %d, %d\n", width, height); + if(width > WIDTH_A) { + x = (width - WIDTH_A) >> 1; + width = WIDTH_A; + } + if(height > HEIGHT_A) { + y = (height - HEIGHT_A) >> 1; + height = HEIGHT_A; + } + mfb_set_viewport(window, x, y, width, height); +} + +void keyboard2(struct Window *window, Key key, KeyMod mod, bool isPressed) { + fprintf(stdout, "keyboard 2: key: %s (pressed: %d) [KeyMod: %x]\n", mfb_get_key_name(key), isPressed, mod); + if(key == KB_KEY_ESCAPE) { + mfb_close(window); + } +} + +void char_input2(struct Window *window, unsigned int charCode) { + kUnused(window); + fprintf(stdout, "charCode 2: %d\n", charCode); +} + +void mouse_btn2(struct Window *window, MouseButton button, KeyMod mod, bool isPressed) { + kUnused(window); + fprintf(stdout, "mouse_btn 2: button: %d (pressed: %d) [KeyMod: %x]\n", button, isPressed, mod); +} + +void mouse_move2(struct Window *window, int x, int y) { + kUnused(window); 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); +void mouse_scroll2(struct Window *window, KeyMod mod, float deltaX, float deltaY) { + kUnused(window); + fprintf(stdout, "mouse_scroll 2: x: %f, y: %f [KeyMod: %x]\n", deltaX, deltaY, mod); } //------------------------------------- @@ -70,32 +147,77 @@ void mouse_scroll(void *user_data, KeyMod mod, float deltaX, float deltaY) { class Events { public: - void active(void *user_data, bool isActive) { - ::active(user_data, isActive); + void active(struct Window *window, bool isActive) { + printf("\nEvents 1 - "); + ::active(window, isActive); } - void resize(void *user_data, int width, int height) { - ::resize(user_data, width, height); + void resize(struct Window *window, int width, int height) { + printf("Events 1 - "); + ::resize(window, width, height); } - void keyboard(void *user_data, Key key, KeyMod mod, bool isPressed) { - ::keyboard(user_data, key, mod, isPressed); + void keyboard(struct Window *window, Key key, KeyMod mod, bool isPressed) { + printf("Events 1 - "); + ::keyboard(window, key, mod, isPressed); } - void char_input(void *user_data, unsigned int charCode) { - ::char_input(user_data, charCode); + void char_input(struct Window *window, unsigned int charCode) { + printf("Events 1 - "); + ::char_input(window, charCode); } - void mouse_btn(void *user_data, MouseButton button, KeyMod mod, bool isPressed) { - ::mouse_btn(user_data, button, mod, isPressed); + void mouse_btn(struct Window *window, MouseButton button, KeyMod mod, bool isPressed) { + printf("Events 1 - "); + ::mouse_btn(window, button, mod, isPressed); } - void mouse_move(void *user_data, int x, int y) { - ::mouse_move(user_data, x, y); + void mouse_move(struct Window *window, int x, int y) { + //printf("Events 1 - "); + ::mouse_move(window, x, y); } - void mouse_scroll(void *user_data, KeyMod mod, float deltaX, float deltaY) { - ::mouse_scroll(user_data, mod, deltaX, deltaY); + void mouse_scroll(struct Window *window, KeyMod mod, float deltaX, float deltaY) { + printf("Events 1 - "); + ::mouse_scroll(window, mod, deltaX, deltaY); + } +}; + +class Events2 { +public: + void active(struct Window *window, bool isActive) { + printf("\nEvents 2 - "); + ::active(window, isActive); + } + + void resize(struct Window *window, int width, int height) { + printf("Events 2 - "); + ::resize(window, width, height); + } + + void keyboard(struct Window *window, Key key, KeyMod mod, bool isPressed) { + printf("Events 2 - "); + ::keyboard(window, key, mod, isPressed); + } + + void char_input(struct Window *window, unsigned int charCode) { + printf("Events 2 - "); + ::char_input(window, charCode); + } + + void mouse_btn(struct Window *window, MouseButton button, KeyMod mod, bool isPressed) { + printf("Events 2 - "); + ::mouse_btn(window, button, mod, isPressed); + } + + void mouse_move(struct Window *window, int x, int y) { + //printf("Events 2 - "); + ::mouse_move(window, x, y); + } + + void mouse_scroll(struct Window *window, KeyMod mod, float deltaX, float deltaY) { + printf("Events 2 - "); + ::mouse_scroll(window, mod, deltaX, deltaY); } }; @@ -106,39 +228,75 @@ public: int main() { int noise, carry, seed = 0xbeef; + int id1 = 1, id2 = 2; + + struct Window *window1 = mfb_open_ex("Noise Test", WIDTH_A, HEIGHT_A, WF_RESIZABLE); + if (!window1) + return 0; + + mfb_set_user_data(window1, &id1); #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); + mfb_active_callback(window1, &e, &Events::active); + mfb_resize_callback(window1, &e, &Events::resize); + mfb_keyboard_callback(window1, &e, &Events::keyboard); + mfb_char_input_callback(window1, &e, &Events::char_input); + mfb_mouse_button_callback(window1, &e, &Events::mouse_btn); + mfb_mouse_move_callback(window1, &e, &Events::mouse_move); + mfb_mouse_scroll_callback(window1, &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); + mfb_active_callback(window1, active); + mfb_resize_callback(window1, resize); + mfb_keyboard_callback(window1, keyboard); + mfb_char_input_callback(window1, char_input); + mfb_mouse_button_callback(window1, mouse_btn); + mfb_mouse_move_callback(window1, mouse_move); + mfb_mouse_scroll_callback(window1, mouse_scroll); #endif - if (!mfb_open_ex("Noise Test", WIDTH, HEIGHT, WF_RESIZABLE)) + struct Window *window2 = mfb_open_ex("Noise Test", WIDTH_B, HEIGHT_B, WF_RESIZABLE); + if (!window2) return 0; + mfb_set_user_data(window2, &id2); + +#if defined(__cplusplus) + + Events2 e2; + + mfb_active_callback(window2, &e2, &Events2::active); + mfb_resize_callback(window2, &e2, &Events::resize); + mfb_keyboard_callback(window2, &e2, &Events::keyboard); + mfb_char_input_callback(window2, &e2, &Events::char_input); + mfb_mouse_button_callback(window2, &e2, &Events::mouse_btn); + mfb_mouse_move_callback(window2, &e2, &Events::mouse_move); + mfb_mouse_scroll_callback(window2, &e2, &Events::mouse_scroll); + +#else + + mfb_active_callback(window2, active2); + mfb_resize_callback(window2, resize2); + mfb_keyboard_callback(window2, keyboard2); + mfb_char_input_callback(window2, char_input2); + mfb_mouse_button_callback(window2, mouse_btn2); + mfb_mouse_move_callback(window2, mouse_move2); + mfb_mouse_scroll_callback(window2, mouse_scroll2); + +#endif + mfb_keyboard_callback(window2, 0x0); + for (;;) { - int i, state; + int i; + UpdateState state1, state2; - for (i = 0; i < WIDTH * HEIGHT; ++i) + for (i = 0; i < WIDTH_A * HEIGHT_A; ++i) { noise = seed; noise >>= 3; @@ -148,16 +306,36 @@ int main() seed >>= 1; seed |= (carry << 30); noise &= 0xFF; - s_buffer[i] = MFB_RGB(noise, noise, noise); + g_buffer1[i] = MFB_RGB(noise, noise, noise); } - state = mfb_update(s_buffer); + for (i = 0; i < WIDTH_B * HEIGHT_B; ++i) + { + noise = seed; + noise >>= 3; + noise ^= seed; + carry = noise & 1; + noise >>= 1; + seed >>= 1; + seed |= (carry << 30); + noise &= 0xFF; + g_buffer2[i] = MFB_RGB(noise, (~noise) & 0xff, 255 - noise); + } - if (state < 0) + state1 = mfb_update(window1, g_buffer1); + state2 = mfb_update(window2, g_buffer2); + if (state1 != STATE_OK) { + window1 = 0x0; + } + if (state2 != STATE_OK) { + window2 = 0x0; + } + if (state1 != STATE_OK && state2 != STATE_OK) { break; + } } - mfb_close(); + mfb_close(window1); return 0; }