diff options
Diffstat (limited to 'src/common/backend.c')
| -rw-r--r-- | src/common/backend.c | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/src/common/backend.c b/src/common/backend.c index 939ec71..ad9e218 100644 --- a/src/common/backend.c +++ b/src/common/backend.c @@ -133,16 +133,21 @@ int yasl_private_display_double_click_ms(const struct yasl_private_display *d) bool yasl_private_display_drag_start(struct yasl_private_display *d, struct yasl_surface *origin, const struct yasl_private_drag_image *image, const struct yasl_private_drag_listener *l, void *ud) { - if (!d || !d->ops->display_drag_start) - return 0; - if (!origin || origin->display != d) - return false; + if (!d || !origin || origin->display != d) { errno = EINVAL; return false; } + if (!d->ops->display_drag_start) { errno = ENOTSUP; return false; } if (image && (!image->pixels || image->size.x <= 0 || image->size.y <= 0 || image->size.x > 32767 || image->size.y > 32767 || - (int64_t)image->size.x * image->size.y * 4 > INT32_MAX)) + (int64_t)image->size.x * image->size.y * 4 > INT32_MAX || + image->hotspot.x < 0 || image->hotspot.y < 0 || + image->hotspot.x >= image->size.x || image->hotspot.y >= image->size.y)) { + errno = EINVAL; return false; + } const struct yasl_private_drag_listener empty = {0}; - return d->ops->display_drag_start(d, origin, image, l ? l : &empty, ud); + errno = 0; + bool ok = d->ops->display_drag_start(d, origin, image, l ? l : &empty, ud); + if (!ok && !errno) errno = EIO; + return ok; } void yasl_private_display_drag_cancel(struct yasl_private_display *d) @@ -326,13 +331,18 @@ bool yasl_private_surface_read_pixels(struct yasl_surface *s, uint32_t *out, siz bool yasl_private_surface_set_pointer_mode(struct yasl_surface *s, enum yasl_private_pointer_mode mode) { - if (!s || (mode != YASL_PRIVATE_POINTER_NORMAL && mode != YASL_PRIVATE_POINTER_RELATIVE)) + if (!s || (mode != YASL_PRIVATE_POINTER_NORMAL && mode != YASL_PRIVATE_POINTER_RELATIVE)) { + errno = EINVAL; return false; + } if (mode == s->pointer_mode) return true; const struct yasl_private_backend_ops *ops = s->display ? s->display->ops : NULL; - if (!ops || !ops->surface_set_pointer_mode) - return mode == YASL_PRIVATE_POINTER_NORMAL; + if (!ops || !ops->surface_set_pointer_mode) { + if (mode == YASL_PRIVATE_POINTER_NORMAL) return true; + errno = ENOTSUP; + return false; + } if (!ops->surface_set_pointer_mode(s, mode)) return false; s->pointer_mode = mode; @@ -416,43 +426,48 @@ void yasl_private_surface_set_ime_caret(struct yasl_surface *s, struct yasl_priv s->display->ops->surface_set_ime_caret(s, caret); } +/* Backend operations that may be missing: ENOTSUP when absent, EIO when a backend + * fails without saying why. */ +#define OPTIONAL_OP(s, op, ...) \ + do { \ + if (!(s)) { errno = EINVAL; return false; } \ + if (!(s)->display->ops->op) { errno = ENOTSUP; return false; } \ + errno = 0; \ + bool ok_ = (s)->display->ops->op(__VA_ARGS__); \ + if (!ok_ && !errno) errno = EIO; \ + return ok_; \ + } while (0) + bool yasl_private_surface_start_interactive_move(struct yasl_surface *s) { - if (!s || !s->display->ops->surface_start_interactive_move) - return 0; - return s->display->ops->surface_start_interactive_move(s); + OPTIONAL_OP(s, surface_start_interactive_move, s); } bool yasl_private_surface_start_interactive_resize(struct yasl_surface *s, enum yasl_private_resize_edge edge) { - if (!s || !s->display->ops->surface_start_interactive_resize || - (edge != YASL_PRIVATE_EDGE_TOP && edge != YASL_PRIVATE_EDGE_BOTTOM && - edge != YASL_PRIVATE_EDGE_LEFT && edge != YASL_PRIVATE_EDGE_RIGHT && - edge != YASL_PRIVATE_EDGE_TOP_LEFT && edge != YASL_PRIVATE_EDGE_TOP_RIGHT && - edge != YASL_PRIVATE_EDGE_BOTTOM_LEFT && edge != YASL_PRIVATE_EDGE_BOTTOM_RIGHT)) - return 0; - return s->display->ops->surface_start_interactive_resize(s, edge); + if (edge != YASL_PRIVATE_EDGE_TOP && edge != YASL_PRIVATE_EDGE_BOTTOM && + edge != YASL_PRIVATE_EDGE_LEFT && edge != YASL_PRIVATE_EDGE_RIGHT && + edge != YASL_PRIVATE_EDGE_TOP_LEFT && edge != YASL_PRIVATE_EDGE_TOP_RIGHT && + edge != YASL_PRIVATE_EDGE_BOTTOM_LEFT && edge != YASL_PRIVATE_EDGE_BOTTOM_RIGHT) { + errno = EINVAL; + return false; + } + OPTIONAL_OP(s, surface_start_interactive_resize, s, edge); } bool yasl_private_surface_show_window_menu(struct yasl_surface *s, struct yasl_private_vector2i pos) { - if (!s || !s->display->ops->surface_show_window_menu) - return 0; - return s->display->ops->surface_show_window_menu(s, pos); + OPTIONAL_OP(s, surface_show_window_menu, s, pos); } bool yasl_private_surface_drag_carry(struct yasl_surface *s, struct yasl_private_vector2i offset) { - if (!s || !s->display->ops->surface_drag_carry) - return 0; - return s->display->ops->surface_drag_carry(s, offset); + OPTIONAL_OP(s, surface_drag_carry, s, offset); } bool yasl_private_surface_place_under_pointer(struct yasl_surface *s, struct yasl_private_vector2i at) { - if (!s || !s->display->ops->surface_place_under_pointer) - return 0; - return s->display->ops->surface_place_under_pointer(s, at); + OPTIONAL_OP(s, surface_place_under_pointer, s, at); } void yasl_private_surface_clear_timers(struct yasl_surface *s) |
