Add timers and ability to set a target fps for the application (#36)
* working on windows * minor fix * working on macosx * Oops! I reversed resolution and frequency on macos * working on X11 * working on wayland * update the readme * format the readme Co-authored-by: Carlos Aragones <>
This commit is contained in:
@ -6,6 +6,13 @@
|
||||
#define kCall(func, ...) if(window_data && window_data->func) window_data->func((struct mfb_window *) window_data, __VA_ARGS__);
|
||||
#define kUnused(var) (void) var;
|
||||
|
||||
typedef struct mfb_timer {
|
||||
int64_t start_time;
|
||||
int64_t delta_counter;
|
||||
uint64_t time;
|
||||
} mfb_timer;
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
32
src/MiniFB_linux.c
Normal file
32
src/MiniFB_linux.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <time.h>
|
||||
#include <MiniFB.h>
|
||||
|
||||
extern double g_timer_frequency;
|
||||
extern double g_timer_resolution;
|
||||
|
||||
#define kClock CLOCK_MONOTONIC
|
||||
//#define kClock CLOCK_REALTIME
|
||||
|
||||
uint64_t
|
||||
mfb_timer_tick() {
|
||||
struct timespec time;
|
||||
|
||||
if (clock_gettime(kClock, &time) != 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return time.tv_sec * 1e+9 + time.tv_nsec;
|
||||
}
|
||||
|
||||
void
|
||||
mfb_timer_init() {
|
||||
struct timespec res;
|
||||
|
||||
if (clock_getres(kClock, &res) != 0) {
|
||||
g_timer_frequency = 1e+9;
|
||||
}
|
||||
else {
|
||||
g_timer_frequency = res.tv_sec + res.tv_nsec * 1e+9;
|
||||
}
|
||||
g_timer_resolution = 1.0 / g_timer_frequency;
|
||||
}
|
102
src/MiniFB_timer.c
Normal file
102
src/MiniFB_timer.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include "MiniFB.h"
|
||||
#include "MiniFB_internal.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
//-------------------------------------
|
||||
double g_timer_frequency;
|
||||
double g_timer_resolution;
|
||||
double g_time_for_frame = 1.0 / 60.0;
|
||||
|
||||
//-------------------------------------
|
||||
extern uint64_t mfb_timer_tick();
|
||||
extern void mfb_timer_init();
|
||||
|
||||
//-------------------------------------
|
||||
void
|
||||
mfb_set_target_fps(uint32_t fps) {
|
||||
if(fps == 0) {
|
||||
g_time_for_frame = 0;
|
||||
}
|
||||
else {
|
||||
g_time_for_frame = 1.0 / fps;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
struct mfb_timer *
|
||||
mfb_timer_create() {
|
||||
static int once = 1;
|
||||
mfb_timer *tmr;
|
||||
|
||||
if(once) {
|
||||
once = 0;
|
||||
mfb_timer_init();
|
||||
}
|
||||
|
||||
tmr = malloc(sizeof(mfb_timer));
|
||||
mfb_timer_reset(tmr);
|
||||
|
||||
return tmr;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void
|
||||
mfb_timer_destroy(struct mfb_timer *tmr) {
|
||||
if(tmr != 0x0) {
|
||||
free(tmr);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void
|
||||
mfb_timer_reset(struct mfb_timer *tmr) {
|
||||
if(tmr == 0x0)
|
||||
return;
|
||||
|
||||
tmr->start_time = mfb_timer_tick();
|
||||
tmr->delta_counter = tmr->start_time;
|
||||
tmr->time = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
double
|
||||
mfb_timer_now(struct mfb_timer *tmr) {
|
||||
uint64_t counter;
|
||||
|
||||
if(tmr == 0x0)
|
||||
return 0.0;
|
||||
|
||||
counter = mfb_timer_tick();
|
||||
tmr->time += (counter - tmr->start_time);
|
||||
tmr->start_time = counter;
|
||||
|
||||
return tmr->time * g_timer_resolution;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
double
|
||||
mfb_timer_delta(struct mfb_timer *tmr) {
|
||||
int64_t counter;
|
||||
uint64_t delta;
|
||||
|
||||
if(tmr == 0x0)
|
||||
return 0.0;
|
||||
|
||||
counter = mfb_timer_tick();
|
||||
delta = (counter - tmr->delta_counter);
|
||||
tmr->delta_counter = counter;
|
||||
|
||||
return delta * g_timer_resolution;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
double
|
||||
mfb_timer_get_frequency() {
|
||||
return g_timer_frequency;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
double
|
||||
mfb_timer_get_resolution() {
|
||||
return g_timer_resolution;
|
||||
}
|
@ -10,6 +10,8 @@
|
||||
#include <MetalKit/MetalKit.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
void init_keycodes();
|
||||
|
||||
@ -250,6 +252,7 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
|
||||
[window_data_osx->window setAcceptsMouseMovedEvents:YES];
|
||||
|
||||
[window_data_osx->window center];
|
||||
window_data_osx->timer = mfb_timer_create();
|
||||
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
|
||||
@ -286,6 +289,8 @@ destroy_window_data(SWindowData *window_data)
|
||||
[window removeWindowData];
|
||||
[window performClose:nil];
|
||||
|
||||
mfb_timer_destroy(window_data_osx->timer);
|
||||
|
||||
memset(window_data_osx, 0, sizeof(SWindowData_OSX));
|
||||
free(window_data_osx);
|
||||
}
|
||||
@ -303,14 +308,12 @@ update_events(SWindowData *window_data)
|
||||
NSEvent* event;
|
||||
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
do
|
||||
{
|
||||
do {
|
||||
event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES];
|
||||
if (event) {
|
||||
[NSApp sendEvent:event];
|
||||
}
|
||||
}
|
||||
while ((window_data->close == false) && event);
|
||||
} while ((window_data->close == false) && event);
|
||||
|
||||
[pool release];
|
||||
}
|
||||
@ -375,6 +378,59 @@ mfb_update_events(struct mfb_window *window)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern double g_time_for_frame;
|
||||
|
||||
bool
|
||||
mfb_wait_sync(struct mfb_window *window)
|
||||
{
|
||||
NSEvent* event;
|
||||
|
||||
if(window == 0x0) {
|
||||
return STATE_INVALID_WINDOW;
|
||||
}
|
||||
|
||||
SWindowData *window_data = (SWindowData *) window;
|
||||
if(window_data->close) {
|
||||
destroy_window_data(window_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
//NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window_data->specific;
|
||||
double current;
|
||||
uint32_t millis = 1;
|
||||
while(1) {
|
||||
event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES];
|
||||
if (event) {
|
||||
[NSApp sendEvent:event];
|
||||
}
|
||||
|
||||
if(window_data->close) {
|
||||
destroy_window_data(window_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
current = mfb_timer_now(window_data_osx->timer);
|
||||
if (current >= g_time_for_frame) {
|
||||
mfb_timer_reset(window_data_osx->timer);
|
||||
return true;
|
||||
}
|
||||
else if(current >= g_time_for_frame * 0.8) {
|
||||
millis = 0;
|
||||
}
|
||||
|
||||
usleep(millis * 1000);
|
||||
//sched_yield();
|
||||
}
|
||||
|
||||
//[pool release];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool
|
||||
mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height)
|
||||
{
|
||||
@ -540,3 +596,35 @@ init_keycodes()
|
||||
g_keycodes[0x43] = KB_KEY_KP_MULTIPLY;
|
||||
g_keycodes[0x4E] = KB_KEY_KP_SUBTRACT;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern double g_timer_frequency;
|
||||
extern double g_timer_resolution;
|
||||
|
||||
uint64_t
|
||||
mfb_timer_tick() {
|
||||
static mach_timebase_info_data_t timebase = { 0 };
|
||||
|
||||
if (timebase.denom == 0) {
|
||||
(void) mach_timebase_info(&timebase);
|
||||
}
|
||||
|
||||
uint64_t time = mach_absolute_time();
|
||||
|
||||
//return (time * s_timebase_info.numer) / s_timebase_info.denom;
|
||||
|
||||
// Perform the arithmetic at 128-bit precision to avoid the overflow!
|
||||
uint64_t high = (time >> 32) * timebase.numer;
|
||||
uint64_t highRem = ((high % timebase.denom) << 32) / timebase.denom;
|
||||
uint64_t low = (time & 0xFFFFFFFFull) * timebase.numer / timebase.denom;
|
||||
high /= timebase.denom;
|
||||
|
||||
return (high << 32) + highRem + low;
|
||||
}
|
||||
|
||||
void
|
||||
mfb_timer_init() {
|
||||
g_timer_frequency = 1e+9;
|
||||
g_timer_resolution = 1.0 / g_timer_frequency;
|
||||
}
|
||||
|
@ -10,7 +10,9 @@
|
||||
@class OSXWindow;
|
||||
|
||||
typedef struct {
|
||||
OSXWindow *window;
|
||||
OSXWindow *window;
|
||||
struct mfb_timer *timer;
|
||||
|
||||
#if defined(USE_METAL_API)
|
||||
struct {
|
||||
id<MTLCommandQueue> command_queue;
|
||||
|
@ -27,6 +27,7 @@ destroy_window_data(SWindowData *window_data)
|
||||
|
||||
SWindowData_Way *window_data_way = (SWindowData_Way *) window_data->specific;
|
||||
if(window_data_way != 0x0) {
|
||||
mfb_timer_destroy(window_data_way->timer);
|
||||
memset(window_data_way, 0, sizeof(SWindowData_Way));
|
||||
free(window_data_way);
|
||||
}
|
||||
@ -596,8 +597,8 @@ mfb_open(const char *title, unsigned width, unsigned height)
|
||||
|
||||
init_keycodes();
|
||||
|
||||
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) {
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
@ -667,6 +668,8 @@ mfb_open(const char *title, unsigned width, unsigned height)
|
||||
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);
|
||||
|
||||
window_data_way->timer = mfb_timer_create();
|
||||
|
||||
mfb_set_keyboard_callback((struct mfb_window *) window_data, keyboard_default);
|
||||
|
||||
printf("Window created using Wayland API\n");
|
||||
@ -762,7 +765,7 @@ mfb_update_events(struct mfb_window *window)
|
||||
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) {
|
||||
if (wl_display_dispatch_pending(window_data_way->display) == -1) {
|
||||
return STATE_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@ -771,6 +774,51 @@ mfb_update_events(struct mfb_window *window)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern double g_time_for_frame;
|
||||
|
||||
bool
|
||||
mfb_wait_sync(struct mfb_window *window) {
|
||||
if(window == 0x0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SWindowData *window_data = (SWindowData *) window;
|
||||
if(window_data->close) {
|
||||
destroy(window_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
SWindowData_Way *window_data_way = (SWindowData_Way *) window_data->specific;
|
||||
double current;
|
||||
uint32_t millis = 1;
|
||||
while(1) {
|
||||
if (wl_display_dispatch_pending(window_data_way->display) == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(window_data->close) {
|
||||
destroy_window_data(window_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
current = mfb_timer_now(window_data_way->timer);
|
||||
if (current >= g_time_for_frame) {
|
||||
mfb_timer_reset(window_data_way->timer);
|
||||
return true;
|
||||
}
|
||||
else if(current >= g_time_for_frame * 0.8) {
|
||||
millis = 0;
|
||||
}
|
||||
|
||||
usleep(millis * 1000);
|
||||
//sched_yield();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern short int g_keycodes[512];
|
||||
|
||||
void
|
||||
|
@ -53,5 +53,6 @@ typedef struct
|
||||
uint32_t buffer_stride;
|
||||
|
||||
uint32_t mod_keys;
|
||||
struct mfb_timer *timer;
|
||||
bool close;
|
||||
} SWindowData_Way;
|
||||
|
@ -48,10 +48,8 @@ WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
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, 0x0);
|
||||
}
|
||||
|
||||
ValidateRect(hWnd, 0x0);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -359,6 +357,8 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
|
||||
|
||||
window_data_win->hdc = GetDC(window_data_win->window);
|
||||
|
||||
window_data_win->timer = mfb_timer_create();
|
||||
|
||||
mfb_set_keyboard_callback((struct mfb_window *) window_data, keyboard_default);
|
||||
|
||||
return (struct mfb_window *) window_data;
|
||||
@ -421,9 +421,8 @@ mfb_update_events(struct mfb_window *window) {
|
||||
|
||||
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)) {
|
||||
if(msg.message == WM_PAINT)
|
||||
return STATE_OK;
|
||||
|
||||
//if(msg.message == WM_PAINT)
|
||||
// return STATE_OK;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
@ -433,6 +432,53 @@ mfb_update_events(struct mfb_window *window) {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern double g_time_for_frame;
|
||||
|
||||
bool
|
||||
mfb_wait_sync(struct mfb_window *window) {
|
||||
MSG msg;
|
||||
|
||||
if (window == 0x0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SWindowData *window_data = (SWindowData *)window;
|
||||
if (window_data->close) {
|
||||
destroy_window_data(window_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific;
|
||||
double current;
|
||||
uint32_t millis = 1;
|
||||
while (1) {
|
||||
if(PeekMessage(&msg, window_data_win->window, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
if (window_data->close) {
|
||||
destroy_window_data(window_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
current = mfb_timer_now(window_data_win->timer);;
|
||||
if (current >= g_time_for_frame) {
|
||||
mfb_timer_reset(window_data_win->timer);
|
||||
return true;
|
||||
}
|
||||
else if(current >= g_time_for_frame * 0.8) {
|
||||
millis = 0;
|
||||
}
|
||||
|
||||
Sleep(millis);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
destroy_window_data(SWindowData *window_data) {
|
||||
if (window_data == 0x0)
|
||||
@ -453,6 +499,8 @@ destroy_window_data(SWindowData *window_data) {
|
||||
window_data_win->window = 0;
|
||||
window_data_win->hdc = 0;
|
||||
window_data_win->bitmapInfo = 0x0;
|
||||
mfb_timer_destroy(window_data_win->timer);
|
||||
window_data_win->timer = 0x0;
|
||||
window_data->close = true;
|
||||
}
|
||||
|
||||
@ -659,3 +707,27 @@ mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern double g_timer_frequency;
|
||||
extern double g_timer_resolution;
|
||||
|
||||
uint64_t
|
||||
mfb_timer_tick() {
|
||||
int64_t counter;
|
||||
|
||||
QueryPerformanceCounter((LARGE_INTEGER *) &counter);
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
void
|
||||
mfb_timer_init() {
|
||||
uint64_t frequency;
|
||||
|
||||
QueryPerformanceFrequency((LARGE_INTEGER *) &frequency);
|
||||
|
||||
g_timer_frequency = (double) ((int64_t) frequency);
|
||||
g_timer_resolution = 1.0 / g_timer_frequency;
|
||||
}
|
||||
|
@ -7,9 +7,10 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
HWND window;
|
||||
WNDCLASS wc;
|
||||
HDC hdc;
|
||||
BITMAPINFO *bitmapInfo;
|
||||
bool mouse_inside;
|
||||
HWND window;
|
||||
WNDCLASS wc;
|
||||
HDC hdc;
|
||||
BITMAPINFO *bitmapInfo;
|
||||
struct mfb_timer *timer;
|
||||
bool mouse_inside;
|
||||
} SWindowData_Win;
|
||||
|
@ -6,15 +6,16 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
Window window;
|
||||
|
||||
Display *display;
|
||||
int screen;
|
||||
GC gc;
|
||||
XImage *image;
|
||||
|
||||
void *image_buffer;
|
||||
XImage *image_scaler;
|
||||
uint32_t image_scaler_width;
|
||||
uint32_t image_scaler_height;
|
||||
Window window;
|
||||
|
||||
Display *display;
|
||||
int screen;
|
||||
GC gc;
|
||||
XImage *image;
|
||||
|
||||
void *image_buffer;
|
||||
XImage *image_scaler;
|
||||
uint32_t image_scaler_width;
|
||||
uint32_t image_scaler_height;
|
||||
struct mfb_timer *timer;
|
||||
} SWindowData_X11;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <MiniFB.h>
|
||||
#include <MiniFB_internal.h>
|
||||
#include "WindowData.h"
|
||||
@ -185,6 +186,8 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
|
||||
|
||||
window_data_x11->image = XCreateImage(window_data_x11->display, CopyFromParent, depth, ZPixmap, 0, 0x0, width, height, 32, width * 4);
|
||||
|
||||
window_data_x11->timer = mfb_timer_create();
|
||||
|
||||
mfb_set_keyboard_callback((struct mfb_window *) window_data, keyboard_default);
|
||||
|
||||
printf("Window created using X11 API\n");
|
||||
@ -203,106 +206,111 @@ int translate_key(int scancode);
|
||||
int translate_mod(int state);
|
||||
int translate_mod_ex(int key, int state, int is_pressed);
|
||||
|
||||
static void
|
||||
processEvent(SWindowData *window_data, XEvent *event) {
|
||||
switch (event->type) {
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
{
|
||||
mfb_key key_code = (mfb_key) translate_key(event->xkey.keycode);
|
||||
int is_pressed = (event->type == KeyPress);
|
||||
window_data->mod_keys = translate_mod_ex(key_code, event->xkey.state, is_pressed);
|
||||
|
||||
window_data->key_status[key_code] = is_pressed;
|
||||
kCall(keyboard_func, key_code, (mfb_key_mod) window_data->mod_keys, is_pressed);
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
{
|
||||
mfb_mouse_button button = (mfb_mouse_button) event->xbutton.button;
|
||||
int is_pressed = (event->type == ButtonPress);
|
||||
window_data->mod_keys = translate_mod(event->xkey.state);
|
||||
switch (button) {
|
||||
case Button1:
|
||||
case Button2:
|
||||
case Button3:
|
||||
kCall(mouse_btn_func, button, (mfb_key_mod) window_data->mod_keys, is_pressed);
|
||||
break;
|
||||
|
||||
case Button4:
|
||||
kCall(mouse_wheel_func, (mfb_key_mod) window_data->mod_keys, 0.0f, 1.0f);
|
||||
break;
|
||||
case Button5:
|
||||
kCall(mouse_wheel_func, (mfb_key_mod) window_data->mod_keys, 0.0f, -1.0f);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
kCall(mouse_wheel_func, (mfb_key_mod) window_data->mod_keys, 1.0f, 0.0f);
|
||||
break;
|
||||
case 7:
|
||||
kCall(mouse_wheel_func, (mfb_key_mod) window_data->mod_keys, -1.0f, 0.0f);
|
||||
break;
|
||||
|
||||
default:
|
||||
kCall(mouse_btn_func, (mfb_mouse_button) (button - 4), (mfb_key_mod) window_data->mod_keys, is_pressed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
window_data->mouse_pos_x = event->xmotion.x;
|
||||
window_data->mouse_pos_y = event->xmotion.y;
|
||||
kCall(mouse_move_func, event->xmotion.x, event->xmotion.y);
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
{
|
||||
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;
|
||||
|
||||
SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific;
|
||||
XClearWindow(window_data_x11->display, window_data_x11->window);
|
||||
kCall(resize_func, window_data->window_width, window_data->window_height);
|
||||
}
|
||||
break;
|
||||
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
break;
|
||||
|
||||
case FocusIn:
|
||||
window_data->is_active = true;
|
||||
kCall(active_func, true);
|
||||
break;
|
||||
|
||||
case FocusOut:
|
||||
window_data->is_active = false;
|
||||
kCall(active_func, false);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
window_data->close = true;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
processEvents(SWindowData *window_data) {
|
||||
XEvent event;
|
||||
SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific;
|
||||
SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific;
|
||||
|
||||
while ((window_data->close == false) && XPending(window_data_x11->display)) {
|
||||
XNextEvent(window_data_x11->display, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
{
|
||||
mfb_key key_code = (mfb_key) translate_key(event.xkey.keycode);
|
||||
int is_pressed = (event.type == KeyPress);
|
||||
window_data->mod_keys = translate_mod_ex(key_code, event.xkey.state, is_pressed);
|
||||
|
||||
window_data->key_status[key_code] = is_pressed;
|
||||
kCall(keyboard_func, key_code, (mfb_key_mod) window_data->mod_keys, is_pressed);
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
{
|
||||
mfb_mouse_button button = (mfb_mouse_button) event.xbutton.button;
|
||||
int is_pressed = (event.type == ButtonPress);
|
||||
window_data->mod_keys = translate_mod(event.xkey.state);
|
||||
switch (button) {
|
||||
case Button1:
|
||||
case Button2:
|
||||
case Button3:
|
||||
kCall(mouse_btn_func, button, (mfb_key_mod) window_data->mod_keys, is_pressed);
|
||||
break;
|
||||
|
||||
case Button4:
|
||||
kCall(mouse_wheel_func, (mfb_key_mod) window_data->mod_keys, 0.0f, 1.0f);
|
||||
break;
|
||||
case Button5:
|
||||
kCall(mouse_wheel_func, (mfb_key_mod) window_data->mod_keys, 0.0f, -1.0f);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
kCall(mouse_wheel_func, (mfb_key_mod) window_data->mod_keys, 1.0f, 0.0f);
|
||||
break;
|
||||
case 7:
|
||||
kCall(mouse_wheel_func, (mfb_key_mod) window_data->mod_keys, -1.0f, 0.0f);
|
||||
break;
|
||||
|
||||
default:
|
||||
kCall(mouse_btn_func, (mfb_mouse_button) (button - 4), (mfb_key_mod) window_data->mod_keys, is_pressed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
window_data->mouse_pos_x = event.xmotion.x;
|
||||
window_data->mouse_pos_y = event.xmotion.y;
|
||||
kCall(mouse_move_func, event.xmotion.x, event.xmotion.y);
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
{
|
||||
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(window_data_x11->display, window_data_x11->window);
|
||||
kCall(resize_func, window_data->window_width, window_data->window_height);
|
||||
}
|
||||
break;
|
||||
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
break;
|
||||
|
||||
case FocusIn:
|
||||
window_data->is_active = true;
|
||||
kCall(active_func, true);
|
||||
break;
|
||||
|
||||
case FocusOut:
|
||||
window_data->is_active = false;
|
||||
kCall(active_func, false);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
window_data->close = true;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
processEvent(window_data, &event);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void destroy(SWindowData *window_data);
|
||||
void destroy_window_data(SWindowData *window_data);
|
||||
|
||||
mfb_update_state
|
||||
mfb_update(struct mfb_window *window, void *buffer) {
|
||||
@ -312,7 +320,7 @@ mfb_update(struct mfb_window *window, void *buffer) {
|
||||
|
||||
SWindowData *window_data = (SWindowData *) window;
|
||||
if (window_data->close) {
|
||||
destroy(window_data);
|
||||
destroy_window_data(window_data);
|
||||
return STATE_EXIT;
|
||||
}
|
||||
|
||||
@ -368,7 +376,7 @@ mfb_update_events(struct mfb_window *window) {
|
||||
|
||||
SWindowData *window_data = (SWindowData *) window;
|
||||
if (window_data->close) {
|
||||
destroy(window_data);
|
||||
destroy_window_data(window_data);
|
||||
return STATE_EXIT;
|
||||
}
|
||||
|
||||
@ -381,8 +389,56 @@ mfb_update_events(struct mfb_window *window) {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern double g_time_for_frame;
|
||||
|
||||
bool
|
||||
mfb_wait_sync(struct mfb_window *window) {
|
||||
if (window == 0x0) {
|
||||
return STATE_INVALID_WINDOW;
|
||||
}
|
||||
|
||||
SWindowData *window_data = (SWindowData *) window;
|
||||
if (window_data->close) {
|
||||
destroy_window_data(window_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific;
|
||||
XFlush(window_data_x11->display);
|
||||
XEvent event;
|
||||
double current;
|
||||
uint32_t millis = 1;
|
||||
while(1) {
|
||||
if(XEventsQueued(window_data_x11->display, QueuedAlready) > 0) {
|
||||
XNextEvent(window_data_x11->display, &event);
|
||||
processEvent(window_data, &event);
|
||||
}
|
||||
|
||||
if(window_data->close) {
|
||||
destroy_window_data(window_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
current = mfb_timer_now(window_data_x11->timer);
|
||||
if (current >= g_time_for_frame) {
|
||||
mfb_timer_reset(window_data_x11->timer);
|
||||
return true;
|
||||
}
|
||||
else if(current >= g_time_for_frame * 0.8) {
|
||||
millis = 0;
|
||||
}
|
||||
|
||||
usleep(millis * 1000);
|
||||
//sched_yield();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
destroy(SWindowData *window_data) {
|
||||
destroy_window_data(SWindowData *window_data) {
|
||||
if (window_data != 0x0) {
|
||||
if (window_data->specific != 0x0) {
|
||||
SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific;
|
||||
@ -392,6 +448,7 @@ destroy(SWindowData *window_data) {
|
||||
XDestroyWindow(window_data_x11->display, window_data_x11->window);
|
||||
XCloseDisplay(window_data_x11->display);
|
||||
}
|
||||
mfb_timer_destroy(window_data_x11->timer);
|
||||
memset(window_data_x11, 0, sizeof(SWindowData_X11));
|
||||
free(window_data_x11);
|
||||
}
|
||||
|
Reference in New Issue
Block a user