From 56c20c4a36d2ce670d837527787067064c9b98e3 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Thu, 16 Jul 2020 11:35:29 -0400 Subject: [PATCH] jtk: indicate which Window had event; convert Event to class --- src/jtk/event.d | 173 +++++++++++++++++++++++++++++++++-------------- src/jtk/init.d | 2 + src/jtk/jtk.c | 64 +++++++----------- src/jtk/window.d | 28 ++++++++ 4 files changed, 175 insertions(+), 92 deletions(-) diff --git a/src/jtk/event.d b/src/jtk/event.d index d7ab6df..30c48fc 100644 --- a/src/jtk/event.d +++ b/src/jtk/event.d @@ -5,27 +5,48 @@ import core.sync.mutex; import core.sync.condition; import std.container.dlist; 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 { - WINDOW_CLOSE, - WINDOW_EXPOSE, - KEY_PRESS, BUTTON_PRESS, BUTTON_RELEASE, + KEY_PRESS, TIMER, + WINDOW_CLOSE, + WINDOW_EXPOSE, WINDOW_RESIZE, }; - struct KeyEvent + struct KeyPressEvent { + Window window; uint key; }; - struct ButtonEvent + struct ButtonPressEvent { + Window window; uint mods; ubyte button; }; @@ -35,37 +56,117 @@ struct Event Timer timer; }; + struct WindowCloseEvent + { + Window window; + } + + struct WindowExposeEvent + { + Window window; + } + struct WindowResizeEvent { + Window window; uint width; uint height; }; - uint type; - uint _pad; + ubyte type; union { - KeyEvent key_event; - ButtonEvent button_event; - TimerEvent timer_event; - WindowResizeEvent resize_event; + KeyPressEvent key_press; + ButtonPressEvent button_press; + TimerEvent timer; + 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 __gshared Mutex event_list_mutex; -private __gshared Mutex wait_event_mutex; -private __gshared Condition wait_event_condition; +private Event c_event_to_event(jtk_event_t * c_event) +{ + Event event = new Event; + 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) { if (!event_list.empty) { - Event * rv = event_list.front; + Event rv = event_list.front; event_list.removeFront(); return rv; } @@ -73,7 +174,7 @@ Event * check_event() return null; } -Event * wait_event() +Event wait_event() { synchronized(wait_event_mutex) { @@ -83,7 +184,7 @@ Event * wait_event() { if (!event_list.empty) { - Event * rv = event_list.front; + Event rv = event_list.front; event_list.removeFront(); 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(); -} diff --git a/src/jtk/init.d b/src/jtk/init.d index d8eda56..965997b 100644 --- a/src/jtk/init.d +++ b/src/jtk/init.d @@ -2,6 +2,7 @@ module jtk.init; static import jtk.event; static import jtk.timer; +static import jtk.window; private extern(C) bool jtk_init(); private extern(C) void jtk_quit(); @@ -15,6 +16,7 @@ bool init() jtk.event.event_init(); jtk.timer.Timer.timer_init(); + jtk.window.Window.window_init(); return true; } diff --git a/src/jtk/jtk.c b/src/jtk/jtk.c index 743f37d..60a900b 100644 --- a/src/jtk/jtk.c +++ b/src/jtk/jtk.c @@ -316,36 +316,22 @@ void jtk_window_set_icon(uint64_t window_handle, const uint8_t * data, #define JTK_KEY_UNKNOWN 0x00FFFFFFu -#define JTK_EVENT_WINDOW_CLOSE 0u -#define JTK_EVENT_WINDOW_EXPOSE 1u +#define JTK_EVENT_BUTTON_PRESS 0u +#define JTK_EVENT_BUTTON_RELEASE 1u #define JTK_EVENT_KEY_PRESS 2u -#define JTK_EVENT_BUTTON_PRESS 3u -#define JTK_EVENT_BUTTON_RELEASE 4u -#define JTK_EVENT_TIMER 5u +#define JTK_EVENT_TIMER 3u +#define JTK_EVENT_WINDOW_CLOSE 4u +#define JTK_EVENT_WINDOW_EXPOSE 5u #define JTK_EVENT_WINDOW_RESIZE 6u typedef struct { - uint32_t key; -} 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 { + uint64_t window_id; uint32_t type; - uint32_t _pad; - union { - jtk_key_event_t key_event; - jtk_button_event_t button_event; - jtk_window_resize_event_t window_resize; - }; + uint32_t key; + uint32_t mods; + int32_t width; + int32_t height; + unsigned char button; } jtk_event_t; 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; 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 * queue. */ 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) { event->type = JTK_EVENT_BUTTON_PRESS; - event->button_event.mods = x_state_to_jtk_key_mods(x_event->xbutton.state); - event->button_event.button = x_event->xbutton.button; + event->window_id = (uint64_t)x_event->xbutton.window; + 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 * events. */ - if ((event->button_event.button == 4) || (event->button_event.button == 5)) + if ((event->button == 4) || (event->button == 5)) { XEvent remove_event; 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) { event->type = JTK_EVENT_WINDOW_RESIZE; - event->window_resize.width = x_event->xconfigure.width; - event->window_resize.height = x_event->xconfigure.height; + event->window_id = (uint64_t)x_event->xconfigure.window; + event->width = x_event->xconfigure.width; + event->height = x_event->xconfigure.height; 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) { event->type = JTK_EVENT_WINDOW_CLOSE; + event->window_id = (uint64_t)x_event->xclient.window; return true; } return false; @@ -624,25 +614,17 @@ static bool process_x_event(XEvent * x_event, jtk_event_t * event) case KeyPress: return process_x_key_press_event(x_event, event); - case KeyRelease: - return false; - case ButtonPress: return process_x_button_press_event(x_event, event); - case ButtonRelease: - break; - case Expose: event->type = JTK_EVENT_WINDOW_EXPOSE; - return true; - - case GraphicsExpose: - event->type = JTK_EVENT_WINDOW_EXPOSE; + event->window_id = (uint64_t)x_event->xexpose.window; return true; case MapNotify: event->type = JTK_EVENT_WINDOW_EXPOSE; + event->window_id = (uint64_t)x_event->xmap.window; return true; case ConfigureNotify: diff --git a/src/jtk/window.d b/src/jtk/window.d index 77abdc4..710cb97 100644 --- a/src/jtk/window.d +++ b/src/jtk/window.d @@ -1,6 +1,7 @@ module jtk.window; import std.string; +import core.sync.mutex; private extern(C) bool jtk_window_create(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 { + private static Window[ulong] windows_by_id; + private static Mutex windows_by_id_mutex; private ulong m_window; this() @@ -19,11 +22,19 @@ class Window { /* TODO */ } + synchronized(windows_by_id_mutex) + { + windows_by_id[m_window] = this; + } } void close() { jtk_window_close(m_window); + synchronized(windows_by_id_mutex) + { + windows_by_id.remove(m_window); + } } void set_title(string title) @@ -35,4 +46,21 @@ class 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; + } + } }