jtk: indicate which Window had event; convert Event to class
This commit is contained in:
parent
a30b4b7ff8
commit
56c20c4a36
173
src/jtk/event.d
173
src/jtk/event.d
@ -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();
|
|
||||||
}
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user