[PATCH weston v4 19/20] clients/clickdot: Add option for using a more complex confine region
Jonas Ådahl
jadahl at gmail.com
Tue Nov 17 02:11:05 PST 2015
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 <jadahl at gmail.com>
---
clients/clickdot.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 133 insertions(+)
diff --git a/clients/clickdot.c b/clients/clickdot.c
index 130a166..5054a68 100644
--- a/clients/clickdot.c
+++ b/clients/clickdot.c
@@ -43,6 +43,11 @@
#include "window.h"
#include "shared/helpers.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;
@@ -67,6 +72,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
@@ -145,6 +154,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;
@@ -167,6 +262,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);
@@ -220,6 +319,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,
@@ -283,6 +389,9 @@ resize_handler(struct widget *widget,
struct clickdot *clickdot = data;
clickdot->reset = 1;
+
+ if (clickdot->complex_confine_region_enabled)
+ clickdot->complex_confine_region_dirty = true;
}
static void
@@ -374,12 +483,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");
@@ -388,6 +516,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.4.3
More information about the wayland-devel
mailing list