Fixed NULL pointer dereferences.
This commit is contained in:
parent
92befb0171
commit
ab733d76e5
@ -41,7 +41,8 @@
|
|||||||
#define TARGET_SEAT_INTERFACE 5
|
#define TARGET_SEAT_INTERFACE 5
|
||||||
#define TARGET_XDG_VERSION 5 /* The version of xdg-shell that we implement */
|
#define TARGET_XDG_VERSION 5 /* The version of xdg-shell that we implement */
|
||||||
|
|
||||||
static const char *event_names[] = {
|
static const char* event_names[] =
|
||||||
|
{
|
||||||
"new seat",
|
"new seat",
|
||||||
"removed seat",
|
"removed seat",
|
||||||
"new output",
|
"new output",
|
||||||
@ -64,17 +65,18 @@ static const char *event_names[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
bool uwac_default_error_handler(UwacDisplay *display, UwacReturnCode code, const char *msg, ...) {
|
bool uwac_default_error_handler(UwacDisplay* display, UwacReturnCode code, const char* msg, ...)
|
||||||
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, msg);
|
va_start(args, msg);
|
||||||
|
|
||||||
vfprintf(stderr, "%s", args);
|
vfprintf(stderr, "%s", args);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UwacErrorHandler uwacErrorHandler = uwac_default_error_handler;
|
UwacErrorHandler uwacErrorHandler = uwac_default_error_handler;
|
||||||
|
|
||||||
void UwacInstallErrorHandler(UwacErrorHandler handler) {
|
void UwacInstallErrorHandler(UwacErrorHandler handler)
|
||||||
|
{
|
||||||
if (handler)
|
if (handler)
|
||||||
uwacErrorHandler = handler;
|
uwacErrorHandler = handler;
|
||||||
else
|
else
|
||||||
@ -82,225 +84,274 @@ void UwacInstallErrorHandler(UwacErrorHandler handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void cb_shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
|
static void cb_shm_format(void* data, struct wl_shm* wl_shm, uint32_t format)
|
||||||
{
|
{
|
||||||
UwacDisplay *d = data;
|
UwacDisplay* d = data;
|
||||||
|
|
||||||
if (format == WL_SHM_FORMAT_RGB565)
|
if (format == WL_SHM_FORMAT_RGB565)
|
||||||
d->has_rgb565 = true;
|
d->has_rgb565 = true;
|
||||||
|
|
||||||
d->shm_formats_nb++;
|
d->shm_formats_nb++;
|
||||||
d->shm_formats = xrealloc((void *)d->shm_formats, sizeof(enum wl_shm_format) * d->shm_formats_nb);
|
d->shm_formats = xrealloc((void*)d->shm_formats, sizeof(enum wl_shm_format) * d->shm_formats_nb);
|
||||||
d->shm_formats[d->shm_formats_nb - 1] = format;
|
d->shm_formats[d->shm_formats_nb - 1] = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct wl_shm_listener shm_listener = {
|
struct wl_shm_listener shm_listener =
|
||||||
|
{
|
||||||
cb_shm_format
|
cb_shm_format
|
||||||
};
|
};
|
||||||
|
|
||||||
static void xdg_shell_ping(void *data, struct xdg_shell *shell, uint32_t serial)
|
static void xdg_shell_ping(void* data, struct xdg_shell* shell, uint32_t serial)
|
||||||
{
|
{
|
||||||
xdg_shell_pong(shell, serial);
|
xdg_shell_pong(shell, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_shell_listener xdg_shell_listener = {
|
static const struct xdg_shell_listener xdg_shell_listener =
|
||||||
|
{
|
||||||
xdg_shell_ping,
|
xdg_shell_ping,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BUILD_FULLSCREEN_SHELL
|
#ifdef BUILD_FULLSCREEN_SHELL
|
||||||
static void fullscreen_capability(void *data, struct _wl_fullscreen_shell *_wl_fullscreen_shell,
|
static void fullscreen_capability(void* data, struct _wl_fullscreen_shell* _wl_fullscreen_shell,
|
||||||
uint32_t capabilty)
|
uint32_t capabilty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct _wl_fullscreen_shell_listener fullscreen_shell_listener = {
|
static const struct _wl_fullscreen_shell_listener fullscreen_shell_listener =
|
||||||
|
{
|
||||||
fullscreen_capability,
|
fullscreen_capability,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static UwacSeat *display_destroy_seat(UwacDisplay *d, uint32_t name)
|
static UwacSeat* display_destroy_seat(UwacDisplay* d, uint32_t name)
|
||||||
{
|
{
|
||||||
UwacSeat *seat;
|
UwacSeat* seat;
|
||||||
|
wl_list_for_each(seat, &d->seats, link)
|
||||||
wl_list_for_each(seat, &d->seats, link) {
|
{
|
||||||
if (seat->seat_id == name) {
|
if (seat->seat_id == name)
|
||||||
|
{
|
||||||
UwacSeatDestroy(seat);
|
UwacSeatDestroy(seat);
|
||||||
return seat;
|
return seat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
|
static void registry_handle_global(void* data, struct wl_registry* registry, uint32_t id,
|
||||||
const char *interface, uint32_t version)
|
const char* interface, uint32_t version)
|
||||||
{
|
{
|
||||||
UwacDisplay *d = data;
|
UwacDisplay* d = data;
|
||||||
UwacGlobal *global;
|
UwacGlobal* global;
|
||||||
|
global = xmalloc(sizeof * global);
|
||||||
global = xmalloc(sizeof *global);
|
|
||||||
global->name = id;
|
global->name = id;
|
||||||
global->interface = xstrdup(interface);
|
global->interface = xstrdup(interface);
|
||||||
global->version = version;
|
global->version = version;
|
||||||
wl_list_insert(d->globals.prev, &global->link);
|
wl_list_insert(d->globals.prev, &global->link);
|
||||||
|
|
||||||
if (strcmp(interface, "wl_compositor") == 0) {
|
if (strcmp(interface, "wl_compositor") == 0)
|
||||||
d->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, min(TARGET_COMPOSITOR_INTERFACE, version));
|
{
|
||||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
d->compositor = wl_registry_bind(registry, id, &wl_compositor_interface,
|
||||||
|
min(TARGET_COMPOSITOR_INTERFACE, version));
|
||||||
|
}
|
||||||
|
else if (strcmp(interface, "wl_shm") == 0)
|
||||||
|
{
|
||||||
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, min(TARGET_SHM_INTERFACE, version));
|
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, min(TARGET_SHM_INTERFACE, version));
|
||||||
wl_shm_add_listener(d->shm, &shm_listener, d);
|
wl_shm_add_listener(d->shm, &shm_listener, d);
|
||||||
} else if (strcmp(interface, "wl_output") == 0) {
|
}
|
||||||
UwacOutput *output;
|
else if (strcmp(interface, "wl_output") == 0)
|
||||||
UwacOutputNewEvent *ev;
|
{
|
||||||
|
UwacOutput* output;
|
||||||
|
UwacOutputNewEvent* ev;
|
||||||
output = UwacCreateOutput(d, id, version);
|
output = UwacCreateOutput(d, id, version);
|
||||||
if (!output) {
|
|
||||||
|
if (!output)
|
||||||
|
{
|
||||||
assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create output\n"));
|
assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create output\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ev = (UwacOutputNewEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_OUTPUT);
|
ev = (UwacOutputNewEvent*)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_OUTPUT);
|
||||||
|
|
||||||
if (ev)
|
if (ev)
|
||||||
ev->output = output;
|
ev->output = output;
|
||||||
|
}
|
||||||
} else if (strcmp(interface, "wl_seat") == 0) {
|
else if (strcmp(interface, "wl_seat") == 0)
|
||||||
UwacSeatNewEvent *ev;
|
{
|
||||||
UwacSeat *seat;
|
UwacSeatNewEvent* ev;
|
||||||
|
UwacSeat* seat;
|
||||||
seat = UwacSeatNew(d, id, min(version, TARGET_SEAT_INTERFACE));
|
seat = UwacSeatNew(d, id, min(version, TARGET_SEAT_INTERFACE));
|
||||||
if (!seat) {
|
|
||||||
|
if (!seat)
|
||||||
|
{
|
||||||
assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat\n"));
|
assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ev = (UwacSeatNewEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_SEAT);
|
ev = (UwacSeatNewEvent*)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_SEAT);
|
||||||
if (!ev) {
|
|
||||||
|
if (!ev)
|
||||||
|
{
|
||||||
assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat event\n"));
|
assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat event\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ev->seat = seat;
|
ev->seat = seat;
|
||||||
} else if (strcmp(interface, "wl_data_device_manager") == 0) {
|
}
|
||||||
d->data_device_manager = wl_registry_bind(registry, id, &wl_data_device_manager_interface, min(TARGET_DDM_INTERFACE, version));
|
else if (strcmp(interface, "wl_data_device_manager") == 0)
|
||||||
} else if (strcmp(interface, "wl_shell") == 0) {
|
{
|
||||||
d->shell = wl_registry_bind(registry, id, &wl_shell_interface, min(TARGET_SHELL_INTERFACE, version));
|
d->data_device_manager = wl_registry_bind(registry, id, &wl_data_device_manager_interface,
|
||||||
} else if (strcmp(interface, "xdg_shell") == 0) {
|
min(TARGET_DDM_INTERFACE, version));
|
||||||
|
}
|
||||||
|
else if (strcmp(interface, "wl_shell") == 0)
|
||||||
|
{
|
||||||
|
d->shell = wl_registry_bind(registry, id, &wl_shell_interface, min(TARGET_SHELL_INTERFACE,
|
||||||
|
version));
|
||||||
|
}
|
||||||
|
else if (strcmp(interface, "xdg_shell") == 0)
|
||||||
|
{
|
||||||
d->xdg_shell = wl_registry_bind(registry, id, &xdg_shell_interface, 1);
|
d->xdg_shell = wl_registry_bind(registry, id, &xdg_shell_interface, 1);
|
||||||
xdg_shell_use_unstable_version(d->xdg_shell, TARGET_XDG_VERSION);
|
xdg_shell_use_unstable_version(d->xdg_shell, TARGET_XDG_VERSION);
|
||||||
xdg_shell_add_listener(d->xdg_shell, &xdg_shell_listener, d);
|
xdg_shell_add_listener(d->xdg_shell, &xdg_shell_listener, d);
|
||||||
#if BUILD_IVI
|
#if BUILD_IVI
|
||||||
} else if (strcmp(interface, "ivi_application") == 0) {
|
}
|
||||||
|
else if (strcmp(interface, "ivi_application") == 0)
|
||||||
|
{
|
||||||
d->ivi_application = wl_registry_bind(registry, id, &ivi_application_interface, 1);
|
d->ivi_application = wl_registry_bind(registry, id, &ivi_application_interface, 1);
|
||||||
#endif
|
#endif
|
||||||
#if BUILD_FULLSCREEN_SHELL
|
#if BUILD_FULLSCREEN_SHELL
|
||||||
} else if (strcmp(interface, "_wl_fullscreen_shell") == 0) {
|
}
|
||||||
|
else if (strcmp(interface, "_wl_fullscreen_shell") == 0)
|
||||||
|
{
|
||||||
d->fullscreen_shell = wl_registry_bind(registry, id, &_wl_fullscreen_shell_interface, 1);
|
d->fullscreen_shell = wl_registry_bind(registry, id, &_wl_fullscreen_shell_interface, 1);
|
||||||
_wl_fullscreen_shell_add_listener(d->fullscreen_shell, &fullscreen_shell_listener, d);
|
_wl_fullscreen_shell_add_listener(d->fullscreen_shell, &fullscreen_shell_listener, d);
|
||||||
#endif
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
} else if (strcmp(interface, "text_cursor_position") == 0) {
|
}
|
||||||
|
else if (strcmp(interface, "text_cursor_position") == 0)
|
||||||
|
{
|
||||||
d->text_cursor_position = wl_registry_bind(registry, id, &text_cursor_position_interface, 1);
|
d->text_cursor_position = wl_registry_bind(registry, id, &text_cursor_position_interface, 1);
|
||||||
} else if (strcmp(interface, "workspace_manager") == 0) {
|
}
|
||||||
|
else if (strcmp(interface, "workspace_manager") == 0)
|
||||||
|
{
|
||||||
//init_workspace_manager(d, id);
|
//init_workspace_manager(d, id);
|
||||||
} else if (strcmp(interface, "wl_subcompositor") == 0) {
|
}
|
||||||
|
else if (strcmp(interface, "wl_subcompositor") == 0)
|
||||||
|
{
|
||||||
d->subcompositor = wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);
|
d->subcompositor = wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
|
static void registry_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name)
|
||||||
UwacDisplay *d = data;
|
{
|
||||||
UwacGlobal *global;
|
UwacDisplay* d = data;
|
||||||
UwacGlobal *tmp;
|
UwacGlobal* global;
|
||||||
|
UwacGlobal* tmp;
|
||||||
wl_list_for_each_safe(global, tmp, &d->globals, link) {
|
wl_list_for_each_safe(global, tmp, &d->globals, link)
|
||||||
|
{
|
||||||
if (global->name != name)
|
if (global->name != name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
if (strcmp(global->interface, "wl_output") == 0)
|
if (strcmp(global->interface, "wl_output") == 0)
|
||||||
display_destroy_output(d, name);
|
display_destroy_output(d, name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (strcmp(global->interface, "wl_seat") == 0) {
|
if (strcmp(global->interface, "wl_seat") == 0)
|
||||||
UwacSeatRemovedEvent *ev;
|
{
|
||||||
UwacSeat *seat;
|
UwacSeatRemovedEvent* ev;
|
||||||
|
UwacSeat* seat;
|
||||||
seat = display_destroy_seat(d, name);
|
seat = display_destroy_seat(d, name);
|
||||||
ev = (UwacSeatRemovedEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_REMOVED_SEAT);
|
ev = (UwacSeatRemovedEvent*)UwacDisplayNewEvent(d, UWAC_EVENT_REMOVED_SEAT);
|
||||||
|
|
||||||
if (ev)
|
if (ev)
|
||||||
ev->seat = seat;
|
ev->seat = seat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wl_list_remove(&global->link);
|
wl_list_remove(&global->link);
|
||||||
free(global->interface);
|
free(global->interface);
|
||||||
free(global);
|
free(global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwacDestroyGlobal(UwacGlobal *global) {
|
void UwacDestroyGlobal(UwacGlobal* global)
|
||||||
|
{
|
||||||
free(global->interface);
|
free(global->interface);
|
||||||
wl_list_remove(&global->link);
|
wl_list_remove(&global->link);
|
||||||
free(global);
|
free(global);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *display_bind(UwacDisplay *display, uint32_t name, const struct wl_interface *interface, uint32_t version) {
|
void* display_bind(UwacDisplay* display, uint32_t name, const struct wl_interface* interface,
|
||||||
|
uint32_t version)
|
||||||
|
{
|
||||||
return wl_registry_bind(display->registry, name, interface, version);
|
return wl_registry_bind(display->registry, name, interface, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_registry_listener registry_listener = {
|
static const struct wl_registry_listener registry_listener =
|
||||||
|
{
|
||||||
registry_handle_global,
|
registry_handle_global,
|
||||||
registry_handle_global_remove
|
registry_handle_global_remove
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int UwacDisplayWatchFd(UwacDisplay *display, int fd, uint32_t events, UwacTask *task) {
|
int UwacDisplayWatchFd(UwacDisplay* display, int fd, uint32_t events, UwacTask* task)
|
||||||
|
{
|
||||||
struct epoll_event ep;
|
struct epoll_event ep;
|
||||||
|
|
||||||
ep.events = events;
|
ep.events = events;
|
||||||
ep.data.ptr = task;
|
ep.data.ptr = task;
|
||||||
return epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep);
|
return epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwacDisplayUnwatchFd(UwacDisplay *display, int fd) {
|
void UwacDisplayUnwatchFd(UwacDisplay* display, int fd)
|
||||||
|
{
|
||||||
epoll_ctl(display->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
|
epoll_ctl(display->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display_exit(UwacDisplay *display) {
|
static void display_exit(UwacDisplay* display)
|
||||||
|
{
|
||||||
display->running = false;
|
display->running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display_dispatch_events(UwacTask *task, uint32_t events)
|
static void display_dispatch_events(UwacTask* task, uint32_t events)
|
||||||
{
|
{
|
||||||
UwacDisplay *display = container_of(task, UwacDisplay, dispatch_fd_task);
|
UwacDisplay* display = container_of(task, UwacDisplay, dispatch_fd_task);
|
||||||
struct epoll_event ep;
|
struct epoll_event ep;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
display->display_fd_events = events;
|
display->display_fd_events = events;
|
||||||
|
|
||||||
if ((events & EPOLLERR) || (events & EPOLLHUP)) {
|
if ((events & EPOLLERR) || (events & EPOLLHUP))
|
||||||
|
{
|
||||||
display_exit(display);
|
display_exit(display);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (events & EPOLLIN) {
|
if (events & EPOLLIN)
|
||||||
|
{
|
||||||
ret = wl_display_dispatch(display->display);
|
ret = wl_display_dispatch(display->display);
|
||||||
if (ret == -1) {
|
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
display_exit(display);
|
display_exit(display);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (events & EPOLLOUT) {
|
if (events & EPOLLOUT)
|
||||||
|
{
|
||||||
ret = wl_display_flush(display->display);
|
ret = wl_display_flush(display->display);
|
||||||
if (ret == 0) {
|
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
ep.events = EPOLLIN | EPOLLERR | EPOLLHUP;
|
ep.events = EPOLLIN | EPOLLERR | EPOLLHUP;
|
||||||
ep.data.ptr = &display->dispatch_fd_task;
|
ep.data.ptr = &display->dispatch_fd_task;
|
||||||
epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep);
|
epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep);
|
||||||
} else if (ret == -1 && errno != EAGAIN) {
|
}
|
||||||
|
else if (ret == -1 && errno != EAGAIN)
|
||||||
|
{
|
||||||
display_exit(display);
|
display_exit(display);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -308,11 +359,13 @@ static void display_dispatch_events(UwacTask *task, uint32_t events)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err) {
|
UwacDisplay* UwacOpenDisplay(const char* name, UwacReturnCode* err)
|
||||||
UwacDisplay *ret;
|
{
|
||||||
|
UwacDisplay* ret;
|
||||||
|
ret = (UwacDisplay*)calloc(1, sizeof(*ret));
|
||||||
|
|
||||||
ret = (UwacDisplay *)calloc(1, sizeof(*ret));
|
if (!ret)
|
||||||
if (!ret) {
|
{
|
||||||
*err = UWAC_ERROR_NOMEMORY;
|
*err = UWAC_ERROR_NOMEMORY;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -321,38 +374,46 @@ UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err) {
|
|||||||
wl_list_init(&ret->seats);
|
wl_list_init(&ret->seats);
|
||||||
wl_list_init(&ret->outputs);
|
wl_list_init(&ret->outputs);
|
||||||
wl_list_init(&ret->windows);
|
wl_list_init(&ret->windows);
|
||||||
|
|
||||||
ret->display = wl_display_connect(name);
|
ret->display = wl_display_connect(name);
|
||||||
if (ret->display == NULL) {
|
|
||||||
|
if (ret->display == NULL)
|
||||||
|
{
|
||||||
fprintf(stderr, "failed to connect to Wayland display %s: %m\n", name);
|
fprintf(stderr, "failed to connect to Wayland display %s: %m\n", name);
|
||||||
*err = UWAC_ERROR_UNABLE_TO_CONNECT;
|
*err = UWAC_ERROR_UNABLE_TO_CONNECT;
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->epoll_fd = uwac_os_epoll_create_cloexec();
|
ret->epoll_fd = uwac_os_epoll_create_cloexec();
|
||||||
if (ret->epoll_fd < 0) {
|
|
||||||
|
if (ret->epoll_fd < 0)
|
||||||
|
{
|
||||||
*err = UWAC_NOT_ENOUGH_RESOURCES;
|
*err = UWAC_NOT_ENOUGH_RESOURCES;
|
||||||
goto out_disconnect;
|
goto out_disconnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->display_fd = wl_display_get_fd(ret->display);
|
ret->display_fd = wl_display_get_fd(ret->display);
|
||||||
|
|
||||||
ret->registry = wl_display_get_registry(ret->display);
|
ret->registry = wl_display_get_registry(ret->display);
|
||||||
if (!ret->registry) {
|
|
||||||
|
if (!ret->registry)
|
||||||
|
{
|
||||||
*err = UWAC_ERROR_NOMEMORY;
|
*err = UWAC_ERROR_NOMEMORY;
|
||||||
goto out_close_epoll;
|
goto out_close_epoll;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_registry_add_listener(ret->registry, ®istry_listener, ret);
|
wl_registry_add_listener(ret->registry, ®istry_listener, ret);
|
||||||
|
|
||||||
if ((wl_display_roundtrip(ret->display) < 0) || (wl_display_roundtrip(ret->display) < 0)) {
|
if ((wl_display_roundtrip(ret->display) < 0) || (wl_display_roundtrip(ret->display) < 0))
|
||||||
|
{
|
||||||
uwacErrorHandler(ret, UWAC_ERROR_UNABLE_TO_CONNECT, "Failed to process Wayland connection: %m\n");
|
uwacErrorHandler(ret, UWAC_ERROR_UNABLE_TO_CONNECT, "Failed to process Wayland connection: %m\n");
|
||||||
*err = UWAC_ERROR_UNABLE_TO_CONNECT;
|
*err = UWAC_ERROR_UNABLE_TO_CONNECT;
|
||||||
goto out_free_registry;
|
goto out_free_registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->dispatch_fd_task.run = display_dispatch_events;
|
ret->dispatch_fd_task.run = display_dispatch_events;
|
||||||
if (UwacDisplayWatchFd(ret, ret->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP, &ret->dispatch_fd_task) < 0) {
|
|
||||||
|
if (UwacDisplayWatchFd(ret, ret->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP,
|
||||||
|
&ret->dispatch_fd_task) < 0)
|
||||||
|
{
|
||||||
uwacErrorHandler(ret, UWAC_ERROR_INTERNAL, "unable to watch display fd: %m\n");
|
uwacErrorHandler(ret, UWAC_ERROR_INTERNAL, "unable to watch display fd: %m\n");
|
||||||
*err = UWAC_ERROR_INTERNAL;
|
*err = UWAC_ERROR_INTERNAL;
|
||||||
goto out_free_registry;
|
goto out_free_registry;
|
||||||
@ -361,7 +422,6 @@ UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err) {
|
|||||||
ret->running = true;
|
ret->running = true;
|
||||||
ret->last_error = *err = UWAC_SUCCESS;
|
ret->last_error = *err = UWAC_SUCCESS;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
out_free_registry:
|
out_free_registry:
|
||||||
wl_registry_destroy(ret->registry);
|
wl_registry_destroy(ret->registry);
|
||||||
out_close_epoll:
|
out_close_epoll:
|
||||||
@ -373,28 +433,33 @@ out_free:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int UwacDisplayDispatch(UwacDisplay *display, int timeout) {
|
int UwacDisplayDispatch(UwacDisplay* display, int timeout)
|
||||||
|
{
|
||||||
int ret, count, i;
|
int ret, count, i;
|
||||||
UwacTask *task;
|
UwacTask* task;
|
||||||
struct epoll_event ep[16];
|
struct epoll_event ep[16];
|
||||||
|
|
||||||
wl_display_dispatch_pending(display->display);
|
wl_display_dispatch_pending(display->display);
|
||||||
|
|
||||||
if (!display->running)
|
if (!display->running)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = wl_display_flush(display->display);
|
ret = wl_display_flush(display->display);
|
||||||
if (ret < 0 && errno == EAGAIN) {
|
|
||||||
|
if (ret < 0 && errno == EAGAIN)
|
||||||
|
{
|
||||||
ep[0].events = (EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP);
|
ep[0].events = (EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP);
|
||||||
ep[0].data.ptr = &display->dispatch_fd_task;
|
ep[0].data.ptr = &display->dispatch_fd_task;
|
||||||
|
|
||||||
epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep[0]);
|
epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep[0]);
|
||||||
} else if (ret < 0) {
|
}
|
||||||
|
else if (ret < 0)
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = epoll_wait(display->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
|
count = epoll_wait(display->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
task = ep[i].data.ptr;
|
task = ep[i].data.ptr;
|
||||||
task->run(task, ep[i].events);
|
task->run(task, ep[i].events);
|
||||||
}
|
}
|
||||||
@ -404,74 +469,85 @@ int UwacDisplayDispatch(UwacDisplay *display, int timeout) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display) {
|
UwacReturnCode UwacDisplayGetLastError(const UwacDisplay* display)
|
||||||
|
{
|
||||||
return display->last_error;
|
return display->last_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay) {
|
UwacReturnCode UwacCloseDisplay(UwacDisplay** pdisplay)
|
||||||
UwacDisplay *display;
|
{
|
||||||
UwacSeat *seat, *tmpSeat;
|
UwacDisplay* display;
|
||||||
UwacWindow *window, *tmpWindow;
|
UwacSeat* seat, *tmpSeat;
|
||||||
UwacOutput *output, *tmpOutput;
|
UwacWindow* window, *tmpWindow;
|
||||||
UwacGlobal *global, *tmpGlobal;
|
UwacOutput* output, *tmpOutput;
|
||||||
|
UwacGlobal* global, *tmpGlobal;
|
||||||
assert(pdisplay);
|
assert(pdisplay);
|
||||||
display = *pdisplay;
|
display = *pdisplay;
|
||||||
|
|
||||||
if (!display)
|
if (!display)
|
||||||
return UWAC_ERROR_INVALID_DISPLAY;
|
return UWAC_ERROR_INVALID_DISPLAY;
|
||||||
|
|
||||||
/* destroy windows */
|
/* destroy windows */
|
||||||
wl_list_for_each_safe(window, tmpWindow, &display->windows, link) {
|
wl_list_for_each_safe(window, tmpWindow, &display->windows, link)
|
||||||
|
{
|
||||||
UwacDestroyWindow(&window);
|
UwacDestroyWindow(&window);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* destroy seats */
|
/* destroy seats */
|
||||||
wl_list_for_each_safe(seat, tmpSeat, &display->seats, link) {
|
wl_list_for_each_safe(seat, tmpSeat, &display->seats, link)
|
||||||
|
{
|
||||||
UwacSeatDestroy(seat);
|
UwacSeatDestroy(seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* destroy output */
|
/* destroy output */
|
||||||
wl_list_for_each_safe(output, tmpOutput, &display->outputs, link) {
|
wl_list_for_each_safe(output, tmpOutput, &display->outputs, link)
|
||||||
|
{
|
||||||
UwacDestroyOutput(output);
|
UwacDestroyOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* destroy globals */
|
/* destroy globals */
|
||||||
wl_list_for_each_safe(global, tmpGlobal, &display->globals, link) {
|
wl_list_for_each_safe(global, tmpGlobal, &display->globals, link)
|
||||||
|
{
|
||||||
UwacDestroyGlobal(global);
|
UwacDestroyGlobal(global);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display->compositor)
|
if (display->compositor)
|
||||||
wl_compositor_destroy(display->compositor);
|
wl_compositor_destroy(display->compositor);
|
||||||
|
|
||||||
#ifdef BUILD_FULLSCREEN_SHELL
|
#ifdef BUILD_FULLSCREEN_SHELL
|
||||||
|
|
||||||
if (display->fullscreen_shell)
|
if (display->fullscreen_shell)
|
||||||
_wl_fullscreen_shell_destroy(display->fullscreen_shell);
|
_wl_fullscreen_shell_destroy(display->fullscreen_shell);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef BUILD_IVI
|
#ifdef BUILD_IVI
|
||||||
|
|
||||||
if (display->ivi_application)
|
if (display->ivi_application)
|
||||||
ivi_application_destroy(display->ivi_application);
|
ivi_application_destroy(display->ivi_application);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (display->xdg_shell)
|
if (display->xdg_shell)
|
||||||
xdg_shell_destroy(display->xdg_shell);
|
xdg_shell_destroy(display->xdg_shell);
|
||||||
|
|
||||||
if (display->shell)
|
if (display->shell)
|
||||||
wl_shell_destroy(display->shell);
|
wl_shell_destroy(display->shell);
|
||||||
|
|
||||||
if (display->shm)
|
if (display->shm)
|
||||||
wl_shm_destroy(display->shm);
|
wl_shm_destroy(display->shm);
|
||||||
|
|
||||||
if (display->subcompositor)
|
if (display->subcompositor)
|
||||||
wl_subcompositor_destroy(display->subcompositor);
|
wl_subcompositor_destroy(display->subcompositor);
|
||||||
|
|
||||||
if (display->data_device_manager)
|
if (display->data_device_manager)
|
||||||
wl_data_device_manager_destroy(display->data_device_manager);
|
wl_data_device_manager_destroy(display->data_device_manager);
|
||||||
|
|
||||||
free(display->shm_formats);
|
free(display->shm_formats);
|
||||||
wl_registry_destroy(display->registry);
|
wl_registry_destroy(display->registry);
|
||||||
|
|
||||||
close(display->epoll_fd);
|
close(display->epoll_fd);
|
||||||
|
|
||||||
wl_display_disconnect(display->display);
|
wl_display_disconnect(display->display);
|
||||||
|
|
||||||
/* cleanup the event queue */
|
/* cleanup the event queue */
|
||||||
while (display->push_queue) {
|
while (display->push_queue)
|
||||||
UwacEventListItem *item = display->push_queue;
|
{
|
||||||
|
UwacEventListItem* item = display->push_queue;
|
||||||
display->push_queue = item->tail;
|
display->push_queue = item->tail;
|
||||||
free(item);
|
free(item);
|
||||||
}
|
}
|
||||||
@ -481,11 +557,13 @@ UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay) {
|
|||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int UwacDisplayGetFd(UwacDisplay *display) {
|
int UwacDisplayGetFd(UwacDisplay* display)
|
||||||
|
{
|
||||||
return display->epoll_fd;
|
return display->epoll_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *errorStrings[] = {
|
static const char* errorStrings[] =
|
||||||
|
{
|
||||||
"success",
|
"success",
|
||||||
"out of memory error",
|
"out of memory error",
|
||||||
"unable to connect to wayland display",
|
"unable to connect to wayland display",
|
||||||
@ -498,37 +576,44 @@ static const char *errorStrings[] = {
|
|||||||
"internal error",
|
"internal error",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *UwacErrorString(UwacReturnCode error) {
|
const char* UwacErrorString(UwacReturnCode error)
|
||||||
|
{
|
||||||
if (error < UWAC_SUCCESS || error >= UWAC_ERROR_LAST)
|
if (error < UWAC_SUCCESS || error >= UWAC_ERROR_LAST)
|
||||||
return "invalid error code";
|
return "invalid error code";
|
||||||
|
|
||||||
return errorStrings[error];
|
return errorStrings[error];
|
||||||
}
|
}
|
||||||
|
|
||||||
UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version) {
|
UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay* display, const char* name,
|
||||||
const UwacGlobal *global;
|
uint32_t* version)
|
||||||
|
{
|
||||||
|
const UwacGlobal* global;
|
||||||
|
|
||||||
if (!display)
|
if (!display)
|
||||||
return UWAC_ERROR_INVALID_DISPLAY;
|
return UWAC_ERROR_INVALID_DISPLAY;
|
||||||
|
|
||||||
wl_list_for_each(global, &display->globals, link) {
|
wl_list_for_each(global, &display->globals, link)
|
||||||
if (strcmp(global->interface, name) == 0) {
|
{
|
||||||
|
if (strcmp(global->interface, name) == 0)
|
||||||
|
{
|
||||||
if (version)
|
if (version)
|
||||||
*version = global->version;
|
*version = global->version;
|
||||||
|
|
||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return UWAC_NOT_FOUND;
|
return UWAC_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display) {
|
uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay* display)
|
||||||
if (!display) {
|
{
|
||||||
display->last_error = UWAC_ERROR_INVALID_DISPLAY;
|
if (!display)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!display->shm) {
|
if (!display->shm)
|
||||||
|
{
|
||||||
display->last_error = UWAC_NOT_FOUND;
|
display->last_error = UWAC_NOT_FOUND;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -538,28 +623,35 @@ uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled) {
|
UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay* display, enum wl_shm_format* formats,
|
||||||
|
int formats_size, int* filled)
|
||||||
|
{
|
||||||
if (!display)
|
if (!display)
|
||||||
return UWAC_ERROR_INVALID_DISPLAY;
|
return UWAC_ERROR_INVALID_DISPLAY;
|
||||||
|
|
||||||
*filled = min(display->shm_formats_nb, formats_size);
|
*filled = min(display->shm_formats_nb, formats_size);
|
||||||
memcpy(formats, (const void *)display->shm_formats, *filled * sizeof(enum wl_shm_format));
|
memcpy(formats, (const void*)display->shm_formats, *filled * sizeof(enum wl_shm_format));
|
||||||
|
|
||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display) {
|
uint32_t UwacDisplayGetNbOutputs(UwacDisplay* display)
|
||||||
|
{
|
||||||
return wl_list_length(&display->outputs);
|
return wl_list_length(&display->outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index) {
|
UwacOutput* UwacDisplayGetOutput(UwacDisplay* display, int index)
|
||||||
struct wl_list *l;
|
{
|
||||||
|
struct wl_list* l;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!display)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (i = 0, l = &display->outputs; l && i < index; i++, l = l->next)
|
for (i = 0, l = &display->outputs; l && i < index; i++, l = l->next)
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!l) {
|
if (!l)
|
||||||
|
{
|
||||||
display->last_error = UWAC_NOT_FOUND;
|
display->last_error = UWAC_NOT_FOUND;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -568,51 +660,62 @@ UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index) {
|
|||||||
return container_of(l, UwacOutput, link);
|
return container_of(l, UwacOutput, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution) {
|
UwacReturnCode UwacOutputGetResolution(UwacOutput* output, UwacSize* resolution)
|
||||||
|
{
|
||||||
*resolution = output->resolution;
|
*resolution = output->resolution;
|
||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacEvent *UwacDisplayNewEvent(UwacDisplay *display, int type) {
|
UwacEvent* UwacDisplayNewEvent(UwacDisplay* display, int type)
|
||||||
UwacEventListItem *ret;
|
{
|
||||||
|
UwacEventListItem* ret;
|
||||||
|
|
||||||
if (!display) {
|
if (!display)
|
||||||
display->last_error = UWAC_ERROR_INVALID_DISPLAY;
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = zalloc(sizeof(UwacEventListItem));
|
ret = zalloc(sizeof(UwacEventListItem));
|
||||||
if (!ret) {
|
|
||||||
assert(uwacErrorHandler(display, UWAC_ERROR_NOMEMORY, "unable to allocate a '%s' event", event_names[type]));
|
if (!ret)
|
||||||
|
{
|
||||||
|
assert(uwacErrorHandler(display, UWAC_ERROR_NOMEMORY, "unable to allocate a '%s' event",
|
||||||
|
event_names[type]));
|
||||||
display->last_error = UWAC_ERROR_NOMEMORY;
|
display->last_error = UWAC_ERROR_NOMEMORY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->event.type = type;
|
ret->event.type = type;
|
||||||
ret->tail = display->push_queue;
|
ret->tail = display->push_queue;
|
||||||
|
|
||||||
if (ret->tail)
|
if (ret->tail)
|
||||||
ret->tail->head = ret;
|
ret->tail->head = ret;
|
||||||
else
|
else
|
||||||
display->pop_queue = ret;
|
display->pop_queue = ret;
|
||||||
|
|
||||||
display->push_queue = ret;
|
display->push_queue = ret;
|
||||||
return &ret->event;
|
return &ret->event;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UwacHasEvent(UwacDisplay *display) {
|
bool UwacHasEvent(UwacDisplay* display)
|
||||||
|
{
|
||||||
return display->pop_queue != NULL;
|
return display->pop_queue != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event) {
|
UwacReturnCode UwacNextEvent(UwacDisplay* display, UwacEvent* event)
|
||||||
UwacEventListItem *prevItem;
|
{
|
||||||
|
UwacEventListItem* prevItem;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!display)
|
if (!display)
|
||||||
return UWAC_ERROR_INVALID_DISPLAY;
|
return UWAC_ERROR_INVALID_DISPLAY;
|
||||||
|
|
||||||
while (!display->pop_queue) {
|
while (!display->pop_queue)
|
||||||
|
{
|
||||||
ret = UwacDisplayDispatch(display, 1 * 1000);
|
ret = UwacDisplayDispatch(display, 1 * 1000);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return UWAC_ERROR_INTERNAL;
|
return UWAC_ERROR_INTERNAL;
|
||||||
else if (ret == 0)
|
else if (ret == 0)
|
||||||
@ -623,9 +726,11 @@ UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event) {
|
|||||||
*event = display->pop_queue->event;
|
*event = display->pop_queue->event;
|
||||||
free(display->pop_queue);
|
free(display->pop_queue);
|
||||||
display->pop_queue = prevItem;
|
display->pop_queue = prevItem;
|
||||||
|
|
||||||
if (prevItem)
|
if (prevItem)
|
||||||
prevItem->tail = NULL;
|
prevItem->tail = NULL;
|
||||||
else
|
else
|
||||||
display->push_queue = NULL;
|
display->push_queue = NULL;
|
||||||
|
|
||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,10 @@
|
|||||||
#define UWAC_INITIAL_BUFFERS 3
|
#define UWAC_INITIAL_BUFFERS 3
|
||||||
|
|
||||||
|
|
||||||
static int bppFromShmFormat(enum wl_shm_format format) {
|
static int bppFromShmFormat(enum wl_shm_format format)
|
||||||
switch (format) {
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
case WL_SHM_FORMAT_ARGB8888:
|
case WL_SHM_FORMAT_ARGB8888:
|
||||||
case WL_SHM_FORMAT_XRGB8888:
|
case WL_SHM_FORMAT_XRGB8888:
|
||||||
default:
|
default:
|
||||||
@ -45,21 +47,24 @@ static int bppFromShmFormat(enum wl_shm_format format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void buffer_release(void *data, struct wl_buffer *buffer) {
|
static void buffer_release(void* data, struct wl_buffer* buffer)
|
||||||
UwacBuffer *uwacBuffer = (UwacBuffer *)data;
|
{
|
||||||
|
UwacBuffer* uwacBuffer = (UwacBuffer*)data;
|
||||||
uwacBuffer->used = false;
|
uwacBuffer->used = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_buffer_listener buffer_listener = {
|
static const struct wl_buffer_listener buffer_listener =
|
||||||
|
{
|
||||||
buffer_release
|
buffer_release
|
||||||
};
|
};
|
||||||
|
|
||||||
void UwacWindowDestroyBuffers(UwacWindow *w) {
|
void UwacWindowDestroyBuffers(UwacWindow* w)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < w->nbuffers; i++) {
|
for (i = 0; i < w->nbuffers; i++)
|
||||||
UwacBuffer *buffer = &w->buffers[i];
|
{
|
||||||
|
UwacBuffer* buffer = &w->buffers[i];
|
||||||
#ifdef HAVE_PIXMAN_REGION
|
#ifdef HAVE_PIXMAN_REGION
|
||||||
pixman_region32_fini(&buffer->damage);
|
pixman_region32_fini(&buffer->damage);
|
||||||
#else
|
#else
|
||||||
@ -74,67 +79,77 @@ void UwacWindowDestroyBuffers(UwacWindow *w) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int UwacWindowShmAllocBuffers(UwacWindow *w, int nbuffers, int allocSize, uint32_t width,
|
int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32_t width,
|
||||||
uint32_t height, enum wl_shm_format format);
|
uint32_t height, enum wl_shm_format format);
|
||||||
|
|
||||||
static void xdg_handle_configure(void *data, struct xdg_surface *surface,
|
static void xdg_handle_configure(void* data, struct xdg_surface* surface,
|
||||||
int32_t width, int32_t height,
|
int32_t width, int32_t height,
|
||||||
struct wl_array *states, uint32_t serial)
|
struct wl_array* states, uint32_t serial)
|
||||||
{
|
{
|
||||||
UwacWindow *window = (UwacWindow *)data;
|
UwacWindow* window = (UwacWindow*)data;
|
||||||
UwacConfigureEvent *event;
|
UwacConfigureEvent* event;
|
||||||
int ret, surfaceState;
|
int ret, surfaceState;
|
||||||
enum xdg_surface_state *state;
|
enum xdg_surface_state* state;
|
||||||
|
|
||||||
surfaceState = 0;
|
surfaceState = 0;
|
||||||
wl_array_for_each(state, states) {
|
wl_array_for_each(state, states)
|
||||||
switch (*state) {
|
{
|
||||||
|
switch (*state)
|
||||||
|
{
|
||||||
case XDG_SURFACE_STATE_MAXIMIZED:
|
case XDG_SURFACE_STATE_MAXIMIZED:
|
||||||
surfaceState |= UWAC_WINDOW_MAXIMIZED;
|
surfaceState |= UWAC_WINDOW_MAXIMIZED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XDG_SURFACE_STATE_FULLSCREEN:
|
case XDG_SURFACE_STATE_FULLSCREEN:
|
||||||
surfaceState |= UWAC_WINDOW_FULLSCREEN;
|
surfaceState |= UWAC_WINDOW_FULLSCREEN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XDG_SURFACE_STATE_ACTIVATED:
|
case XDG_SURFACE_STATE_ACTIVATED:
|
||||||
surfaceState |= UWAC_WINDOW_ACTIVATED;
|
surfaceState |= UWAC_WINDOW_ACTIVATED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XDG_SURFACE_STATE_RESIZING:
|
case XDG_SURFACE_STATE_RESIZING:
|
||||||
surfaceState |= UWAC_WINDOW_RESIZING;
|
surfaceState |= UWAC_WINDOW_RESIZING;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window->surfaceStates = surfaceState;
|
window->surfaceStates = surfaceState;
|
||||||
|
event = (UwacConfigureEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
|
||||||
|
|
||||||
event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
|
if (!event)
|
||||||
if(!event) {
|
{
|
||||||
assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n"));
|
assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY,
|
||||||
|
"failed to allocate a configure event\n"));
|
||||||
goto ack;
|
goto ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
event->window = window;
|
event->window = window;
|
||||||
event->states = surfaceState;
|
event->states = surfaceState;
|
||||||
if (width && height) {
|
|
||||||
|
if (width && height)
|
||||||
|
{
|
||||||
event->width = width;
|
event->width = width;
|
||||||
event->height = height;
|
event->height = height;
|
||||||
|
|
||||||
UwacWindowDestroyBuffers(window);
|
UwacWindowDestroyBuffers(window);
|
||||||
|
|
||||||
window->width = width;
|
window->width = width;
|
||||||
window->stride = width * bppFromShmFormat(window->format);
|
window->stride = width * bppFromShmFormat(window->format);
|
||||||
window->height = height;
|
window->height = height;
|
||||||
|
|
||||||
ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height,
|
ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height,
|
||||||
width, height, window->format);
|
width, height, window->format);
|
||||||
if (ret != UWAC_SUCCESS) {
|
|
||||||
|
if (ret != UWAC_SUCCESS)
|
||||||
|
{
|
||||||
assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
|
assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
|
||||||
window->drawingBuffer = window->pendingBuffer = NULL;
|
window->drawingBuffer = window->pendingBuffer = NULL;
|
||||||
goto ack;
|
goto ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->drawingBuffer = window->pendingBuffer = &window->buffers[0];
|
window->drawingBuffer = window->pendingBuffer = &window->buffers[0];
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
event->width = window->width;
|
event->width = window->width;
|
||||||
event->height = window->height;
|
event->height = window->height;
|
||||||
}
|
}
|
||||||
@ -143,198 +158,221 @@ ack:
|
|||||||
xdg_surface_ack_configure(surface, serial);
|
xdg_surface_ack_configure(surface, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xdg_handle_close(void *data, struct xdg_surface *xdg_surface)
|
static void xdg_handle_close(void* data, struct xdg_surface* xdg_surface)
|
||||||
{
|
{
|
||||||
UwacCloseEvent *event;
|
UwacCloseEvent* event;
|
||||||
UwacWindow *window = (UwacWindow *)data;
|
UwacWindow* window = (UwacWindow*)data;
|
||||||
|
event = (UwacCloseEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_CLOSE);
|
||||||
|
|
||||||
event = (UwacCloseEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CLOSE);
|
if (!event)
|
||||||
if(!event) {
|
{
|
||||||
assert(uwacErrorHandler(window->display, UWAC_ERROR_INTERNAL, "failed to allocate a close event\n"));
|
assert(uwacErrorHandler(window->display, UWAC_ERROR_INTERNAL,
|
||||||
|
"failed to allocate a close event\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event->window = window;
|
event->window = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
static const struct xdg_surface_listener xdg_surface_listener =
|
||||||
|
{
|
||||||
xdg_handle_configure,
|
xdg_handle_configure,
|
||||||
xdg_handle_close,
|
xdg_handle_close,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if BUILD_IVI
|
#if BUILD_IVI
|
||||||
|
|
||||||
static void ivi_handle_configure(void *data, struct ivi_surface *surface,
|
static void ivi_handle_configure(void* data, struct ivi_surface* surface,
|
||||||
int32_t width, int32_t height)
|
int32_t width, int32_t height)
|
||||||
{
|
{
|
||||||
UwacWindow *window = (UwacWindow *)data;
|
UwacWindow* window = (UwacWindow*)data;
|
||||||
UwacConfigureEvent *event;
|
UwacConfigureEvent* event;
|
||||||
int ret;
|
int ret;
|
||||||
|
event = (UwacConfigureEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
|
||||||
|
|
||||||
|
if (!event)
|
||||||
event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
|
{
|
||||||
if(!event) {
|
assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY,
|
||||||
assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n"));
|
"failed to allocate a configure event\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event->window = window;
|
event->window = window;
|
||||||
event->states = 0;
|
event->states = 0;
|
||||||
if (width && height) {
|
|
||||||
|
if (width && height)
|
||||||
|
{
|
||||||
event->width = width;
|
event->width = width;
|
||||||
event->height = height;
|
event->height = height;
|
||||||
|
|
||||||
UwacWindowDestroyBuffers(window);
|
UwacWindowDestroyBuffers(window);
|
||||||
|
|
||||||
window->width = width;
|
window->width = width;
|
||||||
window->stride = width * bppFromShmFormat(window->format);
|
window->stride = width * bppFromShmFormat(window->format);
|
||||||
window->height = height;
|
window->height = height;
|
||||||
|
|
||||||
ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height,
|
ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height,
|
||||||
width, height, window->format);
|
width, height, window->format);
|
||||||
if (ret != UWAC_SUCCESS) {
|
|
||||||
|
if (ret != UWAC_SUCCESS)
|
||||||
|
{
|
||||||
assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
|
assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
|
||||||
window->drawingBuffer = window->pendingBuffer = NULL;
|
window->drawingBuffer = window->pendingBuffer = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->drawingBuffer = window->pendingBuffer = &window->buffers[0];
|
window->drawingBuffer = window->pendingBuffer = &window->buffers[0];
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
event->width = window->width;
|
event->width = window->width;
|
||||||
event->height = window->height;
|
event->height = window->height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ivi_surface_listener ivi_surface_listener = {
|
static const struct ivi_surface_listener ivi_surface_listener =
|
||||||
|
{
|
||||||
ivi_handle_configure,
|
ivi_handle_configure,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void shell_ping(void *data, struct wl_shell_surface *surface, uint32_t serial)
|
void shell_ping(void* data, struct wl_shell_surface* surface, uint32_t serial)
|
||||||
{
|
{
|
||||||
wl_shell_surface_pong(surface, serial);
|
wl_shell_surface_pong(surface, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shell_configure(void *data, struct wl_shell_surface *surface, uint32_t edges,
|
void shell_configure(void* data, struct wl_shell_surface* surface, uint32_t edges,
|
||||||
int32_t width, int32_t height)
|
int32_t width, int32_t height)
|
||||||
{
|
{
|
||||||
UwacWindow *window = (UwacWindow *)data;
|
UwacWindow* window = (UwacWindow*)data;
|
||||||
UwacConfigureEvent *event;
|
UwacConfigureEvent* event;
|
||||||
int ret;
|
int ret;
|
||||||
|
event = (UwacConfigureEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
|
||||||
|
|
||||||
event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
|
if (!event)
|
||||||
if(!event) {
|
{
|
||||||
assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n"));
|
assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY,
|
||||||
|
"failed to allocate a configure event\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event->window = window;
|
event->window = window;
|
||||||
event->states = 0;
|
event->states = 0;
|
||||||
if (width && height) {
|
|
||||||
|
if (width && height)
|
||||||
|
{
|
||||||
event->width = width;
|
event->width = width;
|
||||||
event->height = height;
|
event->height = height;
|
||||||
|
|
||||||
UwacWindowDestroyBuffers(window);
|
UwacWindowDestroyBuffers(window);
|
||||||
|
|
||||||
window->width = width;
|
window->width = width;
|
||||||
window->stride = width * bppFromShmFormat(window->format);
|
window->stride = width * bppFromShmFormat(window->format);
|
||||||
window->height = height;
|
window->height = height;
|
||||||
|
|
||||||
ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height,
|
ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height,
|
||||||
width, height, window->format);
|
width, height, window->format);
|
||||||
if (ret != UWAC_SUCCESS) {
|
|
||||||
|
if (ret != UWAC_SUCCESS)
|
||||||
|
{
|
||||||
assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
|
assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
|
||||||
window->drawingBuffer = window->pendingBuffer = NULL;
|
window->drawingBuffer = window->pendingBuffer = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->drawingBuffer = window->pendingBuffer = &window->buffers[0];
|
window->drawingBuffer = window->pendingBuffer = &window->buffers[0];
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
event->width = window->width;
|
event->width = window->width;
|
||||||
event->height = window->height;
|
event->height = window->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void shell_popup_done(void *data, struct wl_shell_surface *surface)
|
void shell_popup_done(void* data, struct wl_shell_surface* surface)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct wl_shell_surface_listener shell_listener = {
|
static const struct wl_shell_surface_listener shell_listener =
|
||||||
|
{
|
||||||
shell_ping,
|
shell_ping,
|
||||||
shell_configure,
|
shell_configure,
|
||||||
shell_popup_done
|
shell_popup_done
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int UwacWindowShmAllocBuffers(UwacWindow *w, int nbuffers, int allocSize, uint32_t width,
|
int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32_t width,
|
||||||
uint32_t height, enum wl_shm_format format)
|
uint32_t height, enum wl_shm_format format)
|
||||||
{
|
{
|
||||||
int ret = UWAC_SUCCESS;
|
int ret = UWAC_SUCCESS;
|
||||||
UwacBuffer *newBuffers;
|
UwacBuffer* newBuffers;
|
||||||
int i, fd;
|
int i, fd;
|
||||||
void *data;
|
void* data;
|
||||||
struct wl_shm_pool *pool;
|
struct wl_shm_pool* pool;
|
||||||
|
|
||||||
newBuffers = realloc(w->buffers, (w->nbuffers + nbuffers) * sizeof(UwacBuffer));
|
newBuffers = realloc(w->buffers, (w->nbuffers + nbuffers) * sizeof(UwacBuffer));
|
||||||
|
|
||||||
if (!newBuffers)
|
if (!newBuffers)
|
||||||
return UWAC_ERROR_NOMEMORY;
|
return UWAC_ERROR_NOMEMORY;
|
||||||
|
|
||||||
w->buffers = newBuffers;
|
w->buffers = newBuffers;
|
||||||
|
|
||||||
memset(w->buffers + w->nbuffers, 0, sizeof(UwacBuffer) * nbuffers);
|
memset(w->buffers + w->nbuffers, 0, sizeof(UwacBuffer) * nbuffers);
|
||||||
|
|
||||||
fd = uwac_create_anonymous_file(allocSize * nbuffers);
|
fd = uwac_create_anonymous_file(allocSize * nbuffers);
|
||||||
if (fd < 0) {
|
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
return UWAC_ERROR_INTERNAL;
|
return UWAC_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = mmap(NULL, allocSize * nbuffers, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
data = mmap(NULL, allocSize * nbuffers, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
if (data == MAP_FAILED) {
|
|
||||||
|
if (data == MAP_FAILED)
|
||||||
|
{
|
||||||
ret = UWAC_ERROR_NOMEMORY;
|
ret = UWAC_ERROR_NOMEMORY;
|
||||||
goto error_mmap;
|
goto error_mmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
pool = wl_shm_create_pool(w->display->shm, fd, allocSize * nbuffers);
|
pool = wl_shm_create_pool(w->display->shm, fd, allocSize * nbuffers);
|
||||||
if (!pool) {
|
|
||||||
|
if (!pool)
|
||||||
|
{
|
||||||
ret = UWAC_ERROR_NOMEMORY;
|
ret = UWAC_ERROR_NOMEMORY;
|
||||||
goto error_mmap;
|
goto error_mmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < nbuffers; i++) {
|
for (i = 0; i < nbuffers; i++)
|
||||||
UwacBuffer *buffer = &w->buffers[w->nbuffers + i];
|
{
|
||||||
|
UwacBuffer* buffer = &w->buffers[w->nbuffers + i];
|
||||||
#ifdef HAVE_PIXMAN_REGION
|
#ifdef HAVE_PIXMAN_REGION
|
||||||
pixman_region32_init(&buffer->damage);
|
pixman_region32_init(&buffer->damage);
|
||||||
#else
|
#else
|
||||||
region16_init(&buffer->damage);
|
region16_init(&buffer->damage);
|
||||||
#endif
|
#endif
|
||||||
buffer->data = data + (allocSize * i);
|
buffer->data = data + (allocSize * i);
|
||||||
|
buffer->wayland_buffer = wl_shm_pool_create_buffer(pool, allocSize * i, width, height, w->stride,
|
||||||
buffer->wayland_buffer = wl_shm_pool_create_buffer(pool, allocSize * i, width, height, w->stride, format);
|
format);
|
||||||
wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, buffer);
|
wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, buffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_shm_pool_destroy(pool);
|
wl_shm_pool_destroy(pool);
|
||||||
w->nbuffers += nbuffers;
|
w->nbuffers += nbuffers;
|
||||||
|
|
||||||
error_mmap:
|
error_mmap:
|
||||||
close(fd);
|
close(fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
UwacBuffer *UwacWindowFindFreeBuffer(UwacWindow *w) {
|
UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w)
|
||||||
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
for (i = 0; i < w->nbuffers; i++) {
|
for (i = 0; i < w->nbuffers; i++)
|
||||||
if (!w->buffers[i].used) {
|
{
|
||||||
|
if (!w->buffers[i].used)
|
||||||
|
{
|
||||||
w->buffers[i].used = true;
|
w->buffers[i].used = true;
|
||||||
return &w->buffers[i];
|
return &w->buffers[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = UwacWindowShmAllocBuffers(w, 2, w->stride * w->height, w->width, w->height, w->format);
|
ret = UwacWindowShmAllocBuffers(w, 2, w->stride * w->height, w->width, w->height, w->format);
|
||||||
if (ret != UWAC_SUCCESS) {
|
|
||||||
|
if (ret != UWAC_SUCCESS)
|
||||||
|
{
|
||||||
w->display->last_error = ret;
|
w->display->last_error = ret;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -344,17 +382,21 @@ UwacBuffer *UwacWindowFindFreeBuffer(UwacWindow *w) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format) {
|
UwacWindow* UwacCreateWindowShm(UwacDisplay* display, uint32_t width, uint32_t height,
|
||||||
UwacWindow *w;
|
enum wl_shm_format format)
|
||||||
|
{
|
||||||
|
UwacWindow* w;
|
||||||
int allocSize, ret;
|
int allocSize, ret;
|
||||||
|
|
||||||
if (!display) {
|
if (!display)
|
||||||
display->last_error = UWAC_ERROR_INVALID_DISPLAY;
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
w = zalloc(sizeof(*w));
|
w = zalloc(sizeof(*w));
|
||||||
if (!w) {
|
|
||||||
|
if (!w)
|
||||||
|
{
|
||||||
display->last_error = UWAC_ERROR_NOMEMORY;
|
display->last_error = UWAC_ERROR_NOMEMORY;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -365,60 +407,65 @@ UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t h
|
|||||||
w->height = height;
|
w->height = height;
|
||||||
w->stride = width * bppFromShmFormat(format);
|
w->stride = width * bppFromShmFormat(format);
|
||||||
allocSize = w->stride * height;
|
allocSize = w->stride * height;
|
||||||
|
|
||||||
ret = UwacWindowShmAllocBuffers(w, UWAC_INITIAL_BUFFERS, allocSize, width, height, format);
|
ret = UwacWindowShmAllocBuffers(w, UWAC_INITIAL_BUFFERS, allocSize, width, height, format);
|
||||||
if (ret != UWAC_SUCCESS) {
|
|
||||||
|
if (ret != UWAC_SUCCESS)
|
||||||
|
{
|
||||||
display->last_error = ret;
|
display->last_error = ret;
|
||||||
goto out_error_free;
|
goto out_error_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
w->buffers[0].used = true;
|
w->buffers[0].used = true;
|
||||||
w->drawingBuffer = &w->buffers[0];
|
w->drawingBuffer = &w->buffers[0];
|
||||||
|
|
||||||
w->surface = wl_compositor_create_surface(display->compositor);
|
w->surface = wl_compositor_create_surface(display->compositor);
|
||||||
if (!w->surface) {
|
|
||||||
|
if (!w->surface)
|
||||||
|
{
|
||||||
display->last_error = UWAC_ERROR_NOMEMORY;
|
display->last_error = UWAC_ERROR_NOMEMORY;
|
||||||
goto out_error_surface;
|
goto out_error_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_surface_set_user_data(w->surface, w);
|
wl_surface_set_user_data(w->surface, w);
|
||||||
|
|
||||||
if (display->xdg_shell) {
|
if (display->xdg_shell)
|
||||||
|
{
|
||||||
w->xdg_surface = xdg_shell_get_xdg_surface(display->xdg_shell, w->surface);
|
w->xdg_surface = xdg_shell_get_xdg_surface(display->xdg_shell, w->surface);
|
||||||
if (!w->xdg_surface) {
|
|
||||||
|
if (!w->xdg_surface)
|
||||||
|
{
|
||||||
display->last_error = UWAC_ERROR_NOMEMORY;
|
display->last_error = UWAC_ERROR_NOMEMORY;
|
||||||
goto out_error_shell;
|
goto out_error_shell;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(w->xdg_surface);
|
assert(w->xdg_surface);
|
||||||
|
|
||||||
xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w);
|
xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w);
|
||||||
#if BUILD_IVI
|
#if BUILD_IVI
|
||||||
} else if (display->ivi_application) {
|
}
|
||||||
|
else if (display->ivi_application)
|
||||||
|
{
|
||||||
w->ivi_surface = ivi_application_surface_create(display->ivi_application, 1, w->surface);
|
w->ivi_surface = ivi_application_surface_create(display->ivi_application, 1, w->surface);
|
||||||
|
assert(w->ivi_surface);
|
||||||
assert (w->ivi_surface);
|
|
||||||
|
|
||||||
ivi_surface_add_listener(w->ivi_surface, &ivi_surface_listener, w);
|
ivi_surface_add_listener(w->ivi_surface, &ivi_surface_listener, w);
|
||||||
#endif
|
#endif
|
||||||
#if BUILD_FULLSCREEN_SHELL
|
#if BUILD_FULLSCREEN_SHELL
|
||||||
} else if (display->fullscreen_shell) {
|
}
|
||||||
|
else if (display->fullscreen_shell)
|
||||||
|
{
|
||||||
_wl_fullscreen_shell_present_surface(display->fullscreen_shell, w->surface,
|
_wl_fullscreen_shell_present_surface(display->fullscreen_shell, w->surface,
|
||||||
_WL_FULLSCREEN_SHELL_PRESENT_METHOD_CENTER, NULL);
|
_WL_FULLSCREEN_SHELL_PRESENT_METHOD_CENTER, NULL);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
w->shell_surface = wl_shell_get_shell_surface(display->shell, w->surface);
|
w->shell_surface = wl_shell_get_shell_surface(display->shell, w->surface);
|
||||||
|
|
||||||
assert(w->shell_surface);
|
assert(w->shell_surface);
|
||||||
|
|
||||||
wl_shell_surface_add_listener(w->shell_surface, &shell_listener, w);
|
wl_shell_surface_add_listener(w->shell_surface, &shell_listener, w);
|
||||||
wl_shell_surface_set_toplevel(w->shell_surface);
|
wl_shell_surface_set_toplevel(w->shell_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_list_insert(display->windows.prev, &w->link);
|
wl_list_insert(display->windows.prev, &w->link);
|
||||||
|
|
||||||
display->last_error = UWAC_SUCCESS;
|
display->last_error = UWAC_SUCCESS;
|
||||||
return w;
|
return w;
|
||||||
|
|
||||||
out_error_shell:
|
out_error_shell:
|
||||||
wl_surface_destroy(w->surface);
|
wl_surface_destroy(w->surface);
|
||||||
out_error_surface:
|
out_error_surface:
|
||||||
@ -429,11 +476,10 @@ out_error_free:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacReturnCode UwacDestroyWindow(UwacWindow **pwindow) {
|
UwacReturnCode UwacDestroyWindow(UwacWindow** pwindow)
|
||||||
UwacWindow *w;
|
{
|
||||||
|
UwacWindow* w;
|
||||||
assert (pwindow);
|
assert(pwindow);
|
||||||
|
|
||||||
w = *pwindow;
|
w = *pwindow;
|
||||||
UwacWindowDestroyBuffers(w);
|
UwacWindowDestroyBuffers(w);
|
||||||
|
|
||||||
@ -442,9 +488,12 @@ UwacReturnCode UwacDestroyWindow(UwacWindow **pwindow) {
|
|||||||
|
|
||||||
if (w->xdg_surface)
|
if (w->xdg_surface)
|
||||||
xdg_surface_destroy(w->xdg_surface);
|
xdg_surface_destroy(w->xdg_surface);
|
||||||
|
|
||||||
#if BUILD_IVI
|
#if BUILD_IVI
|
||||||
|
|
||||||
if (w->ivi_surface)
|
if (w->ivi_surface)
|
||||||
ivi_surface_destroy(w->ivi_surface);
|
ivi_surface_destroy(w->ivi_surface);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (w->opaque_region)
|
if (w->opaque_region)
|
||||||
@ -456,13 +505,12 @@ UwacReturnCode UwacDestroyWindow(UwacWindow **pwindow) {
|
|||||||
wl_surface_destroy(w->surface);
|
wl_surface_destroy(w->surface);
|
||||||
wl_list_remove(&w->link);
|
wl_list_remove(&w->link);
|
||||||
free(w);
|
free(w);
|
||||||
|
|
||||||
*pwindow = NULL;
|
*pwindow = NULL;
|
||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width,
|
UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow* window, uint32_t x, uint32_t y, uint32_t width,
|
||||||
uint32_t height)
|
uint32_t height)
|
||||||
{
|
{
|
||||||
assert(window);
|
assert(window);
|
||||||
@ -471,6 +519,7 @@ UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_
|
|||||||
wl_region_destroy(window->opaque_region);
|
wl_region_destroy(window->opaque_region);
|
||||||
|
|
||||||
window->opaque_region = wl_compositor_create_region(window->display->compositor);
|
window->opaque_region = wl_compositor_create_region(window->display->compositor);
|
||||||
|
|
||||||
if (!window->opaque_region)
|
if (!window->opaque_region)
|
||||||
return UWAC_ERROR_NOMEMORY;
|
return UWAC_ERROR_NOMEMORY;
|
||||||
|
|
||||||
@ -479,13 +528,16 @@ UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_
|
|||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
|
UwacReturnCode UwacWindowSetInputRegion(UwacWindow* window, uint32_t x, uint32_t y, uint32_t width,
|
||||||
|
uint32_t height)
|
||||||
|
{
|
||||||
assert(window);
|
assert(window);
|
||||||
|
|
||||||
if (window->input_region)
|
if (window->input_region)
|
||||||
wl_region_destroy(window->input_region);
|
wl_region_destroy(window->input_region);
|
||||||
|
|
||||||
window->input_region = wl_compositor_create_region(window->display->compositor);
|
window->input_region = wl_compositor_create_region(window->display->compositor);
|
||||||
|
|
||||||
if (!window->input_region)
|
if (!window->input_region)
|
||||||
return UWAC_ERROR_NOMEMORY;
|
return UWAC_ERROR_NOMEMORY;
|
||||||
|
|
||||||
@ -495,35 +547,41 @@ UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *UwacWindowGetDrawingBuffer(UwacWindow *window) {
|
void* UwacWindowGetDrawingBuffer(UwacWindow* window)
|
||||||
|
{
|
||||||
return window->drawingBuffer->data;
|
return window->drawingBuffer->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frame_done_cb(void *data, struct wl_callback *callback, uint32_t time);
|
static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t time);
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener = {
|
static const struct wl_callback_listener frame_listener =
|
||||||
|
{
|
||||||
frame_done_cb
|
frame_done_cb
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void UwacSubmitBufferPtr(UwacWindow *window, UwacBuffer *buffer) {
|
static void UwacSubmitBufferPtr(UwacWindow* window, UwacBuffer* buffer)
|
||||||
|
{
|
||||||
UINT32 nrects, i;
|
UINT32 nrects, i;
|
||||||
#ifdef HAVE_PIXMAN_REGION
|
#ifdef HAVE_PIXMAN_REGION
|
||||||
const pixman_box32_t *box;
|
const pixman_box32_t* box;
|
||||||
#else
|
#else
|
||||||
const RECTANGLE_16 *box;
|
const RECTANGLE_16* box;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wl_surface_attach(window->surface, buffer->wayland_buffer, 0, 0);
|
wl_surface_attach(window->surface, buffer->wayland_buffer, 0, 0);
|
||||||
|
|
||||||
#ifdef HAVE_PIXMAN_REGION
|
#ifdef HAVE_PIXMAN_REGION
|
||||||
box = pixman_region32_rectangles(&buffer->damage, &nrects);
|
box = pixman_region32_rectangles(&buffer->damage, &nrects);
|
||||||
|
|
||||||
for (i = 0; i < nrects; i++, box++)
|
for (i = 0; i < nrects; i++, box++)
|
||||||
wl_surface_damage(window->surface, box->x1, box->y1, (box->x2 - box->x1), (box->y2 - box->y1));
|
wl_surface_damage(window->surface, box->x1, box->y1, (box->x2 - box->x1), (box->y2 - box->y1));
|
||||||
|
|
||||||
#else
|
#else
|
||||||
box = region16_rects(&buffer->damage, &nrects);
|
box = region16_rects(&buffer->damage, &nrects);
|
||||||
|
|
||||||
for (i = 0; i < nrects; i++, box++)
|
for (i = 0; i < nrects; i++, box++)
|
||||||
wl_surface_damage(window->surface, box->left, box->top, (box->right - box->left), (box->bottom - box->top));
|
wl_surface_damage(window->surface, box->left, box->top, (box->right - box->left),
|
||||||
|
(box->bottom - box->top));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (window->frame_callback)
|
if (window->frame_callback)
|
||||||
@ -531,9 +589,7 @@ static void UwacSubmitBufferPtr(UwacWindow *window, UwacBuffer *buffer) {
|
|||||||
|
|
||||||
window->frame_callback = wl_surface_frame(window->surface);
|
window->frame_callback = wl_surface_frame(window->surface);
|
||||||
wl_callback_add_listener(window->frame_callback, &frame_listener, window);
|
wl_callback_add_listener(window->frame_callback, &frame_listener, window);
|
||||||
|
|
||||||
wl_surface_commit(window->surface);
|
wl_surface_commit(window->surface);
|
||||||
|
|
||||||
#ifdef HAVE_PIXMAN_REGION
|
#ifdef HAVE_PIXMAN_REGION
|
||||||
pixman_region32_clear(&buffer->damage);
|
pixman_region32_clear(&buffer->damage);
|
||||||
#else
|
#else
|
||||||
@ -542,24 +598,32 @@ static void UwacSubmitBufferPtr(UwacWindow *window, UwacBuffer *buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void frame_done_cb(void *data, struct wl_callback *callback, uint32_t time) {
|
static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t time)
|
||||||
UwacWindow *window = (UwacWindow *)data;
|
{
|
||||||
UwacFrameDoneEvent *event;
|
UwacWindow* window = (UwacWindow*)data;
|
||||||
|
UwacFrameDoneEvent* event;
|
||||||
window->pendingBuffer = NULL;
|
window->pendingBuffer = NULL;
|
||||||
event = (UwacFrameDoneEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE);
|
event = (UwacFrameDoneEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE);
|
||||||
if(event)
|
|
||||||
|
if (event)
|
||||||
event->window = window;
|
event->window = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
|
UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, uint32_t width,
|
||||||
|
uint32_t height)
|
||||||
|
{
|
||||||
#ifdef HAVE_PIXMAN_REGION
|
#ifdef HAVE_PIXMAN_REGION
|
||||||
if (!pixman_region32_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, x, y, width, height))
|
|
||||||
|
if (!pixman_region32_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, x,
|
||||||
|
y, width, height))
|
||||||
#else
|
#else
|
||||||
RECTANGLE_16 box;
|
RECTANGLE_16 box;
|
||||||
box.left = x; box.top = y;
|
|
||||||
box.right = x + width; box.bottom = y + height;
|
box.left = x;
|
||||||
|
box.top = y;
|
||||||
|
box.right = x + width;
|
||||||
|
box.bottom = y + height;
|
||||||
|
|
||||||
if (!region16_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, &box))
|
if (!region16_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, &box))
|
||||||
#endif
|
#endif
|
||||||
@ -569,50 +633,61 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, u
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame) {
|
UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame)
|
||||||
UwacBuffer *drawingBuffer = window->drawingBuffer;
|
{
|
||||||
|
UwacBuffer* drawingBuffer = window->drawingBuffer;
|
||||||
|
|
||||||
if (window->pendingBuffer) {
|
if (window->pendingBuffer)
|
||||||
|
{
|
||||||
/* we already have a pending frame, don't do anything*/
|
/* we already have a pending frame, don't do anything*/
|
||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UwacSubmitBufferPtr(window, drawingBuffer);
|
UwacSubmitBufferPtr(window, drawingBuffer);
|
||||||
|
|
||||||
window->pendingBuffer = window->drawingBuffer;
|
window->pendingBuffer = window->drawingBuffer;
|
||||||
window->drawingBuffer = UwacWindowFindFreeBuffer(window);
|
window->drawingBuffer = UwacWindowFindFreeBuffer(window);
|
||||||
|
|
||||||
if (!window->drawingBuffer)
|
if (!window->drawingBuffer)
|
||||||
return UWAC_ERROR_NOMEMORY;
|
return UWAC_ERROR_NOMEMORY;
|
||||||
|
|
||||||
if (copyContentForNextFrame) {
|
if (copyContentForNextFrame)
|
||||||
|
{
|
||||||
memcpy(window->drawingBuffer->data, window->pendingBuffer->data, window->stride * window->height);
|
memcpy(window->drawingBuffer->data, window->pendingBuffer->data, window->stride * window->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry) {
|
UwacReturnCode UwacWindowGetGeometry(UwacWindow* window, UwacSize* geometry)
|
||||||
|
{
|
||||||
assert(window);
|
assert(window);
|
||||||
assert(geometry);
|
assert(geometry);
|
||||||
|
|
||||||
geometry->width = window->width;
|
geometry->width = window->width;
|
||||||
geometry->height = window->height;
|
geometry->height = window->height;
|
||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen) {
|
UwacReturnCode UwacWindowSetFullscreenState(UwacWindow* window, UwacOutput* output,
|
||||||
if (window->xdg_surface) {
|
bool isFullscreen)
|
||||||
if (isFullscreen) {
|
{
|
||||||
|
if (window->xdg_surface)
|
||||||
|
{
|
||||||
|
if (isFullscreen)
|
||||||
|
{
|
||||||
xdg_surface_set_fullscreen(window->xdg_surface, output ? output->output : NULL);
|
xdg_surface_set_fullscreen(window->xdg_surface, output ? output->output : NULL);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
xdg_surface_unset_fullscreen(window->xdg_surface);
|
xdg_surface_unset_fullscreen(window->xdg_surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return UWAC_SUCCESS;
|
return UWAC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwacWindowSetTitle(UwacWindow *window, const char *name) {
|
void UwacWindowSetTitle(UwacWindow* window, const char* name)
|
||||||
|
{
|
||||||
if (window->xdg_surface)
|
if (window->xdg_surface)
|
||||||
xdg_surface_set_title(window->xdg_surface, name);
|
xdg_surface_set_title(window->xdg_surface, name);
|
||||||
else if (window->shell_surface)
|
else if (window->shell_surface)
|
||||||
|
Loading…
Reference in New Issue
Block a user