From 0257a60419c26d06bbf6cee47582a5c209f2b7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Aragon=C3=A9s?= <9335325+Darky-Lucera@users.noreply.github.com> Date: Sat, 14 Dec 2019 11:20:59 +0100 Subject: [PATCH] mfb_update_events (#27) * update documentation * Fix typo * Added some examples * changed window names * Minor fix * Added mfb_update_events to all platforms. Checked on Windows, X11 and Wayland --- CMakeLists.txt | 2 +- include/MiniFB.h | 9 +++- src/macosx/MacMiniFB.m | 23 +++++++++ src/wayland/WaylandMiniFB.c | 29 +++++++++++- src/windows/WinMiniFB.c | 93 +++++++++++++++++++++++-------------- src/x11/X11MiniFB.c | 74 +++++++++++++++++------------ tests/input_events.c | 34 ++++++++------ 7 files changed, 181 insertions(+), 83 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06ba472..7087aab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ 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_C_FLAGS "-g -Wall -Wextra -pedantic -Wno-switch -Wno-unused-function -Wno-implicit-fallthrough") set (CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11") set (CMAKE_OBJC_FLAGS "${CMAKE_C_FLAGS}") set (CMAKE_OBJCXX_FLAGS "${CMAKE_CXX_FLAGS}") diff --git a/include/MiniFB.h b/include/MiniFB.h index 6c4ea1d..7139a7b 100644 --- a/include/MiniFB.h +++ b/include/MiniFB.h @@ -17,10 +17,15 @@ extern "C" { struct Window * mfb_open(const char *title, unsigned width, unsigned height); struct Window * mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags); -// Update the display. Input buffer is assumed to be a 32-bit buffer of the size given in the open call -// Will return a negative status if something went wrong or the user want to exit. +// Update the display +// Input buffer is assumed to be a 32-bit buffer of the size given in the open call +// Will return a negative status if something went wrong or the user want to exit +// Also updates the window events UpdateState mfb_update(struct Window *window, void *buffer); +// Only updates the window events +UpdateState mfb_update_events(struct Window *window); + // Close the window void mfb_close(struct Window *window); diff --git a/src/macosx/MacMiniFB.m b/src/macosx/MacMiniFB.m index 23ef909..3f3c334 100644 --- a/src/macosx/MacMiniFB.m +++ b/src/macosx/MacMiniFB.m @@ -345,6 +345,29 @@ UpdateState mfb_update(struct Window *window, void *buffer) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +UpdateState mfb_update_events(struct Window *window) +{ + if(window == 0x0) { + return STATE_INVALID_WINDOW; + } + + SWindowData *window_data = (SWindowData *) window; + if(window_data->close) { + destroy_window_data(window_data); + return STATE_EXIT; + } + + 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_OK; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool mfb_set_viewport(struct Window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) { SWindowData *window_data = (SWindowData *) window; diff --git a/src/wayland/WaylandMiniFB.c b/src/wayland/WaylandMiniFB.c index 2723bdc..fe8e758 100644 --- a/src/wayland/WaylandMiniFB.c +++ b/src/wayland/WaylandMiniFB.c @@ -718,8 +718,7 @@ mfb_update(struct Window *window, void *buffer) wl_surface_commit(window_data_way->surface); while (!done && window_data->close == false) { - if (wl_display_dispatch(window_data_way->display) == -1 || wl_display_roundtrip(window_data_way->display) == -1) - { + if (wl_display_dispatch(window_data_way->display) == -1 || wl_display_roundtrip(window_data_way->display) == -1) { wl_callback_destroy(frame_callback); return STATE_INTERNAL_ERROR; } @@ -730,6 +729,32 @@ mfb_update(struct Window *window, void *buffer) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +UpdateState +mfb_update_events(struct Window *window) +{ + if(window == 0x0) { + return STATE_INVALID_WINDOW; + } + + SWindowData *window_data = (SWindowData *) window; + if(window_data->close) { + destroy(window_data); + return STATE_EXIT; + } + + 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; + + if (wl_display_dispatch(window_data_way->display) == -1 || wl_display_roundtrip(window_data_way->display) == -1) { + return STATE_INTERNAL_ERROR; + } + + return STATE_OK; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + extern short int g_keycodes[512]; void diff --git a/src/windows/WinMiniFB.c b/src/windows/WinMiniFB.c index e69702d..e725f3f 100644 --- a/src/windows/WinMiniFB.c +++ b/src/windows/WinMiniFB.c @@ -15,13 +15,12 @@ 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 CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT res = 0; SWindowData *window_data = (SWindowData *) GetWindowLongPtr(hWnd, GWLP_USERDATA); SWindowData_Win *window_data_win = 0x0; - if(window_data != 0x0) { + if (window_data != 0x0) { window_data_win = (SWindowData_Win *) window_data->specific; } @@ -31,18 +30,18 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { if (window_data && window_data->draw_buffer && window_data_win) { - //if(window_data->dst_offset_x > 0) { + //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) { + //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) { + //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) { + //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); //} @@ -58,7 +57,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_DESTROY: case WM_CLOSE: { - if(window_data) { + if (window_data) { window_data->close = true; } break; @@ -69,7 +68,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_KEYUP: case WM_SYSKEYUP: { - if(window_data) { + if (window_data) { Key key_code = translate_key((unsigned int)wParam, (unsigned long)lParam); int is_pressed = !((lParam >> 31) & 1); window_data->mod_keys = translate_mod(); @@ -88,14 +87,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_UNICHAR: { - if(window_data) { - if(message == WM_UNICHAR && wParam == UNICODE_NOCHAR) { + 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(char_input_func, wParam); + kCall(char_input_func, (unsigned int) wParam); } break; } @@ -113,7 +112,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: { - if(window_data) { + if (window_data) { MouseButton button = MOUSE_BTN_0; window_data->mod_keys = translate_mod(); int is_pressed = 0; @@ -136,7 +135,7 @@ 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; } } @@ -146,7 +145,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } case WM_MOUSEWHEEL: - if(window_data) { + if (window_data) { kCall(mouse_wheel_func, translate_mod(), 0.0f, (SHORT)HIWORD(wParam) / (float)WHEEL_DELTA); } break; @@ -154,14 +153,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 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 - if(window_data) { + if (window_data) { kCall(mouse_wheel_func, translate_mod(), -((SHORT)HIWORD(wParam) / (float)WHEEL_DELTA), 0.0f); } break; case WM_MOUSEMOVE: - if(window_data) { - if(window_data_win->mouse_inside == false) { + if (window_data) { + if (window_data_win->mouse_inside == false) { window_data_win->mouse_inside = true; TRACKMOUSEEVENT tme; ZeroMemory(&tme, sizeof(tme)); @@ -177,13 +176,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_MOUSELEAVE: - if(window_data) { + if (window_data) { window_data_win->mouse_inside = false; } break; case WM_SIZE: - if(window_data) { + if (window_data) { window_data->dst_offset_x = 0; window_data->dst_offset_y = 0; window_data->dst_width = LOWORD(lParam); @@ -196,14 +195,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_SETFOCUS: - if(window_data) { + if (window_data) { window_data->is_active = true; kCall(active_func, true); } break; case WM_KILLFOCUS: - if(window_data) { + if (window_data) { window_data->is_active = false; kCall(active_func, false); } @@ -358,21 +357,20 @@ struct Window *mfb_open(const char *title, unsigned width, unsigned height) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -UpdateState mfb_update(struct Window *window, void *buffer) -{ +UpdateState mfb_update(struct Window *window, void *buffer) { MSG msg; - if(window == 0x0) { + if (window == 0x0) { return STATE_INVALID_WINDOW; } SWindowData *window_data = (SWindowData *)window; - if(window_data->close) { + if (window_data->close) { destroy_window_data(window_data); return STATE_EXIT; } - if(buffer == 0x0) { + if (buffer == 0x0) { return STATE_INVALID_BUFFER; } @@ -382,8 +380,31 @@ UpdateState mfb_update(struct Window *window, void *buffer) 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)) - { + while (window_data->close == false && PeekMessage(&msg, window_data_win->window, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return STATE_OK; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +UpdateState mfb_update_events(struct Window *window) { + MSG msg; + + if (window == 0x0) { + return STATE_INVALID_WINDOW; + } + + SWindowData *window_data = (SWindowData *)window; + if (window_data->close) { + destroy_window_data(window_data); + return STATE_EXIT; + } + + SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific; + while (window_data->close == false && PeekMessage(&msg, window_data_win->window, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } @@ -394,16 +415,17 @@ UpdateState mfb_update(struct Window *window, void *buffer) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void destroy_window_data(SWindowData *window_data) { - if(window_data == 0x0) + 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) { + if (window_data_win->bitmapInfo != 0x0) { free(window_data_win->bitmapInfo); } - if(window_data_win->window != 0 && window_data_win->hdc != 0) { + + 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); } @@ -595,14 +617,13 @@ Key translate_key(unsigned int wParam, unsigned long lParam) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool mfb_set_viewport(struct Window *window, 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) { SWindowData *window_data = (SWindowData *) window; - if(offset_x + width > window_data->window_width) { + if (offset_x + width > window_data->window_width) { return false; } - if(offset_y + height > window_data->window_height) { + if (offset_y + height > window_data->window_height) { return false; } diff --git a/src/x11/X11MiniFB.c b/src/x11/X11MiniFB.c index 442faa5..42d966e 100644 --- a/src/x11/X11MiniFB.c +++ b/src/x11/X11MiniFB.c @@ -157,7 +157,7 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) sizeHints.y = 0; sizeHints.min_width = width; sizeHints.min_height = height; - if(flags & WF_RESIZABLE) { + if (flags & WF_RESIZABLE) { sizeHints.max_width = screenWidth; sizeHints.max_height = screenHeight; } @@ -183,8 +183,7 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) } struct Window * -mfb_open(const char *title, unsigned width, unsigned height) -{ +mfb_open(const char *title, unsigned width, unsigned height) { return mfb_open_ex(title, width, height, 0); } @@ -194,8 +193,7 @@ int translate_key(int scancode); int translate_mod(int state); int translate_mod_ex(int key, int state, int is_pressed); -static void processEvents(SWindowData *window_data) -{ +static void processEvents(SWindowData *window_data) { XEvent event; SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific; @@ -295,31 +293,30 @@ static void processEvents(SWindowData *window_data) void destroy(SWindowData *window_data); -UpdateState mfb_update(struct Window *window, void *buffer) -{ - if(window == 0x0) { +UpdateState mfb_update(struct Window *window, void *buffer) { + if (window == 0x0) { return STATE_INVALID_WINDOW; } SWindowData *window_data = (SWindowData *) window; - if(window_data->close) { + if (window_data->close) { destroy(window_data); return STATE_EXIT; } - if(buffer == 0x0) { + 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) { + 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(window_data_x11->image_buffer != 0x0) { + if (window_data_x11->image_buffer != 0x0) { free(window_data_x11->image_buffer); window_data_x11->image_buffer = 0x0; } @@ -331,7 +328,7 @@ UpdateState mfb_update(struct Window *window, void *buffer) } } - if(window_data_x11->image_scaler != 0x0) { + 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); @@ -348,12 +345,31 @@ UpdateState mfb_update(struct Window *window, void *buffer) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void destroy(SWindowData *window_data) -{ - if(window_data != 0x0) { - if(window_data->specific != 0x0) { +UpdateState mfb_update_events(struct Window *window) { + if (window == 0x0) { + return STATE_INVALID_WINDOW; + } + + SWindowData *window_data = (SWindowData *) window; + if (window_data->close) { + destroy(window_data); + return STATE_EXIT; + } + + SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific; + XFlush(window_data_x11->display); + processEvents(window_data); + + return STATE_OK; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void destroy(SWindowData *window_data) { + 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) { + 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); @@ -543,11 +559,11 @@ void init_keycodes(SWindowData_X11 *window_data_x11) { g_keycodes[i] = KB_KEY_UNKNOWN; // Valid key code range is [8,255], according to the Xlib manual - for(int i=8; i<=255; ++i) { + for (int i=8; i<=255; ++i) { // Try secondary keysym, for numeric keypad keys keySym = XkbKeycodeToKeysym(window_data_x11->display, i, 0, 1); g_keycodes[i] = translateKeyCodeB(keySym); - if(g_keycodes[i] == KB_KEY_UNKNOWN) { + if (g_keycodes[i] == KB_KEY_UNKNOWN) { keySym = XkbKeycodeToKeysym(window_data_x11->display, i, 0, 0); g_keycodes[i] = translateKeyCodeA(keySym); } @@ -595,7 +611,7 @@ int translate_mod_ex(int key, int state, int is_pressed) { { case KB_KEY_LEFT_SHIFT: case KB_KEY_RIGHT_SHIFT: - if(is_pressed) + if (is_pressed) mod_keys |= KB_MOD_SHIFT; else mod_keys &= ~KB_MOD_SHIFT; @@ -603,7 +619,7 @@ int translate_mod_ex(int key, int state, int is_pressed) { case KB_KEY_LEFT_CONTROL: case KB_KEY_RIGHT_CONTROL: - if(is_pressed) + if (is_pressed) mod_keys |= KB_MOD_CONTROL; else mod_keys &= ~KB_MOD_CONTROL; @@ -611,7 +627,7 @@ int translate_mod_ex(int key, int state, int is_pressed) { case KB_KEY_LEFT_ALT: case KB_KEY_RIGHT_ALT: - if(is_pressed) + if (is_pressed) mod_keys |= KB_MOD_ALT; else mod_keys &= ~KB_MOD_ALT; @@ -619,7 +635,7 @@ int translate_mod_ex(int key, int state, int is_pressed) { case KB_KEY_LEFT_SUPER: case KB_KEY_RIGHT_SUPER: - if(is_pressed) + if (is_pressed) mod_keys |= KB_MOD_SUPER; else mod_keys &= ~KB_MOD_SUPER; @@ -631,14 +647,13 @@ int translate_mod_ex(int key, int state, int is_pressed) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool mfb_set_viewport(struct Window *window, 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) { SWindowData *window_data = (SWindowData *) window; - if(offset_x + width > window_data->window_width) { + if (offset_x + width > window_data->window_width) { return false; } - if(offset_y + height > window_data->window_height) { + if (offset_y + height > window_data->window_height) { return false; } @@ -646,5 +661,6 @@ bool mfb_set_viewport(struct Window *window, unsigned offset_x, unsigned offset_ window_data->dst_offset_y = offset_y; window_data->dst_width = width; window_data->dst_height = height; + return true; } diff --git a/tests/input_events.c b/tests/input_events.c index 08b9531..b99fa2f 100644 --- a/tests/input_events.c +++ b/tests/input_events.c @@ -2,11 +2,12 @@ #include #include -#define kUnused(var) (void) var; +#define kUnused(var) (void) var #define WIDTH 800 #define HEIGHT 600 static unsigned int g_buffer[WIDTH * HEIGHT]; +static bool g_active = true; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -16,6 +17,7 @@ void active(struct Window *window, bool isActive) { window_title = (const char *) mfb_get_user_data(window); } fprintf(stdout, "%s > active: %d\n", window_title, isActive); + g_active = isActive; } void resize(struct Window *window, int width, int height) { @@ -109,20 +111,26 @@ int main() int i; UpdateState state; - for (i = 0; i < WIDTH * HEIGHT; ++i) + if(g_active) { - noise = seed; - noise >>= 3; - noise ^= seed; - carry = noise & 1; - noise >>= 1; - seed >>= 1; - seed |= (carry << 30); - noise &= 0xFF; - g_buffer[i] = MFB_RGB(noise, noise, noise); - } + for (i = 0; i < WIDTH * HEIGHT; ++i) + { + noise = seed; + noise >>= 3; + noise ^= seed; + carry = noise & 1; + noise >>= 1; + seed >>= 1; + seed |= (carry << 30); + noise &= 0xFF; + g_buffer[i] = MFB_RGB(noise, noise, noise); + } - state = mfb_update(window, g_buffer); + state = mfb_update(window, g_buffer); + } + else { + state = mfb_update_events(window); + } if (state != STATE_OK) { window = 0x0; break;