diff --git a/src/dulcepan.h b/src/dulcepan.h index 5530317..ce69412 100644 --- a/src/dulcepan.h +++ b/src/dulcepan.h @@ -92,7 +92,7 @@ struct dp_seat { // The output the pointer is on struct dp_output *ptr_output; // In buffer space - int ptr_x, ptr_y; + double ptr_x, ptr_y; struct wl_list link; }; @@ -114,15 +114,15 @@ enum dp_resize_edges { struct dp_selection { struct dp_output *output; // May be NULL - int x, y, width, height; + double x, y, width, height; enum dp_selection_action action; bool action_active; // Pointer offset to apply during movement - int ptr_off_x, ptr_off_y; + double ptr_off_x, ptr_off_y; int resize_edges; // Resize anchor - int resize_x, resize_y; + double resize_x, resize_y; }; enum dp_file_format { @@ -213,12 +213,12 @@ void dp_output_hide_surface(struct dp_output *output); void dp_seat_create(struct dp_state *state, uint32_t name, struct wl_seat *wl_seat); void dp_seat_destroy(struct dp_seat *seat); -void dp_select_start_interactive(struct dp_selection *selection, struct dp_output *output, int x, - int y, bool modify_existing); +void dp_select_start_interactive(struct dp_selection *selection, struct dp_output *output, double x, + double y, bool modify_existing); void dp_select_stop_interactive(struct dp_selection *selection); void dp_select_notify_pointer_position( - struct dp_selection *selection, struct dp_output *output, int x, int y); + struct dp_selection *selection, struct dp_output *output, double x, double y); void dp_select_whole(struct dp_selection *selection, struct dp_output *output); diff --git a/src/output.c b/src/output.c index 6932752..e873945 100644 --- a/src/output.c +++ b/src/output.c @@ -272,8 +272,8 @@ static inline uint32_t get_time_msec(void) { return (uint32_t)(now.tv_sec * 1000 + now.tv_nsec / 1000000); } -static void setup_linear_gradient(cairo_t *cairo, struct dp_state *state) { - struct dp_selection *selection = &state->selection; +static void setup_linear_gradient( + cairo_t *cairo, struct dp_state *state, double x, double y, double width, double height) { struct dp_config *config = &state->config; cairo_matrix_t matrix; @@ -285,25 +285,25 @@ static void setup_linear_gradient(cairo_t *cairo, struct dp_state *state) { matrix = state->precomputed_linear_matrix; } - cairo_matrix_scale(&matrix, 1.0 / selection->width, 1.0 / selection->height); - cairo_matrix_translate(&matrix, -selection->x, -selection->y); + cairo_matrix_scale(&matrix, 1.0 / width, 1.0 / height); + cairo_matrix_translate(&matrix, -x, -y); cairo_pattern_set_matrix(state->border_pattern, &matrix); cairo_set_source(cairo, state->border_pattern); } -static void setup_loop_gradient(cairo_t *cairo, struct dp_state *state) { +static void setup_loop_gradient( + cairo_t *cairo, struct dp_state *state, double x, double y, double width, double height) { struct dp_selection *selection = &state->selection; struct dp_config *config = &state->config; - double scale = state->loop_step_scale / selection->output->scale; - - double offset = - (selection->x + selection->y + (selection->width + selection->height) / 2.0) * scale; + double offset = (x + y + (width + height) / 2.0) * state->loop_step_scale; if (config->animation_duration != 0) { - offset += (double)get_time_msec() * state->time_multiplier / selection->output->scale; + offset += (double)get_time_msec() * state->time_multiplier; } + double scale = state->loop_step_scale / selection->output->scale; + cairo_matrix_t matrix; cairo_matrix_init(&matrix, scale, 0, 0, scale, fmod(offset, 2.0), 0); @@ -345,31 +345,34 @@ static void redraw(struct dp_output *output) { cairo_paint(buffer->cairo); if (output == selection->output) { + double scale = output->scale; + double x = selection->x * scale, y = selection->y * scale; + double width = selection->width * scale, height = selection->height * scale; + int border_size = config->border_size; - if (border_size != 0 && selection->width != 0 && selection->height != 0) { - double scaled_size = border_size * output->scale; + if (border_size != 0 && width != 0 && height != 0) { + double scaled_size = border_size * scale; cairo_set_line_width(buffer->cairo, scaled_size); double off = scaled_size / 2.0; - cairo_rectangle(buffer->cairo, selection->x - off, selection->y - off, - selection->width + scaled_size, selection->height + scaled_size); + cairo_rectangle( + buffer->cairo, x - off, y - off, width + scaled_size, height + scaled_size); switch (config->border_gradient) { case DP_BORDER_GRADIENT_NONE: set_cairo_color(buffer->cairo, config->border_color); break; case DP_BORDER_GRADIENT_LINEAR: - setup_linear_gradient(buffer->cairo, state); + setup_linear_gradient(buffer->cairo, state, x, y, width, height); break; case DP_BORDER_GRADIENT_LOOP: - setup_loop_gradient(buffer->cairo, state); + setup_loop_gradient(buffer->cairo, state, x, y, width, height); break; } cairo_stroke(buffer->cairo); } - cairo_rectangle( - buffer->cairo, selection->x, selection->y, selection->width, selection->height); + cairo_rectangle(buffer->cairo, x, y, width, height); set_cairo_color(buffer->cairo, config->selected_color); cairo_fill(buffer->cairo); diff --git a/src/persistent.c b/src/persistent.c index d2b838d..8706f6d 100644 --- a/src/persistent.c +++ b/src/persistent.c @@ -28,7 +28,7 @@ void dp_persistent_load(struct dp_state *state) { } char name[32]; - int x, y, width, height; + double x, y, width, height; int n_read = 0; fgets(name, sizeof(name), fp); @@ -36,7 +36,7 @@ void dp_persistent_load(struct dp_state *state) { if (name[name_len - 1] == '\n') { name[--name_len] = '\0'; } - n_read += fscanf(fp, "%d %d %d %d", &x, &y, &width, &height); + n_read += fscanf(fp, "%lf %lf %lf %lf", &x, &y, &width, &height); bool ok = ferror(fp) == 0 && n_read == 4; fclose(fp); @@ -61,8 +61,8 @@ void dp_persistent_load(struct dp_state *state) { return; } - if (x < 0 || y < 0 || x + width > selection_output->transformed_width || - y + height > selection_output->transformed_height) { + if (x < 0 || y < 0 || x + width > selection_output->effective_width || + y + height > selection_output->effective_height) { dp_log_error("Persistent state: invalid selection geometry", name); return; } @@ -84,7 +84,7 @@ void dp_persistent_save(struct dp_state *state) { } else { fprintf(fp, "%s\n" - "%d %d %d %d\n", + "%lf %lf %lf %lf\n", selection->output->name, selection->x, selection->y, selection->width, selection->height); fclose(fp); diff --git a/src/save.c b/src/save.c index 08102cd..adf21ca 100644 --- a/src/save.c +++ b/src/save.c @@ -140,10 +140,15 @@ void dp_save(struct dp_state *state) { pixman_image_set_transform(frame_image, &frame_transform); - pixman_image_t *out_image = - pixman_image_create_bits(PIXMAN_a8b8g8r8, selection->width, selection->height, NULL, 0); - pixman_image_composite32(PIXMAN_OP_SRC, frame_image, NULL, out_image, selection->x, - selection->y, 0, 0, 0, 0, selection->width, selection->height); + double scale = output->scale; + + int x = (int)round(selection->x * scale), y = (int)round(selection->y * scale); + int width = (int)round(selection->width * scale), + height = (int)round(selection->height * scale); + + pixman_image_t *out_image = pixman_image_create_bits(PIXMAN_a8b8g8r8, width, height, NULL, 0); + pixman_image_composite32( + PIXMAN_OP_SRC, frame_image, NULL, out_image, x, y, 0, 0, 0, 0, width, height); pixman_image_unref(frame_image); FILE *fp = NULL; @@ -160,11 +165,10 @@ void dp_save(struct dp_state *state) { case DP_FILE_UNKNOWN: abort(); // Unreachable case DP_FILE_PNG: - write_png( - fp, out_image, selection->width, selection->height, state->config.png_compression); + write_png(fp, out_image, width, height, state->config.png_compression); break; case DP_FILE_PPM: - write_ppm(fp, out_image, selection->width, selection->height); + write_ppm(fp, out_image, width, height); break; } diff --git a/src/seat.c b/src/seat.c index d5a2d28..1cafad4 100644 --- a/src/seat.c +++ b/src/seat.c @@ -111,9 +111,10 @@ static enum wp_cursor_shape_device_v1_shape get_cursor_shape(struct dp_selection } break; case DP_SELECTION_ACTION_MOVING: + // XXX: this might have rounding issues but whatever if (selection->x == 0 && selection->y == 0 && - selection->width == selection->output->width && - selection->height == selection->output->height) { + selection->width == selection->output->effective_width && + selection->height == selection->output->effective_height) { // Moving is impossible return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT; } @@ -129,10 +130,8 @@ static void update_cursor(struct dp_seat *seat, uint32_t serial) { static void process_position(struct dp_seat *seat, wl_fixed_t x, wl_fixed_t y, uint32_t serial) { struct dp_output *output = seat->ptr_output; - seat->ptr_x = - (int)(wl_fixed_to_double(x) * output->transformed_width / output->effective_width); - seat->ptr_y = - (int)(wl_fixed_to_double(y) * output->transformed_height / output->effective_height); + seat->ptr_x = wl_fixed_to_double(x); + seat->ptr_y = wl_fixed_to_double(y); dp_select_notify_pointer_position(&seat->state->selection, output, seat->ptr_x, seat->ptr_y); update_cursor(seat, serial); } diff --git a/src/select.c b/src/select.c index e5c8829..ffd0dd0 100644 --- a/src/select.c +++ b/src/select.c @@ -20,31 +20,30 @@ static void set_selected_output(struct dp_selection *selection, struct dp_output } } -static void update_action(struct dp_selection *selection, struct dp_output *output, int x, int y) { +static void update_action( + struct dp_selection *selection, struct dp_output *output, double x, double y) { if (output == selection->output) { - int sx = x - selection->x; - int sy = y - selection->y; + double sx = x - selection->x; + double sy = y - selection->y; - int inner = (int)ceil(RESIZE_INNER_SIZE * output->scale); - int outer = (int)ceil(RESIZE_OUTER_SIZE * output->scale); - int threshold = (int)ceil(RESIZE_THRESHOLD * output->scale); - - if (sx >= inner && sy >= inner && sx < selection->width - inner && - sy <= selection->height - inner) { + if (sx >= RESIZE_INNER_SIZE && sy >= RESIZE_INNER_SIZE && + sx < selection->width - RESIZE_INNER_SIZE && + sy <= selection->height - RESIZE_INNER_SIZE) { selection->action = DP_SELECTION_ACTION_MOVING; return; - } else if (sx >= -outer && sy >= -outer && sx < selection->width + outer && - sy < selection->height + outer) { + } else if (sx >= -RESIZE_OUTER_SIZE && sy >= -RESIZE_OUTER_SIZE && + sx < selection->width + RESIZE_OUTER_SIZE && + sy < selection->height + RESIZE_OUTER_SIZE) { int edges = DP_EDGE_NONE; - if (sx >= selection->width - threshold && sx >= selection->width / 2) { + if (sx >= selection->width - RESIZE_THRESHOLD && sx >= selection->width / 2) { edges |= DP_EDGE_RIGHT; - } else if (sx < threshold) { + } else if (sx < RESIZE_THRESHOLD) { edges |= DP_EDGE_LEFT; } - if (sy >= selection->height - threshold && sy >= selection->height / 2) { + if (sy >= selection->height - RESIZE_THRESHOLD && sy >= selection->height / 2) { edges |= DP_EDGE_BOTTOM; - } else if (sy < threshold) { + } else if (sy < RESIZE_THRESHOLD) { edges |= DP_EDGE_TOP; } @@ -59,20 +58,20 @@ static void update_action(struct dp_selection *selection, struct dp_output *outp selection->action = DP_SELECTION_ACTION_NONE; } -static void do_resize(struct dp_selection *selection, int x, int y) { - int ptr_x = x - selection->ptr_off_x, ptr_y = y - selection->ptr_off_y; +static void do_resize(struct dp_selection *selection, double x, double y) { + double ptr_x = x - selection->ptr_off_x, ptr_y = y - selection->ptr_off_y; if (ptr_x < 0) { ptr_x = 0; - } else if (ptr_x > selection->output->transformed_width) { - ptr_x = selection->output->transformed_width; + } else if (ptr_x > selection->output->effective_width) { + ptr_x = selection->output->effective_width; } if (ptr_y < 0) { ptr_y = 0; - } else if (ptr_y > selection->output->transformed_height) { - ptr_y = selection->output->transformed_height; + } else if (ptr_y > selection->output->effective_height) { + ptr_y = selection->output->effective_height; } - int width = selection->width, height = selection->height; + double width = selection->width, height = selection->height; retry_horiz: if ((selection->resize_edges & DP_EDGE_LEFT) != 0) { @@ -117,18 +116,18 @@ retry_verti: dp_output_redraw(selection->output); } -static void do_move(struct dp_selection *selection, int x, int y) { - int new_x = x - selection->ptr_off_x, new_y = y - selection->ptr_off_y; +static void do_move(struct dp_selection *selection, double x, double y) { + double new_x = x - selection->ptr_off_x, new_y = y - selection->ptr_off_y; if (new_x < 0) { new_x = 0; - } else if (new_x > selection->output->transformed_width - selection->width) { - new_x = selection->output->transformed_width - selection->width; + } else if (new_x > selection->output->effective_width - selection->width) { + new_x = selection->output->effective_width - selection->width; } if (new_y < 0) { new_y = 0; - } else if (new_y > selection->output->transformed_height - selection->height) { - new_y = selection->output->transformed_height - selection->height; + } else if (new_y > selection->output->effective_height - selection->height) { + new_y = selection->output->effective_height - selection->height; } if (new_x == selection->x && new_y == selection->y) { @@ -140,7 +139,7 @@ static void do_move(struct dp_selection *selection, int x, int y) { dp_output_redraw(selection->output); } -static void init_resize(struct dp_selection *selection, int x, int y) { +static void init_resize(struct dp_selection *selection, double x, double y) { if ((selection->resize_edges & DP_EDGE_RIGHT) != 0) { selection->ptr_off_x = x - selection->x - selection->width; selection->resize_x = selection->x; @@ -157,8 +156,8 @@ static void init_resize(struct dp_selection *selection, int x, int y) { } } -void dp_select_start_interactive(struct dp_selection *selection, struct dp_output *output, int x, - int y, bool modify_existing) { +void dp_select_start_interactive(struct dp_selection *selection, struct dp_output *output, double x, + double y, bool modify_existing) { update_action(selection, output, x, y); selection->action_active = true; @@ -195,7 +194,7 @@ void dp_select_stop_interactive(struct dp_selection *selection) { } void dp_select_notify_pointer_position( - struct dp_selection *selection, struct dp_output *output, int x, int y) { + struct dp_selection *selection, struct dp_output *output, double x, double y) { if (selection->action_active) { switch (selection->action) { case DP_SELECTION_ACTION_NONE: @@ -217,8 +216,8 @@ void dp_select_whole(struct dp_selection *selection, struct dp_output *output) { selection->x = 0; selection->y = 0; - selection->width = output->transformed_width; - selection->height = output->transformed_height; + selection->width = output->effective_width; + selection->height = output->effective_height; dp_output_redraw(output); }