jtk: indicate which Window had event; convert Event to class
This commit is contained in:
parent
a30b4b7ff8
commit
56c20c4a36
183
src/jtk/event.d
183
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,78 +56,53 @@ 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 __gshared DList!(Event *) * event_list;
|
||||
private __gshared Mutex event_list_mutex;
|
||||
private __gshared Mutex wait_event_mutex;
|
||||
private __gshared Condition wait_event_condition;
|
||||
|
||||
Event * check_event()
|
||||
{
|
||||
synchronized(event_list_mutex)
|
||||
{
|
||||
if (!event_list.empty)
|
||||
{
|
||||
Event * rv = event_list.front;
|
||||
event_list.removeFront();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Event * wait_event()
|
||||
{
|
||||
synchronized(wait_event_mutex)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
synchronized(event_list_mutex)
|
||||
{
|
||||
if (!event_list.empty)
|
||||
{
|
||||
Event * rv = event_list.front;
|
||||
event_list.removeFront();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
wait_event_condition.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void event_thread()
|
||||
{
|
||||
jtk_event_t c_event;
|
||||
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))
|
||||
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();
|
||||
@ -114,11 +110,86 @@ private void event_thread()
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 = 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_list.removeFront();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Event wait_event()
|
||||
{
|
||||
synchronized(wait_event_mutex)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
synchronized(event_list_mutex)
|
||||
{
|
||||
if (!event_list.empty)
|
||||
{
|
||||
Event rv = event_list.front;
|
||||
event_list.removeFront();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
wait_event_condition.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user