By passing --complex-confine-region clickdot will draw an area looking like a strange H in half transparent gray. This region will act as the confine region when pointer confinement is activated (by right clicking).
Signed-off-by: Jonas Ådahl <jad...@gmail.com> --- clients/clickdot.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/clients/clickdot.c b/clients/clickdot.c index f20581f..bf5169e 100644 --- a/clients/clickdot.c +++ b/clients/clickdot.c @@ -41,6 +41,11 @@ #include "window.h" +#define NUM_COMPLEX_REGION_RECTS 9 + +static int32_t option_complex_confine_region; +static int32_t option_help; + struct clickdot { struct display *display; struct window *window; @@ -65,6 +70,10 @@ struct clickdot { struct task cursor_timeout_task; bool pointer_confined; + + bool complex_confine_region_enabled; + bool complex_confine_region_dirty; + struct rectangle complex_confine_region[NUM_COMPLEX_REGION_RECTS]; }; static void @@ -143,6 +152,92 @@ draw_line(struct clickdot *clickdot, cairo_t *cr, } static void +calculate_complex_confine_region(struct clickdot *clickdot) +{ + struct rectangle allocation; + struct rectangle *rs = clickdot->complex_confine_region; + + if (!clickdot->complex_confine_region_dirty) + return; + + widget_get_allocation(clickdot->widget, &allocation); + + /* + * The code below constructs a region made up of rectangles that + * is then used to set up both an illustrative shaded region in the + * widget and a confine region used when confining the pointer. + */ + + rs[0].x = allocation.x + (int)round(allocation.width * 0.05); + rs[0].y = allocation.y + (int)round(allocation.height * 0.15); + rs[0].width = (int)round(allocation.width * 0.35); + rs[0].height = (int)round(allocation.height * 0.7); + + rs[1].x = rs[0].x + rs[0].width; + rs[1].y = allocation.y + (int)round(allocation.height * 0.45); + rs[1].width = (int)round(allocation.width * 0.09); + rs[1].height = (int)round(allocation.height * 0.1); + + rs[2].x = rs[1].x + rs[1].width; + rs[2].y = allocation.y + (int)round(allocation.height * 0.48); + rs[2].width = (int)round(allocation.width * 0.02); + rs[2].height = (int)round(allocation.height * 0.04); + + rs[3].x = rs[2].x + rs[2].width; + rs[3].y = allocation.y + (int)round(allocation.height * 0.45); + rs[3].width = (int)round(allocation.width * 0.09); + rs[3].height = (int)round(allocation.height * 0.1); + + rs[4].x = rs[3].x + rs[3].width; + rs[4].y = allocation.y + (int)round(allocation.height * 0.15); + rs[4].width = (int)round(allocation.width * 0.35); + rs[4].height = (int)round(allocation.height * 0.7); + + rs[5].x = allocation.x + (int)round(allocation.width * 0.05); + rs[5].y = allocation.y + (int)round(allocation.height * 0.05); + rs[5].width = rs[0].width + rs[1].width + rs[2].width + + rs[3].width + rs[4].width; + rs[5].height = (int)round(allocation.height * 0.10); + + rs[6].x = allocation.x + (int)round(allocation.width * 0.1); + rs[6].y = rs[4].y + rs[4].height + (int)round(allocation.height * 0.02); + rs[6].width = (int)round(allocation.width * 0.8); + rs[6].height = (int)round(allocation.height * 0.03); + + rs[7].x = allocation.x + (int)round(allocation.width * 0.05); + rs[7].y = rs[6].y + rs[6].height; + rs[7].width = (int)round(allocation.width * 0.9); + rs[7].height = (int)round(allocation.height * 0.03); + + rs[8].x = allocation.x + (int)round(allocation.width * 0.1); + rs[8].y = rs[7].y + rs[7].height; + rs[8].width = (int)round(allocation.width * 0.8); + rs[8].height = (int)round(allocation.height * 0.03); + + clickdot->complex_confine_region_dirty = false; +} + +static void +draw_complex_confine_region_mask(struct clickdot *clickdot, cairo_t *cr) +{ + int i; + + calculate_complex_confine_region(clickdot); + + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + + for (i = 0; i < NUM_COMPLEX_REGION_RECTS; i++) { + cairo_rectangle(cr, + clickdot->complex_confine_region[i].x, + clickdot->complex_confine_region[i].y, + clickdot->complex_confine_region[i].width, + clickdot->complex_confine_region[i].height); + cairo_set_source_rgba(cr, 0.14, 0.14, 0.14, 0.9); + cairo_fill(cr); + } +} + +static void redraw_handler(struct widget *widget, void *data) { static const double r = 10.0; @@ -165,6 +260,10 @@ redraw_handler(struct widget *widget, void *data) cairo_set_source_rgba(cr, 0, 0, 0, 0.8); cairo_fill(cr); + if (clickdot->complex_confine_region_enabled) { + draw_complex_confine_region_mask(clickdot, cr); + } + draw_line(clickdot, cr, &allocation); cairo_translate(cr, clickdot->dot.x + 0.5, clickdot->dot.y + 0.5); @@ -218,6 +317,13 @@ toggle_pointer_confine(struct clickdot *clickdot, struct input *input) { if (clickdot->pointer_confined) { window_unconfine_pointer(clickdot->window); + } else if (clickdot->complex_confine_region_enabled) { + calculate_complex_confine_region(clickdot); + window_confine_pointer_to_rectangles( + clickdot->window, + input, + clickdot->complex_confine_region, + NUM_COMPLEX_REGION_RECTS); } else { window_confine_pointer_to_widget(clickdot->window, clickdot->widget, @@ -281,6 +387,7 @@ resize_handler(struct widget *widget, struct clickdot *clickdot = data; clickdot->reset = 1; + clickdot->complex_confine_region_dirty = true; } static void @@ -372,12 +479,31 @@ clickdot_destroy(struct clickdot *clickdot) free(clickdot); } +static const struct weston_option clickdot_options[] = { + { WESTON_OPTION_BOOLEAN, "complex-confine-region", 0, &option_complex_confine_region }, + { WESTON_OPTION_BOOLEAN, "help", 0, &option_help }, +}; + +static void +print_help(const char *argv0) +{ + printf("Usage: %s [--complex-confine-region]\n", argv0); +} + int main(int argc, char *argv[]) { struct display *display; struct clickdot *clickdot; + if (parse_options(clickdot_options, + ARRAY_LENGTH(clickdot_options), + &argc, argv) > 1 || + option_help) { + print_help(argv[0]); + return 0; + } + display = display_create(&argc, argv); if (display == NULL) { fprintf(stderr, "failed to create display: %m\n"); @@ -386,6 +512,11 @@ main(int argc, char *argv[]) clickdot = clickdot_create(display); + if (option_complex_confine_region) { + clickdot->complex_confine_region_dirty = true; + clickdot->complex_confine_region_enabled = true; + } + display_run(display); clickdot_destroy(clickdot); -- 2.1.4 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel