diff options
Diffstat (limited to 'src/common/backend.c')
| -rw-r--r-- | src/common/backend.c | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/src/common/backend.c b/src/common/backend.c index ccb9c27..23275d6 100644 --- a/src/common/backend.c +++ b/src/common/backend.c @@ -81,10 +81,18 @@ uint32_t yasl_display_caps(const struct yasl_display *d) int yasl_display_dispatch(struct yasl_display *d, int timeout_ms) { - if (!d) return -1; - if (d->ops->display_dispatch_timeout) - return d->ops->display_dispatch_timeout(d, timeout_ms); - return -1; + if (!d) { + errno = EINVAL; + return -1; + } + if (!d->ops->display_dispatch_timeout) { + errno = ENOTSUP; + return -1; + } + errno = 0; + int result = d->ops->display_dispatch_timeout(d, timeout_ms); + if (result < 0 && !errno) errno = EIO; + return result; } void yasl_display_flush(struct yasl_display *d) @@ -127,7 +135,12 @@ bool yasl_display_drag_start(struct yasl_display *d, struct yasl_surface *origin return 0; if (!origin || origin->display != d) return false; - return d->ops->display_drag_start(d, origin, image, l, ud); + 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)) + return false; + const struct yasl_drag_listener empty = {0}; + return d->ops->display_drag_start(d, origin, image, l ? l : &empty, ud); } void yasl_display_drag_cancel(struct yasl_display *d) @@ -151,7 +164,10 @@ struct yasl_surface *yasl_create_toplevel(struct yasl_display *d, errno = ENOTSUP; return NULL; } - return d->ops->surface_create_toplevel(d, spec, graphics_device); + errno = 0; + struct yasl_surface *s = d->ops->surface_create_toplevel(d, spec, graphics_device); + if (!s && !errno) errno = ENODEV; + return s; } struct yasl_surface *yasl_surface_create_toplevel(struct yasl_display *d, @@ -160,18 +176,50 @@ struct yasl_surface *yasl_surface_create_toplevel(struct yasl_display *d, return yasl_create_toplevel(d, spec, NULL); } +static bool popup_spec_valid(const struct yasl_popup_spec *spec) +{ + return spec && spec->size.x > 0 && spec->size.y > 0 && + spec->size.x <= 32767 && spec->size.y <= 32767 && + (int64_t)spec->size.x * spec->size.y * 4 <= INT32_MAX && + spec->anchor.width >= 0 && spec->anchor.height >= 0 && + spec->content_offset.x >= 0 && spec->content_offset.y >= 0 && + spec->content_size.x >= 0 && spec->content_size.y >= 0 && + (int64_t)spec->content_offset.x + spec->content_size.x <= spec->size.x && + (int64_t)spec->content_offset.y + spec->content_size.y <= spec->size.y; +} + struct yasl_surface *yasl_surface_create_popup(struct yasl_surface *parent, const struct yasl_popup_spec *spec) { - if (!parent || !parent->display->ops->surface_create_popup) - return 0; - return parent->display->ops->surface_create_popup(parent, spec); + if (!parent || !popup_spec_valid(spec)) { + errno = EINVAL; + return NULL; + } + if (!(yasl_display_caps(parent->display) & YASL_CAP_POPUPS) || + !parent->display->ops->surface_create_popup) { + errno = ENOTSUP; + return NULL; + } + errno = 0; + struct yasl_surface *s = parent->display->ops->surface_create_popup(parent, spec); + if (!s && !errno) errno = ENODEV; + return s; } bool yasl_surface_popup_reposition(struct yasl_surface *popup, const struct yasl_popup_spec *spec) { - if (!popup || !popup->display->ops->surface_popup_reposition) - return 0; - return popup->display->ops->surface_popup_reposition(popup, spec); + if (!popup || !popup_spec_valid(spec)) { + errno = EINVAL; + return false; + } + if (!(yasl_display_caps(popup->display) & YASL_CAP_POPUPS) || + !popup->display->ops->surface_popup_reposition) { + errno = ENOTSUP; + return false; + } + errno = 0; + bool result = popup->display->ops->surface_popup_reposition(popup, spec); + if (!result && !errno) errno = ENODEV; + return result; } void yasl_surface_destroy(struct yasl_surface *s) |
