diff --git a/c_src/device/cairo/cairo_gtk.c b/c_src/device/cairo/cairo_gtk.c index 0f252dc..65b9033 100644 --- a/c_src/device/cairo/cairo_gtk.c +++ b/c_src/device/cairo/cairo_gtk.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ typedef struct { GThread* main; GtkWidget* window; GMutex render_mutex; + GMutex cmd_mutex; float last_x; float last_y; } cairo_gtk_t; @@ -58,10 +60,13 @@ static gboolean on_motion_event(GtkWidget* widget, GdkEventMotion* event, gpointer data) { - if ((g_cairo_gtk.last_x != event->x) && (g_cairo_gtk.last_y != event->y)) { - send_cursor_pos(event->x, event->y); - g_cairo_gtk.last_x = event->x; - g_cairo_gtk.last_y = event->y; + float x = floorf(event->x); + float y = floorf(event->y); + + if ((g_cairo_gtk.last_x != x) && (g_cairo_gtk.last_y != y)) { + send_cursor_pos(x, y); + g_cairo_gtk.last_x = x; + g_cairo_gtk.last_y = y; } return TRUE; @@ -83,11 +88,14 @@ static gboolean on_button_event(GtkWidget* widget, return FALSE; } + float x = floorf(event->x); + float y = floorf(event->y); + send_mouse_button(KEYMAP_GDK, event->button, action, event->state, - event->x, event->y); + x, y); return TRUE; } @@ -105,6 +113,32 @@ static gboolean on_key_event(GtkWidget* widget, return TRUE; } +static gboolean on_enter_leave_event(GtkWidget* widget, + GdkEventCrossing* event, + gpointer data) +{ + int action = (event->type == GDK_ENTER_NOTIFY) ? 1 : 0; + float x = floorf(event->x); + float y = floorf(event->y); + + send_cursor_enter(action, x, y); + + return TRUE; +} + +static gboolean on_scroll_event(GtkWidget* widget, + GdkEventScroll* event, + gpointer data) +{ + float x = floorf(event->x); + float y = floorf(event->y); + float xoffset = floorf(event->delta_x); + float yoffset = floorf(event->delta_y); + send_scroll(xoffset, yoffset, x, y); + + return TRUE; +} + int device_init(const device_opts_t* p_opts, device_info_t* p_info, driver_data_t* p_data) @@ -134,14 +168,20 @@ int device_init(const device_opts_t* p_opts, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_ENTER_NOTIFY_MASK | GDK_KEY_PRESS_MASK | - GDK_KEY_RELEASE_MASK); + GDK_KEY_RELEASE_MASK | + GDK_LEAVE_NOTIFY_MASK | + GDK_SCROLL_MASK ); g_signal_connect(G_OBJECT(g_cairo_gtk.window), "motion-notify-event", G_CALLBACK(on_motion_event), NULL); g_signal_connect(G_OBJECT(g_cairo_gtk.window), "button-press-event", G_CALLBACK(on_button_event), NULL); g_signal_connect(G_OBJECT(g_cairo_gtk.window), "button-release-event", G_CALLBACK(on_button_event), NULL); g_signal_connect(G_OBJECT(g_cairo_gtk.window), "key-press-event", G_CALLBACK(on_key_event), NULL); g_signal_connect(G_OBJECT(g_cairo_gtk.window), "key-release-event", G_CALLBACK(on_key_event), NULL); + g_signal_connect(G_OBJECT(g_cairo_gtk.window), "enter-notify-event", G_CALLBACK(on_enter_leave_event), NULL); + g_signal_connect(G_OBJECT(g_cairo_gtk.window), "leave-notify-event", G_CALLBACK(on_enter_leave_event), NULL); + g_signal_connect(G_OBJECT(g_cairo_gtk.window), "scroll-event", G_CALLBACK(on_scroll_event), NULL); GtkDrawingArea* drawing_area = (GtkDrawingArea*)gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(g_cairo_gtk.window), (GtkWidget*)drawing_area); @@ -203,10 +243,33 @@ void device_end_render(driver_data_t* p_data) g_idle_add((GSourceFunc)gtk_widget_queue_draw, (void*)g_cairo_gtk.window); } +void glib_print(const gchar* string) +{ + log_info("glib: %s", string); +} + +void glib_error(const gchar* string) +{ + log_error("glib: %s", string); +} + +void scenic_cmd_lock() +{ + g_mutex_lock(&g_cairo_gtk.cmd_mutex); +} + +void scenic_cmd_unlock() +{ + g_mutex_unlock(&g_cairo_gtk.cmd_mutex); +} + void device_loop(driver_data_t* p_data) { g_cairo_gtk.main = g_thread_new("scenic_loop", scenic_loop, p_data); + g_set_print_handler(glib_print); + g_set_printerr_handler(glib_error); + gtk_widget_show_all((GtkWidget*)g_cairo_gtk.window); gtk_main(); } diff --git a/c_src/scenic/comms.c b/c_src/scenic/comms.c index 6dc5801..7cef107 100644 --- a/c_src/scenic/comms.c +++ b/c_src/scenic/comms.c @@ -37,7 +37,6 @@ The caller will typically be erlang, so use the 2-byte length indicator extern device_info_t g_device_info; - //============================================================================= // raw comms with host app // from erl_comm.c @@ -45,14 +44,17 @@ extern device_info_t g_device_info; //--------------------------------------------------------- // the length indicator from erlang is always big-endian -int write_cmd(uint8_t* buf, unsigned int len) +int write_cmd(uint8_t* buf, uint32_t len) { int written = 0; uint32_t cmd_len = len; cmd_len = hton_ui32(cmd_len); + + scenic_cmd_lock(); write_exact((uint8_t*) &cmd_len, sizeof(uint32_t)); written = write_exact(buf, len); + scenic_cmd_unlock(); return written; } @@ -89,9 +91,11 @@ void logv(uint32_t cmd, const char* msg, va_list args) uint32_t msg_len = vasprintf(&output, msg, args); uint32_t cmd_len = ntoh_ui32(msg_len + sizeof(uint32_t)); + scenic_cmd_lock(); write_exact((uint8_t*) &cmd_len, sizeof(uint32_t)); write_exact((uint8_t*) &cmd, sizeof(uint32_t)); write_exact((uint8_t*) output, msg_len); + scenic_cmd_unlock(); free(output); } @@ -163,9 +167,11 @@ void send_write(const char* msg) cmd_len = ntoh_ui32(cmd_len); + scenic_cmd_lock(); write_exact((uint8_t*) &cmd_len, sizeof(uint32_t)); write_exact((uint8_t*) &cmd, sizeof(uint32_t)); write_exact((uint8_t*) msg, msg_len); + scenic_cmd_unlock(); } //--------------------------------------------------------- @@ -176,9 +182,11 @@ void send_inspect(void* data, int length) ntoh_ui32(cmd_len); + scenic_cmd_lock(); write_exact((uint8_t*) &cmd_len, sizeof(uint32_t)); write_exact((uint8_t*) &cmd, sizeof(uint32_t)); write_exact(data, length); + scenic_cmd_unlock(); } //--------------------------------------------------------- @@ -190,9 +198,11 @@ void send_static_texture_miss(const char* key) ntoh_ui32(cmd_len); + scenic_cmd_lock(); write_exact((uint8_t*) &cmd_len, sizeof(uint32_t)); write_exact((uint8_t*) &cmd, sizeof(uint32_t)); write_exact((uint8_t*) key, msg_len); + scenic_cmd_unlock(); } //--------------------------------------------------------- @@ -204,9 +214,11 @@ void send_dynamic_texture_miss(const char* key) ntoh_ui32(cmd_len); + scenic_cmd_lock(); write_exact((uint8_t*) &cmd_len, sizeof(uint32_t)); write_exact((uint8_t*) &cmd, sizeof(uint32_t)); write_exact((uint8_t*) key, msg_len); + scenic_cmd_unlock(); } //--------------------------------------------------------- @@ -218,9 +230,11 @@ void send_font_miss(const char* key) ntoh_ui32(cmd_len); + scenic_cmd_lock(); write_exact((uint8_t*) &cmd_len, sizeof(uint32_t)); write_exact((uint8_t*) &cmd, sizeof(uint32_t)); write_exact((uint8_t*) key, msg_len); + scenic_cmd_unlock(); } //--------------------------------------------------------- diff --git a/c_src/scenic/scenic_ops.c b/c_src/scenic/scenic_ops.c index 3cc44e4..6413e01 100644 --- a/c_src/scenic/scenic_ops.c +++ b/c_src/scenic/scenic_ops.c @@ -192,3 +192,8 @@ void* scenic_loop(void* user_data) return NULL; } +__attribute__((weak)) +void scenic_cmd_lock() { } + +__attribute__((weak)) +void scenic_cmd_unlock() { } diff --git a/c_src/scenic/scenic_ops.h b/c_src/scenic/scenic_ops.h index d613336..b2a8573 100644 --- a/c_src/scenic/scenic_ops.h +++ b/c_src/scenic/scenic_ops.h @@ -55,4 +55,7 @@ void scenic_ops_put_image(uint32_t* p_msg_length, driver_data_t* p_data); void scenic_ops_crash(); void dispatch_scenic_ops(uint32_t msg_length, driver_data_t* p_data); -void* scenic_loop(void* user_data); \ No newline at end of file +void* scenic_loop(void* user_data); + +void scenic_cmd_lock(); +void scenic_cmd_unlock();