jtk: indicate which Window had event; convert Event to class

This commit is contained in:
Josh Holtrop 2020-07-16 11:35:29 -04:00
parent a30b4b7ff8
commit 56c20c4a36
4 changed files with 175 additions and 92 deletions

View File

@ -5,27 +5,48 @@ import core.sync.mutex;
import core.sync.condition; import core.sync.condition;
import std.container.dlist; import std.container.dlist;
import jtk.timer; import jtk.timer;
import jtk.window;
struct Event private struct jtk_event_t
{
ulong window_id;
uint type;
uint key;
uint mods;
int width;
int height;
ubyte button;
}
private extern(C) bool jtk_wait_event(jtk_event_t * event, ulong time_to_wait);
private __gshared DList!(Event) * event_list;
private __gshared Mutex event_list_mutex;
private __gshared Mutex wait_event_mutex;
private __gshared Condition wait_event_condition;
class Event
{ {
enum : uint enum : uint
{ {
WINDOW_CLOSE,
WINDOW_EXPOSE,
KEY_PRESS,
BUTTON_PRESS, BUTTON_PRESS,
BUTTON_RELEASE, BUTTON_RELEASE,
KEY_PRESS,
TIMER, TIMER,
WINDOW_CLOSE,
WINDOW_EXPOSE,
WINDOW_RESIZE, WINDOW_RESIZE,
}; };
struct KeyEvent struct KeyPressEvent
{ {
Window window;
uint key; uint key;
}; };
struct ButtonEvent struct ButtonPressEvent
{ {
Window window;
uint mods; uint mods;
ubyte button; ubyte button;
}; };
@ -35,37 +56,117 @@ struct Event
Timer timer; Timer timer;
}; };
struct WindowCloseEvent
{
Window window;
}
struct WindowExposeEvent
{
Window window;
}
struct WindowResizeEvent struct WindowResizeEvent
{ {
Window window;
uint width; uint width;
uint height; uint height;
}; };
uint type; ubyte type;
uint _pad;
union union
{ {
KeyEvent key_event; KeyPressEvent key_press;
ButtonEvent button_event; ButtonPressEvent button_press;
TimerEvent timer_event; TimerEvent timer;
WindowResizeEvent resize_event; WindowCloseEvent window_close;
WindowExposeEvent window_expose;
WindowResizeEvent window_resize;
}; };
} }
private extern(C) bool jtk_wait_event(Event * event, ulong time_to_wait); private void event_thread()
{
jtk_event_t c_event;
for (;;)
{
ulong time_until_next_timer_expiry = Timer.time_to_next_timer_expiration();
if (!jtk_wait_event(&c_event, time_until_next_timer_expiry))
{
break;
}
synchronized(event_list_mutex)
{
Event event = c_event_to_event(&c_event);
if (event !is null)
{
event_list.insertBack(event);
}
}
synchronized(wait_event_mutex)
{
wait_event_condition.notifyAll();
}
}
}
private __gshared DList!(Event *) * event_list; private Event c_event_to_event(jtk_event_t * c_event)
private __gshared Mutex event_list_mutex; {
private __gshared Mutex wait_event_mutex; Event event = new Event;
private __gshared Condition wait_event_condition; event.type = cast(ubyte)c_event.type;
Window window = Window.find_by_id(c_event.window_id);
switch (c_event.type)
{
case Event.BUTTON_PRESS:
event.button_press.window = window;
event.button_press.mods = c_event.mods;
event.button_press.button = c_event.button;
break;
Event * check_event() case Event.BUTTON_RELEASE:
break;
case Event.KEY_PRESS:
event.key_press.window = window;
event.key_press.key = c_event.key;
break;
case Event.WINDOW_CLOSE:
event.window_close.window = window;
break;
case Event.WINDOW_EXPOSE:
event.window_expose.window = window;
break;
case Event.WINDOW_RESIZE:
event.window_resize.window = window;
event.window_resize.width = c_event.width;
event.window_resize.height = c_event.height;
break;
default:
return null;
}
return event;
}
package void event_init()
{
event_list = new DList!(Event);
event_list_mutex = new Mutex;
wait_event_mutex = new Mutex;
wait_event_condition = new Condition(wait_event_mutex);
new Thread(&event_thread).start();
}
Event check_event()
{ {
synchronized(event_list_mutex) synchronized(event_list_mutex)
{ {
if (!event_list.empty) if (!event_list.empty)
{ {
Event * rv = event_list.front; Event rv = event_list.front;
event_list.removeFront(); event_list.removeFront();
return rv; return rv;
} }
@ -73,7 +174,7 @@ Event * check_event()
return null; return null;
} }
Event * wait_event() Event wait_event()
{ {
synchronized(wait_event_mutex) synchronized(wait_event_mutex)
{ {
@ -83,7 +184,7 @@ Event * wait_event()
{ {
if (!event_list.empty) if (!event_list.empty)
{ {
Event * rv = event_list.front; Event rv = event_list.front;
event_list.removeFront(); event_list.removeFront();
return rv; return rv;
} }
@ -92,33 +193,3 @@ Event * wait_event()
} }
} }
} }
private void event_thread()
{
for (;;)
{
Event * event = new Event;
ulong time_until_next_timer_expiry = Timer.time_to_next_timer_expiration();
if (!jtk_wait_event(event, time_until_next_timer_expiry))
{
break;
}
synchronized(event_list_mutex)
{
event_list.insertBack(event);
}
synchronized(wait_event_mutex)
{
wait_event_condition.notifyAll();
}
}
}
package void event_init()
{
event_list = new DList!(Event *);
event_list_mutex = new Mutex;
wait_event_mutex = new Mutex;
wait_event_condition = new Condition(wait_event_mutex);
new Thread(&event_thread).start();
}

View File

@ -2,6 +2,7 @@ module jtk.init;
static import jtk.event; static import jtk.event;
static import jtk.timer; static import jtk.timer;
static import jtk.window;
private extern(C) bool jtk_init(); private extern(C) bool jtk_init();
private extern(C) void jtk_quit(); private extern(C) void jtk_quit();
@ -15,6 +16,7 @@ bool init()
jtk.event.event_init(); jtk.event.event_init();
jtk.timer.Timer.timer_init(); jtk.timer.Timer.timer_init();
jtk.window.Window.window_init();
return true; return true;
} }

View File

@ -316,36 +316,22 @@ void jtk_window_set_icon(uint64_t window_handle, const uint8_t * data,
#define JTK_KEY_UNKNOWN 0x00FFFFFFu #define JTK_KEY_UNKNOWN 0x00FFFFFFu
#define JTK_EVENT_WINDOW_CLOSE 0u #define JTK_EVENT_BUTTON_PRESS 0u
#define JTK_EVENT_WINDOW_EXPOSE 1u #define JTK_EVENT_BUTTON_RELEASE 1u
#define JTK_EVENT_KEY_PRESS 2u #define JTK_EVENT_KEY_PRESS 2u
#define JTK_EVENT_BUTTON_PRESS 3u #define JTK_EVENT_TIMER 3u
#define JTK_EVENT_BUTTON_RELEASE 4u #define JTK_EVENT_WINDOW_CLOSE 4u
#define JTK_EVENT_TIMER 5u #define JTK_EVENT_WINDOW_EXPOSE 5u
#define JTK_EVENT_WINDOW_RESIZE 6u #define JTK_EVENT_WINDOW_RESIZE 6u
typedef struct { typedef struct {
uint32_t key; uint64_t window_id;
} jtk_key_event_t;
typedef struct {
uint32_t mods;
uint8_t button;
} jtk_button_event_t;
typedef struct {
uint32_t width;
uint32_t height;
} jtk_window_resize_event_t;
typedef struct {
uint32_t type; uint32_t type;
uint32_t _pad; uint32_t key;
union { uint32_t mods;
jtk_key_event_t key_event; int32_t width;
jtk_button_event_t button_event; int32_t height;
jtk_window_resize_event_t window_resize; unsigned char button;
};
} jtk_event_t; } jtk_event_t;
static uint32_t x_state_to_jtk_key_mods(unsigned int x_state) static uint32_t x_state_to_jtk_key_mods(unsigned int x_state)
@ -530,7 +516,8 @@ static bool process_x_key_press_event(XEvent * x_event, jtk_event_t * event)
{ {
unsigned int x_keycode = x_event->xkey.keycode; unsigned int x_keycode = x_event->xkey.keycode;
event->type = JTK_EVENT_KEY_PRESS; event->type = JTK_EVENT_KEY_PRESS;
event->key_event.key = x_key_to_jtk_key(x_keycode, x_event->xkey.state); event->window_id = (uint64_t)x_event->xkey.window;
event->key = x_key_to_jtk_key(x_keycode, x_event->xkey.state);
/* Remove any following keypress events for the same keycode from the X /* Remove any following keypress events for the same keycode from the X
* queue. */ * queue. */
XEvent remove_event; XEvent remove_event;
@ -555,11 +542,12 @@ static Bool match_button_press(Display * display, XEvent * event, XPointer arg)
static bool process_x_button_press_event(XEvent * x_event, jtk_event_t * event) static bool process_x_button_press_event(XEvent * x_event, jtk_event_t * event)
{ {
event->type = JTK_EVENT_BUTTON_PRESS; event->type = JTK_EVENT_BUTTON_PRESS;
event->button_event.mods = x_state_to_jtk_key_mods(x_event->xbutton.state); event->window_id = (uint64_t)x_event->xbutton.window;
event->button_event.button = x_event->xbutton.button; event->mods = x_state_to_jtk_key_mods(x_event->xbutton.state);
event->button = x_event->xbutton.button;
/* If this is a mouse wheel scroll event, remove any following scroll /* If this is a mouse wheel scroll event, remove any following scroll
* events. */ * events. */
if ((event->button_event.button == 4) || (event->button_event.button == 5)) if ((event->button == 4) || (event->button == 5))
{ {
XEvent remove_event; XEvent remove_event;
while (XCheckIfEvent(g_display, &remove_event, match_button_press, (XPointer)x_event) == True) while (XCheckIfEvent(g_display, &remove_event, match_button_press, (XPointer)x_event) == True)
@ -580,8 +568,9 @@ static bool process_x_button_press_event(XEvent * x_event, jtk_event_t * event)
static bool process_x_configure_event(XEvent * x_event, jtk_event_t * event) static bool process_x_configure_event(XEvent * x_event, jtk_event_t * event)
{ {
event->type = JTK_EVENT_WINDOW_RESIZE; event->type = JTK_EVENT_WINDOW_RESIZE;
event->window_resize.width = x_event->xconfigure.width; event->window_id = (uint64_t)x_event->xconfigure.window;
event->window_resize.height = x_event->xconfigure.height; event->width = x_event->xconfigure.width;
event->height = x_event->xconfigure.height;
return true; return true;
} }
@ -599,6 +588,7 @@ static bool process_x_client_message_event(XEvent * x_event, jtk_event_t * event
if (x_event->xclient.data.l[0] == (long)wm_delete_window_atom) if (x_event->xclient.data.l[0] == (long)wm_delete_window_atom)
{ {
event->type = JTK_EVENT_WINDOW_CLOSE; event->type = JTK_EVENT_WINDOW_CLOSE;
event->window_id = (uint64_t)x_event->xclient.window;
return true; return true;
} }
return false; return false;
@ -624,25 +614,17 @@ static bool process_x_event(XEvent * x_event, jtk_event_t * event)
case KeyPress: case KeyPress:
return process_x_key_press_event(x_event, event); return process_x_key_press_event(x_event, event);
case KeyRelease:
return false;
case ButtonPress: case ButtonPress:
return process_x_button_press_event(x_event, event); return process_x_button_press_event(x_event, event);
case ButtonRelease:
break;
case Expose: case Expose:
event->type = JTK_EVENT_WINDOW_EXPOSE; event->type = JTK_EVENT_WINDOW_EXPOSE;
return true; event->window_id = (uint64_t)x_event->xexpose.window;
case GraphicsExpose:
event->type = JTK_EVENT_WINDOW_EXPOSE;
return true; return true;
case MapNotify: case MapNotify:
event->type = JTK_EVENT_WINDOW_EXPOSE; event->type = JTK_EVENT_WINDOW_EXPOSE;
event->window_id = (uint64_t)x_event->xmap.window;
return true; return true;
case ConfigureNotify: case ConfigureNotify:

View File

@ -1,6 +1,7 @@
module jtk.window; module jtk.window;
import std.string; import std.string;
import core.sync.mutex;
private extern(C) bool jtk_window_create(ulong * window); private extern(C) bool jtk_window_create(ulong * window);
private extern(C) void jtk_window_swap_buffers(ulong window); private extern(C) void jtk_window_swap_buffers(ulong window);
@ -11,6 +12,8 @@ private extern(C) void jtk_window_set_icon(ulong window, const ubyte * data,
class Window class Window
{ {
private static Window[ulong] windows_by_id;
private static Mutex windows_by_id_mutex;
private ulong m_window; private ulong m_window;
this() this()
@ -19,11 +22,19 @@ class Window
{ {
/* TODO */ /* TODO */
} }
synchronized(windows_by_id_mutex)
{
windows_by_id[m_window] = this;
}
} }
void close() void close()
{ {
jtk_window_close(m_window); jtk_window_close(m_window);
synchronized(windows_by_id_mutex)
{
windows_by_id.remove(m_window);
}
} }
void set_title(string title) void set_title(string title)
@ -35,4 +46,21 @@ class Window
{ {
jtk_window_swap_buffers(m_window); jtk_window_swap_buffers(m_window);
} }
package static void window_init()
{
windows_by_id_mutex = new Mutex;
}
package static Window find_by_id(ulong window_id)
{
try
{
return windows_by_id[window_id];
}
catch (core.exception.RangeError re)
{
return null;
}
}
} }