diff options
Diffstat (limited to 'rcm-client-receive.c')
-rw-r--r-- | rcm-client-receive.c | 435 |
1 files changed, 103 insertions, 332 deletions
diff --git a/rcm-client-receive.c b/rcm-client-receive.c index 5ae1af3..9c1646d 100644 --- a/rcm-client-receive.c +++ b/rcm-client-receive.c @@ -10,6 +10,8 @@ #include "rcm-client-main.h" #include "rcm-client-receive.h" +#include "linux-input-keycodes.h" + #define WINDOW_WIDTH 300 #define WINDOW_HEIGHT 300 @@ -18,242 +20,26 @@ struct remote { GList *header_buttons; guint width; guint height; - struct rcbutton *hover; bool editing; }; struct rcbutton { char *name; - bool clicked; - guint x; - guint y; guint row; guint col; guint rows; guint cols; - guint width; - guint height; - guint padding; - guint corner_radius; + GtkWidget *button; struct rcbutton *next; - GdkRGBA *color; - void (*on_hover)(struct rcbutton *rcb, GtkWidget *widget, bool hover); }; static struct remote *remote = NULL; -static void -curve_rectangle(cairo_t * cr, gdouble x0, gdouble y0, - gdouble width, gdouble height, gdouble radius) -{ - gdouble x1, y1; - - if (!width || !height) - return; - - x1 = x0 + width; - y1 = y0 + height; - - radius = MIN (radius, MIN (width / 2, height / 2)); - - cairo_move_to (cr, x0, y0 + radius); - cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI, - 3 * M_PI / 2); - cairo_line_to (cr, x1 - radius, y0); - cairo_arc (cr, x1 - radius, y0 + radius, radius, 3 * M_PI / 2, - 2 * M_PI); - cairo_line_to (cr, x1, y1 - radius); - cairo_arc (cr, x1 - radius, y1 - radius, radius, 0, M_PI / 2); - cairo_line_to (cr, x0 + radius, y1); - cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI / 2, M_PI); - - cairo_close_path (cr); -} GdkRGBA *remote_background_color; GdkRGBA *remote_edit_background_color; GdkRGBA *cd; -GdkRGBA *cre; GdkRGBA *cb; -GdkRGBA cgreen; -GdkRGBA cred; - -static void -draw_curve_rectangle(cairo_t * cr, struct rcbutton *rcb) -{ - double tx, ty; - cairo_text_extents_t extents; - const char *label = rcb->name ? rcb->name : "?"; - - curve_rectangle(cr, rcb->x, rcb->y, - rcb->width, rcb->height, rcb->corner_radius); - - if (rcb->color) - gdk_cairo_set_source_rgba(cr, rcb->color); - else - gdk_cairo_set_source_rgba(cr, rcb->clicked ? cre : cd); - - cairo_fill_preserve(cr); - - gdk_cairo_set_source_rgba(cr, cb); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - /* - if (filled) - cairo_fill(cr); - else { - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - } - */ - - cairo_save(cr); - cairo_rectangle(cr, - rcb->x + rcb->padding, - rcb->y + rcb->padding, - rcb->width - rcb->padding * 2, - rcb->height - rcb->padding * 2); - cairo_clip(cr); - cairo_set_font_size(cr, 13); - cairo_text_extents (cr, label, &extents); - tx = rcb->x + (rcb->width / 2) - (extents.width / 2 + extents.x_bearing); - ty = rcb->y + (rcb->height / 2) - (extents.height / 2 + extents.y_bearing); - cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); - cairo_move_to(cr, tx, ty); - cairo_show_text(cr, label); - cairo_restore(cr); - cairo_new_sub_path(cr); -} - -#define SPACING 5 -#define PADDING 5 -#define BW 56 -#define BH 56 - -static gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data) -{ - struct rcbutton *rcb; - guint w = 0, h = 0; - - /* Set color for background */ - gdk_cairo_set_source_rgba(cr, remote->editing ? - remote_edit_background_color : - remote_background_color); - - /* fill in the background color*/ - cairo_paint(cr); - - GList *l; - - for (l = remote->buttons; l; l = l->next) { - rcb = l->data; - - draw_curve_rectangle(cr, rcb); - - if (rcb->x + rcb->width > w) - w = rcb->x + rcb->width; - - if (rcb->y + rcb->height > h) - h = rcb->y + rcb->height; - } - - w += (SPACING + BW) / 2; - h += (SPACING + BH) / 2; - - /*->name ? rcb->name : "?", false, - rcb->clicked ? cre : cd, - rcb->x, rcb->y, rcb->width, rcb->height, - rcb->padding, rcb->corner_radius); -*/ - gtk_widget_set_size_request(widget, w, h); - gtk_widget_set_halign(widget, GTK_ALIGN_CENTER); - gtk_widget_set_valign(widget, GTK_ALIGN_CENTER); - gtk_widget_set_margin_top(widget, BH / 2); - gtk_widget_set_margin_bottom(widget, BH / 2); - gtk_widget_set_margin_start(widget, BW / 2); - gtk_widget_set_margin_end(widget, BW / 2); - - - return FALSE; -} - -#if 0 -static struct rcbutton *new_button(const char *name, guint row, guint col) -{ - struct rcbutton *rcb; - - rcb = g_malloc(sizeof(*rcb)); - rcb->name = strdup(name); - rcb->clicked = false; - rcb->x = (SPACING + BW) * (col) + (SPACING + BW) / 2; - rcb->y = (SPACING + BH) * (row) + (SPACING + BH) / 2; - rcb->width = BW; - rcb->height = BH; - rcb->padding = PADDING; - rcb->corner_radius = 3; - rcb->color = NULL; - return rcb; -} -#endif - -static void -button_calculate_position(struct rcbutton *rcb) -{ - rcb->x = (SPACING + BW) * (rcb->col) + (SPACING + BW) / 2; - rcb->y = (SPACING + BH) * (rcb->row) + (SPACING + BH) / 2; - rcb->width = BW + (rcb->cols - 1) * (BW + SPACING); - rcb->height = BH + (rcb->rows - 1) * (BH + SPACING); -} - -static struct rcbutton * -new_button_add(const char *name, GdkRGBA *color, - guint x, guint y, guint w, guint h) -{ - struct rcbutton *rcb; - - rcb = g_malloc0(sizeof(*rcb)); - rcb->name = strdup(name); - rcb->clicked = false; - rcb->col = x; - rcb->row = y; - rcb->cols = w; - rcb->rows = h; - button_calculate_position(rcb); - rcb->padding = PADDING; - rcb->corner_radius = 3; - rcb->color = color; - remote->buttons = g_list_append(remote->buttons, rcb); - remote->width = MAX(remote->width, w); - remote->height = MAX(remote->height, h); - return rcb; -} - -#if 0 -static struct rcbutton *new_button_addr(const char *name, guint row, guint col) -{ - struct rcbutton *rcb; - - rcb = g_malloc(sizeof(*rcb)); - rcb->name = strdup(name); - rcb->clicked = false; - rcb->x = (SPACING + BW) / 2; - rcb->y = (SPACING + BH) / 2; - rcb->width = (SPACING + BW) * (col) - SPACING; - rcb->height = BH; - rcb->padding = PADDING; - rcb->corner_radius = 3; - rcb->color = &cred; - return rcb; -} -#endif -static void -button_redraw(struct rcbutton *rcb, GtkWidget *widget) -{ - printf("Asked to redraw: X,Y,W,H - %u,%u,%u,%u\n", - rcb->x - 1, rcb->y - 1, rcb->width + 2, rcb->height + 2); - gtk_widget_queue_draw_area(widget, rcb->x - 1, rcb->y - 1, - rcb->width + 2, rcb->height + 2); -} static void quick_message(GtkWindow *parent, gchar *message) @@ -271,110 +57,103 @@ quick_message(GtkWindow *parent, gchar *message) gtk_container_add(GTK_CONTAINER(content_area), label); gtk_widget_show_all(dialog); } - -static gboolean -button_press_event_cb(GtkWidget *widget, - GdkEventButton *event, - gpointer data) -{ - struct rcbutton *rcb; - GList *l; - - if (event->button != GDK_BUTTON_PRIMARY) - return true; - for (l = remote->buttons; l; l = l->next) { - rcb = l->data; - - if (event->x < rcb->x || event->x > (rcb->x + rcb->width)) - continue; +static void +button_press_event_cb(GtkButton *button, gpointer user_data) +{ + struct rcbutton *rcb = user_data; - if (event->y < rcb->y || event->y > (rcb->y + rcb->height)) - continue; + if (GTK_BUTTON(rcb->button) != button) + return; - if (remote->editing) { - printf("Button at %ux%u clicked in edit mode\n", rcb->x, rcb->y); - quick_message(GTK_WINDOW(gtk_widget_get_toplevel(widget)), "Edit button pressed"); - } else { - rcb->clicked = true; - button_redraw(rcb, widget); - printf("Button at %ux%u clicked\n", rcb->x, rcb->y); - poke_objects(); - } + if (remote->editing) { + printf("Button at %ux%u clicked in edit mode\n", rcb->col, rcb->row); + quick_message(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))), "Edit button pressed"); + } else { + printf("Button at %ux%u clicked\n", rcb->col, rcb->row); + poke_objects(); } - - return true; } -static gboolean -button_release_event_cb(GtkWidget *widget, - GdkEventButton *event, - gpointer data) -{ - struct rcbutton *rcb; - GList *l; - - if (event->button != GDK_BUTTON_PRIMARY) - return true; +#define REMOTE_BUTTON_WIDTH 64 +#define REMOTE_BUTTON_HEIGHT 64 +#define REMOTE_BUTTON_PADDING 2 +#define REMOTE_BUTTON_FONT_SIZE 15 - for (l = remote->buttons; l; l = l->next) { - rcb = l->data; +static GtkWidget * +create_button(const char *keycode) +{ + struct linux_input_keycode *lik; + cairo_surface_t *surface; + cairo_t *ct; + GtkWidget *button; + cairo_text_extents_t text_extents; + cairo_font_extents_t font_extents; + GtkWidget *img; + const char *label = keycode; + double x, y; + double scale_x, scale_y; + double scale = 1.0; + + for (lik = &linux_input_keycodes[0]; lik->name; lik++) + if (keycode && !strcmp(lik->name, keycode)) + break; + + if (!lik->name) { + printf("Unknown keycode! %s\n", keycode); + label = "<?>"; + } - if (!rcb->clicked) - continue; + if (lik->cs) + goto out; - rcb->clicked = false; + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + REMOTE_BUTTON_WIDTH, + REMOTE_BUTTON_HEIGHT); + ct = cairo_create(surface); + cairo_set_font_size(ct, REMOTE_BUTTON_FONT_SIZE); + cairo_text_extents(ct, label, &text_extents); + /* font extents so the vertial alignment is the same for all buttons */ + cairo_font_extents(ct, &font_extents); + scale_x = (REMOTE_BUTTON_WIDTH - REMOTE_BUTTON_PADDING * 2) / text_extents.width; + scale_y = (REMOTE_BUTTON_HEIGHT - REMOTE_BUTTON_PADDING * 2) / font_extents.height; + scale = scale_x < scale ? scale_x : scale; + scale = scale_y < scale ? scale_y : scale; + x = REMOTE_BUTTON_WIDTH / 2 - (text_extents.x_bearing + text_extents.width / 2.0) * scale; + y = REMOTE_BUTTON_HEIGHT / 2 - (font_extents.descent - font_extents.height / 2.0) * scale; + cairo_move_to(ct, x, y); + cairo_scale(ct, scale, scale); + cairo_set_source_rgb(ct, 0.1, 0.1, 0.1); + cairo_show_text(ct, label); + + cairo_destroy(ct); + lik->cs = surface; - button_redraw(rcb, widget); - } +out: + img = gtk_image_new_from_surface(lik->cs); + button = gtk_button_new(); + gtk_button_set_image(GTK_BUTTON(button), img); - return true; + return button; } -static gboolean -motion_notify_event_cb(GtkWidget *widget, - GdkEventMotion *event, - gpointer data) +static struct rcbutton * +new_button_add(GtkGrid *grid, const char *name, GdkRGBA *color, + guint x, guint y, guint w, guint h) { struct rcbutton *rcb; - static GdkCursor *cursor = NULL; - GdkWindow* win = gtk_widget_get_parent_window(widget); - GList *l; - - if (!cursor) - cursor = gdk_cursor_new_for_display(gdk_window_get_display(win), GDK_HAND1); - - for (l = remote->buttons; l; l = l->next) { - rcb = l->data; - - if (event->x < rcb->x || event->x > (rcb->x + rcb->width)) - continue; - - if (event->y < rcb->y || event->y > (rcb->y + rcb->height)) - continue; - break; - } - - if (!l) - rcb = NULL; - - if (remote->hover == rcb) - return true; - - gdk_window_set_cursor(win, rcb ? cursor : NULL); - - if (remote->hover && remote->hover->on_hover) { - remote->hover->on_hover(remote->hover, widget, false); - remote->hover = NULL; - } - - if (rcb && rcb->on_hover) { - rcb->on_hover(rcb, widget, true); - remote->hover = rcb; - } - - return true; + rcb = g_malloc0(sizeof(*rcb)); + rcb->name = strdup(name); + rcb->col = x; + rcb->row = y; + rcb->cols = w; + rcb->rows = h; + rcb->button = create_button(name); + g_signal_connect(rcb->button, "clicked", G_CALLBACK(button_press_event_cb), rcb); + remote->buttons = g_list_append(remote->buttons, rcb); + gtk_grid_attach(grid, rcb->button, x, y, w, h); + return rcb; } static GtkWidget *scrollda = NULL; @@ -388,7 +167,6 @@ void rcng_client_receive_destroy_ui() } static gint own_page_num = -1; -static GtkWidget *da; /* FIXME: These two functions should probably move to the core */ static void @@ -492,8 +270,6 @@ set_edit_keymap(bool editing) create_header_button("Resize", "document-page-setup", G_CALLBACK(resize_keymap), &remote); } else create_header_button("Edit", "list-add", G_CALLBACK(toggle_edit_keymap), &remote); - - gtk_widget_queue_draw(da); } static void @@ -573,24 +349,25 @@ void rcng_client_receive_init_ui(GDBusObject *new_hw) cd->green *= 0.7; cd->blue *= 0.7; - cre = gdk_rgba_copy(remote_background_color); - cre->red *= 2.0; - cb = gdk_rgba_copy(remote_background_color); cb->red = 0.0; cb->green = 0.0; cb->blue = 0.0; cb->alpha = 1.0; - gdk_rgba_parse(&cgreen, "#a9b68f"); - gdk_rgba_parse(&cred, "#cf8989"); - cred.alpha = 0.8; - n_items = g_variant_iter_init(&iter, km_entries); g_print("Key items: %zu\n", n_items); guint row = 0; guint col = 0; + GtkWidget *grid; + grid = gtk_grid_new(); + gtk_grid_set_column_spacing(GTK_GRID(grid), 12); + gtk_grid_set_row_spacing(GTK_GRID(grid), 12); + gtk_grid_set_column_homogeneous(GTK_GRID(grid), true); + gtk_grid_set_row_homogeneous(GTK_GRID(grid), true); + gtk_container_set_border_width(GTK_CONTAINER(grid), 12); + while (g_variant_iter_loop (&iter, "@a{sv}", &item)) { gchar *protocol; guint64 scancode; @@ -600,7 +377,7 @@ void rcng_client_receive_init_ui(GDBusObject *new_hw) g_variant_lookup(item, "scancode", "t", &scancode); g_variant_lookup(item, "keycode", "s", &keycode); - new_button_add(keycode, NULL, col, row, 1, 1); + new_button_add(GTK_GRID(grid), keycode, NULL, col, row, 1, 1); col++; if (col >= km_width) { @@ -611,25 +388,19 @@ void rcng_client_receive_init_ui(GDBusObject *new_hw) printf("Got a key: %s:0x%08" PRIx64 ":%s\n", protocol, scancode, keycode); } - da = gtk_drawing_area_new(); -// gtk_widget_set_size_request (da, WINDOW_WIDTH, WINDOW_HEIGHT); - g_signal_connect (da, "draw", G_CALLBACK(draw_cb), NULL); - - g_signal_connect(da, "button-press-event", - G_CALLBACK (button_press_event_cb), NULL); - - g_signal_connect(da, "button-release-event", - G_CALLBACK (button_release_event_cb), NULL); - - g_signal_connect(da, "motion-notify-event", - G_CALLBACK (motion_notify_event_cb), NULL); - - gtk_widget_set_events (da, gtk_widget_get_events (da) - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); scrollda = gtk_scrolled_window_new(NULL, NULL); - gtk_container_add(GTK_CONTAINER(scrollda), da); + GtkWidget *frame; + frame = gtk_frame_new(NULL); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gtk_widget_override_background_color(GTK_WIDGET(frame), GTK_STATE_FLAG_NORMAL, cd); + G_GNUC_END_IGNORE_DEPRECATIONS + gtk_container_set_border_width(GTK_CONTAINER(frame), 12); + gtk_container_add(GTK_CONTAINER(frame), grid); + + gtk_container_add(GTK_CONTAINER(scrollda), frame); gtk_widget_show_all(scrollda); own_page_num = gtk_notebook_append_page(global->notebook, scrollda, gtk_label_new("Receive")); } |