summaryrefslogtreecommitdiff
path: root/rcm-client-receive.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2015-07-14 14:50:25 +0200
committerDavid Härdeman <david@hardeman.nu>2015-07-14 14:50:25 +0200
commit071cc70f0586e7296ed22baafb67149f76e6620a (patch)
tree0146c78213982e03f6d281531c2ee923bbddb9a4 /rcm-client-receive.c
parent165ba73d1ee88661cac144cda605e1d18d6f5928 (diff)
Change remote to use GtkButtons
Diffstat (limited to 'rcm-client-receive.c')
-rw-r--r--rcm-client-receive.c435
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"));
}