summaryrefslogtreecommitdiffstats
path: root/video/out/wayland_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/wayland_common.c')
-rw-r--r--video/out/wayland_common.c341
1 files changed, 82 insertions, 259 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index b1f08fce4d..9c1d5ffe55 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -26,12 +26,10 @@
#include <inttypes.h>
#include <limits.h>
#include <assert.h>
-#include <fcntl.h>
+#include <poll.h>
#include <unistd.h>
#include <sys/mman.h>
-#include <sys/epoll.h>
-#include <sys/timerfd.h>
#include <linux/input.h>
#include "config.h"
@@ -57,12 +55,14 @@
#define MOD_ALT_MASK 0x02
#define MOD_CONTROL_MASK 0x04
-#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
-
static int lookupkey(int key);
static void hide_cursor(struct vo_wayland_state * wl);
static void show_cursor(struct vo_wayland_state * wl);
+static void resize_window(struct vo_wayland_state *wl,
+ uint32_t edges,
+ int32_t width,
+ int32_t height);
/*** wayland interface ***/
@@ -75,16 +75,6 @@ static void ssurface_handle_ping(void *data,
wl_shell_surface_pong(shell_surface, serial);
}
-static void ssurface_schedule_resize(struct vo_wayland_window *window,
- int32_t width,
- int32_t height)
-{
- window->pending_width = width;
- window->pending_height = height;
- window->resize_needed = 1;
- window->events |= VO_EVENT_RESIZE;
-}
-
static void ssurface_handle_configure(void *data,
struct wl_shell_surface *shell_surface,
uint32_t edges,
@@ -92,9 +82,7 @@ static void ssurface_handle_configure(void *data,
int32_t height)
{
struct vo_wayland_state *wl = data;
-
- wl->window->edges = edges;
- ssurface_schedule_resize(wl->window, width, height);
+ resize_window(wl, edges, width, height);
}
static void ssurface_handle_popup_done(void *data,
@@ -142,20 +130,14 @@ static void output_handle_mode(void *data,
int32_t height,
int32_t refresh)
{
- struct vo_wayland_display *d = data;
- struct vo_wayland_output *output;
+ struct vo_wayland_output *output = data;
- wl_list_for_each(output, &d->output_list, link) {
- if (wl_output == output->output) {
- output->width = width;
- output->height = height;
- if (flags)
- output->flags = flags;
- }
- }
+ if (!output)
+ return;
- /* one output is enough */
- d->output_mode_received = 1;
+ output->width = width;
+ output->height = height;
+ output->flags = flags;
}
const struct wl_output_listener output_listener = {
@@ -219,15 +201,10 @@ static void keyboard_handle_keymap(void *data,
int32_t fd,
uint32_t size)
{
- struct vo_wayland_input *input = ((struct vo_wayland_state *) data)->input;
+ struct vo_wayland_input *input;
char *map_str;
- if(!data) {
- close(fd);
- return;
- }
-
- if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
+ if(!data || format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
close(fd);
return;
}
@@ -238,8 +215,9 @@ static void keyboard_handle_keymap(void *data,
return;
}
- input->xkb.keymap = xkb_map_new_from_string(input->xkb.context,
- map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
+ input = ((struct vo_wayland_state *) data)->input;
+ input->xkb.keymap = xkb_keymap_new_from_buffer(input->xkb.context,
+ map_str, size, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
munmap(map_str, size);
close(fd);
@@ -256,13 +234,6 @@ static void keyboard_handle_keymap(void *data,
input->xkb.keymap = NULL;
return;
}
-
- input->xkb.control_mask =
- 1 << xkb_map_mod_get_index(input->xkb.keymap, "Control");
- input->xkb.alt_mask =
- 1 << xkb_map_mod_get_index(input->xkb.keymap, "Mod1");
- input->xkb.shift_mask =
- 1 << xkb_map_mod_get_index(input->xkb.keymap, "Shift");
}
static void keyboard_handle_enter(void *data,
@@ -290,60 +261,24 @@ static void keyboard_handle_key(void *data,
struct vo_wayland_state *wl = data;
struct vo_wayland_input *input = wl->input;
uint32_t code, num_syms;
-
- struct itimerspec its = {{0, 0}, {0, 0}};
+ int mpkey;
const xkb_keysym_t *syms;
xkb_keysym_t sym;
- xkb_mod_mask_t mask;
code = key + 8;
num_syms = xkb_key_get_syms(input->xkb.state, code, &syms);
- mask = xkb_state_serialize_mods(input->xkb.state,
- XKB_STATE_DEPRESSED | XKB_STATE_LATCHED);
-
- input->modifiers = 0;
- if (mask & input->xkb.control_mask)
- input->modifiers |= MOD_CONTROL_MASK;
- if (mask & input->xkb.alt_mask)
- input->modifiers |= MOD_ALT_MASK;
- if (mask & input->xkb.shift_mask)
- input->modifiers |= MOD_SHIFT_MASK;
-
sym = XKB_KEY_NoSymbol;
if (num_syms == 1)
sym = syms[0];
- if (sym != XKB_KEY_NoSymbol && state == WL_KEYBOARD_KEY_STATE_PRESSED) {
- int mpkey = lookupkey(sym);
- if (mpkey)
+ if (sym != XKB_KEY_NoSymbol && (mpkey = lookupkey(sym))) {
+ if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
+ mplayer_put_key(wl->vo->key_fifo, mpkey | MP_KEY_STATE_DOWN);
+ else
mplayer_put_key(wl->vo->key_fifo, mpkey);
}
-
- if (state == WL_KEYBOARD_KEY_STATE_RELEASED && key == input->repeat.key) {
- input->repeat.sym = 0;
- input->repeat.key = 0;
- input->repeat.time = 0;
- }
- else if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
- if (input->repeat.key == key) {
- its.it_interval.tv_sec = 0;
- its.it_interval.tv_nsec = 20 * 1000 * 1000;
- its.it_value.tv_sec = 0;
- its.it_value.tv_nsec = 100 * 1000 * 1000;
- }
- else {
- input->repeat.sym = sym;
- input->repeat.key = key;
- input->repeat.time = time;
- its.it_interval.tv_sec = 0;
- its.it_interval.tv_nsec = 25 * 1000 * 1000;
- its.it_value.tv_sec = 0;
- its.it_value.tv_nsec = 400 * 1000 * 1000;
- }
- }
- timerfd_settime(input->repeat.timer_fd, 0, &its, NULL);
}
static void keyboard_handle_modifiers(void *data,
@@ -411,20 +346,8 @@ static void pointer_handle_motion(void *data,
display->cursor.pointer = pointer;
- if (wl->window->type == TYPE_FULLSCREEN) {
+ if (wl->window->type == TYPE_FULLSCREEN)
show_cursor(wl);
-
- struct itimerspec its;
- int ms = wl->vo->opts->cursor_autohide_delay;
- int sec = ms / 1000;
- ms %= 1000;
-
- its.it_interval.tv_sec = 0;
- its.it_interval.tv_nsec = 100 * 1000 * 1000;
- its.it_value.tv_sec = sec;
- its.it_value.tv_nsec = ms * 1000 * 1000;
- timerfd_settime(display->cursor.timer_fd, 0, &its, NULL);
- }
}
static void pointer_handle_button(void *data,
@@ -441,7 +364,6 @@ static void pointer_handle_button(void *data,
if ((button == BTN_LEFT) && (state == WL_POINTER_BUTTON_STATE_PRESSED))
wl_shell_surface_move(wl->window->shell_surface, wl->input->seat, serial);
-
}
static void pointer_handle_axis(void *data,
@@ -550,7 +472,7 @@ static void registry_handle_global (void *data,
&wl_output_interface,
1);
- wl_output_add_listener(output->output, &output_listener, d);
+ wl_output_add_listener(output->output, &output_listener, output);
wl_list_insert(&d->output_list, &output->link);
}
@@ -579,40 +501,6 @@ static const struct wl_registry_listener registry_listener = {
/*** internal functions ***/
-static int set_cloexec_or_close(int fd)
-{
- long flags;
-
- if (fd == -1)
- return -1;
-
- if ((flags = fcntl(fd, F_GETFD)) == -1)
- goto err;
-
- if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
- goto err;
-
- return fd;
-
-err:
- close(fd);
- return -1;
-}
-
-static int os_epoll_create_cloexec(void)
-{
- int fd;
-
-#ifdef EPOLL_CLOEXEC
- if ((fd = epoll_create1(EPOLL_CLOEXEC)) >= 0)
- return fd;
- if (errno != EINVAL)
- return -1;
-#endif
-
- return set_cloexec_or_close(epoll_create(1));
-}
-
static int lookupkey(int key)
{
static const char *passthrough_keys
@@ -639,6 +527,7 @@ static void hide_cursor (struct vo_wayland_state *wl)
wl_pointer_set_cursor(display->cursor.pointer, display->cursor.serial,
NULL, 0, 0);
+
}
static void show_cursor (struct vo_wayland_state *wl)
@@ -658,77 +547,25 @@ static void show_cursor (struct vo_wayland_state *wl)
wl_surface_damage(display->cursor.surface, 0, 0,
image->width, image->height);
wl_surface_commit(display->cursor.surface);
-}
-static void
-display_watch_fd(struct vo_wayland_display *display,
- int fd, uint32_t events, struct vo_wayland_task *task)
-{
- struct epoll_event ep;
-
- if (display->epoll_fd < 0) {
- mp_msg(MSGT_VO, MSGL_WARN, "[wayland] Could not watch fd\n");
- return;
- }
-
- ep.events = events;
- ep.data.ptr = task;
- epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep);
+ display->cursor.mouse_timer = GetTimerMS() + wl->vo->opts->cursor_autohide_delay;
+ display->cursor.mouse_waiting_hide = true;
}
-static void display_handle_data(struct vo_wayland_task *task,
- uint32_t events,
- struct vo_wayland_state *wl)
+static void resize_window(struct vo_wayland_state *wl,
+ uint32_t edges,
+ int32_t width,
+ int32_t height)
{
- struct vo_wayland_display *display = wl->display;
- struct epoll_event ep;
- int ret;
-
- if (events & EPOLLERR || events & EPOLLHUP)
- exit(-1);
-
- if (events & EPOLLIN) {
- ret = wl_display_dispatch(display->display);
- if (ret == -1)
- exit(-1);
+ struct vo_wayland_window *w = wl->window;
+ if (w->resize_func && w->resize_func_data) {
+ w->resize_func(wl, edges, width, height, w->resize_func_data);
+ w->events |= VO_EVENT_RESIZE;
}
-
- if (events & EPOLLOUT) {
- ret = wl_display_flush(display->display);
- if (ret == 0) {
- ep.events = EPOLLIN | EPOLLERR | EPOLLHUP;
- ep.data.ptr = &display->display_task;
- epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD,
- display->display_fd, &ep);
- } else if (ret == -1 && errno != EAGAIN)
- exit(-1);
- }
-}
-
-static void cursor_timer_func(struct vo_wayland_task *task,
- uint32_t events,
- struct vo_wayland_state *wl)
-{
- if (wl->window->type == TYPE_FULLSCREEN)
- hide_cursor(wl);
+ else
+ mp_msg(MSGT_VO, MSGL_WARN, "[waylnad] No resizing possible!\n");
}
-static void keyboard_timer_func(struct vo_wayland_task *task,
- uint32_t events,
- struct vo_wayland_state *wl)
-{
- struct vo_wayland_input *input = wl->input;
- uint64_t exp;
-
- if (read(input->repeat.timer_fd, &exp, sizeof exp) != sizeof exp)
- /* If we change the timer between the fd becoming
- * readable and getting here, there'll be nothing to
- * read and we get EAGAIN. */
- return;
-
- keyboard_handle_key(wl, input->keyboard, 0, input->repeat.time,
- input->repeat.key, WL_KEYBOARD_KEY_STATE_PRESSED);
-}
static bool create_display (struct vo_wayland_state *wl)
{
@@ -754,11 +591,7 @@ static bool create_display (struct vo_wayland_state *wl)
d->cursor.surface =
wl_compositor_create_surface(d->compositor);
- d->epoll_fd = os_epoll_create_cloexec();
d->display_fd = wl_display_get_fd(d->display);
- d->display_task.run = display_handle_data;
- display_watch_fd(d, d->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP,
- &d->display_task);
return true;
}
@@ -804,9 +637,6 @@ static void create_window (struct vo_wayland_state *wl)
static void destroy_window (struct vo_wayland_state *wl)
{
- if (wl->window->callback)
- wl_callback_destroy(wl->window->callback);
-
wl_shell_surface_destroy(wl->window->shell_surface);
wl_surface_destroy(wl->window->surface);
}
@@ -839,29 +669,6 @@ static void destroy_input (struct vo_wayland_state *wl)
xkb_context_unref(wl->input->xkb.context);
}
-static void create_timers (struct vo_wayland_state *wl)
-{
- struct vo_wayland_display *d = wl->display;
- struct vo_wayland_input *i = wl->input;
-
- d->cursor.task.run = cursor_timer_func;
- d->cursor.timer_fd = timerfd_create(CLOCK_MONOTONIC,
- TFD_CLOEXEC | TFD_NONBLOCK);
- display_watch_fd(d, d->cursor.timer_fd, EPOLLIN, &d->cursor.task);
-
- i->repeat.task.run = keyboard_timer_func;
- i->repeat.timer_fd = timerfd_create(CLOCK_MONOTONIC,
- TFD_CLOEXEC | TFD_NONBLOCK);
- display_watch_fd(d, i->repeat.timer_fd, EPOLLIN, &i->repeat.task);
-}
-
-static void destroy_timers (struct vo_wayland_state *wl)
-{
- close(wl->input->repeat.timer_fd);
- close(wl->display->cursor.timer_fd);
-}
-
-
/*** mplayer2 interface ***/
int vo_wayland_init (struct vo *vo)
@@ -877,8 +684,7 @@ int vo_wayland_init (struct vo *vo)
return false;
}
- create_timers(wl);
- vo->event_fd = wl->display->epoll_fd;
+ vo->event_fd = wl->display->display_fd;
create_window(wl);
vo_wayland_update_window_title(vo);
@@ -888,7 +694,6 @@ int vo_wayland_init (struct vo *vo)
void vo_wayland_uninit (struct vo *vo)
{
struct vo_wayland_state *wl = vo->wayland;
- destroy_timers(wl);
destroy_input(wl);
destroy_window(wl);
destroy_display(wl);
@@ -944,8 +749,7 @@ void vo_wayland_fullscreen (struct vo *vo)
else {
wl_shell_surface_set_toplevel(wl->window->shell_surface);
- ssurface_schedule_resize(wl->window, wl->window->p_width,
- wl->window->p_height);
+ resize_window(wl, 0, wl->window->p_width, wl->window->p_height);
wl->window->type = TYPE_TOPLEVEL;
vo->opts->fs = false;
@@ -955,35 +759,45 @@ void vo_wayland_fullscreen (struct vo *vo)
int vo_wayland_check_events (struct vo *vo)
{
- struct vo_wayland_task *task;
struct vo_wayland_state *wl = vo->wayland;
- int i, ret, count;
- struct epoll_event ep[16];
-
- wl_display_dispatch_pending(wl->display->display);
-
- ret = wl_display_flush(wl->display->display);
-
- if (ret < 0 && errno == EAGAIN) {
- ep[0].events = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP;
- ep[0].data.ptr = NULL;
+ struct wl_display *dp = wl->display->display;
+ int ret;
- epoll_ctl(wl->display->epoll_fd, EPOLL_CTL_MOD,
- wl->display->display_fd, &ep[0]);
- }
- else if (ret < 0) {
- return 0;
+ if (wl->window->type == TYPE_FULLSCREEN &&
+ wl->display->cursor.mouse_waiting_hide &&
+ GetTimerMS() >= wl->display->cursor.mouse_timer)
+ {
+ hide_cursor(wl);
+ wl->display->cursor.mouse_waiting_hide = false;
}
- count = epoll_wait(wl->display->epoll_fd, ep, ARRAY_LENGTH(ep), 1);
+ wl_display_dispatch_pending(dp);
+ wl_display_flush(dp);
- for (i = 0; i < count; i++) {
- task = ep[i].data.ptr;
- task->run(task, ep[i].events, wl);
- }
+ struct pollfd fd = {
+ wl->display->display_fd,
+ POLLIN | POLLOUT | POLLERR | POLLHUP,
+ 0
+ };
+ /* wl_display_dispatch is blocking
+ * wl_dipslay_dispatch_pending is non-blocking but does not read from the fd
+ *
+ * when pausing no input events get queued so we have to check if there
+ * are events to read from the file descriptor through poll */
+ if (poll(&fd, 1, 0) > 0) {
+ if (fd.revents & POLLERR || fd.revents & POLLHUP)
+ mp_msg(MSGT_VO, MSGL_ERR, "[wayland] error occurred on fd\n");
+ if (fd.revents & POLLIN)
+ wl_display_dispatch(dp);
+ if (fd.revents & POLLOUT)
+ wl_display_flush(dp);
+ }
+
+ if (wl->display->cursor.mouse_waiting_hide)
+ vo->next_wakeup_time = FFMIN(vo->next_wakeup_time,
+ wl->display->cursor.mouse_timer);
ret = wl->window->events;
-
wl->window->events = 0;
return ret;
@@ -993,10 +807,9 @@ void vo_wayland_update_screeninfo (struct vo *vo)
{
struct vo_wayland_state *wl = vo->wayland;
struct mp_vo_opts *opts = vo->opts;
+ bool mode_received = false;
wl_display_roundtrip(wl->display->display);
- if (!wl->display->output_mode_received)
- mp_msg(MSGT_VO, MSGL_ERR, "[wayland] no output mode detected\n");
vo->xinerama_x = vo->xinerama_y = 0;
@@ -1007,6 +820,11 @@ void vo_wayland_update_screeninfo (struct vo *vo)
struct vo_wayland_output *fsscreen_output = NULL;
wl_list_for_each_reverse(output, &wl->display->output_list, link) {
+ if (!output || !output->width)
+ continue;
+
+ mode_received = true;
+
if (opts->fsscreen_id == screen_id)
fsscreen_output = output;
@@ -1016,6 +834,11 @@ void vo_wayland_update_screeninfo (struct vo *vo)
screen_id++;
}
+ if (!mode_received) {
+ mp_msg(MSGT_VO, MSGL_ERR, "[wayland] no output mode detected\n");
+ return;
+ }
+
if (fsscreen_output) {
wl->display->fs_output = fsscreen_output->output;
opts->screenwidth = fsscreen_output->width;