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"));  } | 
