summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
Diffstat (limited to 'video/out')
-rw-r--r--video/out/cocoa_cb_common.swift10
-rw-r--r--video/out/d3d11/context.c42
-rw-r--r--video/out/d3d11/ra_d3d11.c20
-rw-r--r--video/out/hwdec/hwdec_cuda_vk.c2
-rw-r--r--video/out/hwdec/hwdec_vaapi.c6
-rw-r--r--video/out/opengl/context_x11egl.c1
-rw-r--r--video/out/opengl/egl_helpers.c111
-rw-r--r--video/out/vo.h2
-rw-r--r--video/out/vo_vaapi.c16
-rw-r--r--video/out/w32_common.c10
-rw-r--r--video/out/wayland_common.c171
-rw-r--r--video/out/x11_common.c36
-rw-r--r--video/out/x11_common.h2
13 files changed, 299 insertions, 130 deletions
diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift
index b2910dba85..4b4250c565 100644
--- a/video/out/cocoa_cb_common.swift
+++ b/video/out/cocoa_cb_common.swift
@@ -135,7 +135,6 @@ class CocoaCB: Common, EventSubscriber {
case MAC_CSP_AUTO: return colorSpace
case MAC_CSP_DISPLAY_P3: return CGColorSpace(name: CGColorSpace.displayP3)
case MAC_CSP_DISPLAY_P3_HLG: return CGColorSpace(name: CGColorSpace.displayP3_HLG)
- case MAC_CSP_DISPLAY_P3_PQ: return CGColorSpace(name: CGColorSpace.displayP3_PQ)
case MAC_CSP_DCI_P3: return CGColorSpace(name: CGColorSpace.dcip3)
case MAC_CSP_BT_2020: return CGColorSpace(name: CGColorSpace.itur_2020)
case MAC_CSP_BT_709: return CGColorSpace(name: CGColorSpace.itur_709)
@@ -146,6 +145,15 @@ class CocoaCB: Common, EventSubscriber {
default: break
}
+#if HAVE_MACOS_10_15_4_FEATURES
+ if #available(macOS 10.15.4, *) {
+ switch outputCsp {
+ case MAC_CSP_DISPLAY_P3_PQ: return CGColorSpace(name: CGColorSpace.displayP3_PQ)
+ default: break
+ }
+ }
+#endif
+
#if HAVE_MACOS_11_FEATURES
if #available(macOS 11.0, *) {
switch outputCsp {
diff --git a/video/out/d3d11/context.c b/video/out/d3d11/context.c
index f183ae8be5..488884eb53 100644
--- a/video/out/d3d11/context.c
+++ b/video/out/d3d11/context.c
@@ -99,8 +99,8 @@ struct priv {
struct pl_color_space swapchain_csp;
int64_t perf_freq;
- unsigned sync_refresh_count;
- int64_t sync_qpc_time;
+ unsigned last_sync_refresh_count;
+ int64_t last_sync_qpc_time;
int64_t vsync_duration_qpc;
int64_t last_submit_qpc;
};
@@ -156,8 +156,8 @@ static int d3d11_color_depth(struct ra_swapchain *sw)
struct priv *p = sw->priv;
DXGI_OUTPUT_DESC1 desc1;
- if (mp_get_dxgi_output_desc(p->swapchain, &desc1))
- return desc1.BitsPerColor;
+ if (!mp_get_dxgi_output_desc(p->swapchain, &desc1))
+ desc1.BitsPerColor = 0;
DXGI_SWAP_CHAIN_DESC desc;
@@ -165,15 +165,18 @@ static int d3d11_color_depth(struct ra_swapchain *sw)
if (FAILED(hr)) {
MP_ERR(sw->ctx, "Failed to query swap chain description: %s!\n",
mp_HRESULT_to_str(hr));
- return 0;
+ return desc1.BitsPerColor;
}
const struct ra_format *ra_fmt =
ra_d3d11_get_ra_format(sw->ctx->ra, desc.BufferDesc.Format);
- if (!ra_fmt)
- return 0;
+ if (!ra_fmt || !ra_fmt->component_depth[0])
+ return desc1.BitsPerColor;
+
+ if (!desc1.BitsPerColor)
+ return ra_fmt->component_depth[0];
- return ra_fmt->component_depth[0];
+ return MPMIN(ra_fmt->component_depth[0], desc1.BitsPerColor);
}
static bool d3d11_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
@@ -273,33 +276,28 @@ static void d3d11_get_vsync(struct ra_swapchain *sw, struct vo_vsync_info *info)
DXGI_FRAME_STATISTICS stats;
hr = IDXGISwapChain_GetFrameStatistics(p->swapchain, &stats);
if (hr == DXGI_ERROR_FRAME_STATISTICS_DISJOINT) {
- p->sync_refresh_count = 0;
- p->sync_qpc_time = 0;
+ p->last_sync_refresh_count = 0;
+ p->last_sync_qpc_time = 0;
}
if (FAILED(hr))
return;
- info->last_queue_display_time = 0;
- info->vsync_duration = 0;
// Detecting skipped vsyncs is possible but not supported yet
info->skipped_vsyncs = -1;
- // Get the number of physical vsyncs that have passed since the start of the
- // playback or disjoint event.
+ // Get the number of physical vsyncs that have passed since the last call.
// Check for 0 here, since sometimes GetFrameStatistics returns S_OK but
// with 0s in some (all?) members of DXGI_FRAME_STATISTICS.
unsigned src_passed = 0;
- if (stats.SyncRefreshCount && p->sync_refresh_count)
- src_passed = stats.SyncRefreshCount - p->sync_refresh_count;
- if (p->sync_refresh_count == 0)
- p->sync_refresh_count = stats.SyncRefreshCount;
+ if (stats.SyncRefreshCount && p->last_sync_refresh_count)
+ src_passed = stats.SyncRefreshCount - p->last_sync_refresh_count;
+ p->last_sync_refresh_count = stats.SyncRefreshCount;
// Get the elapsed time passed between the above vsyncs
unsigned sqt_passed = 0;
- if (stats.SyncQPCTime.QuadPart && p->sync_qpc_time)
- sqt_passed = stats.SyncQPCTime.QuadPart - p->sync_qpc_time;
- if (p->sync_qpc_time == 0)
- p->sync_qpc_time = stats.SyncQPCTime.QuadPart;
+ if (stats.SyncQPCTime.QuadPart && p->last_sync_qpc_time)
+ sqt_passed = stats.SyncQPCTime.QuadPart - p->last_sync_qpc_time;
+ p->last_sync_qpc_time = stats.SyncQPCTime.QuadPart;
// If any vsyncs have passed, estimate the physical frame rate
if (src_passed && sqt_passed)
diff --git a/video/out/d3d11/ra_d3d11.c b/video/out/d3d11/ra_d3d11.c
index 4438b2083c..2b35686111 100644
--- a/video/out/d3d11/ra_d3d11.c
+++ b/video/out/d3d11/ra_d3d11.c
@@ -1503,21 +1503,21 @@ static size_t vbuf_upload(struct ra *ra, void *data, size_t size)
}
static const char cache_magic[4] = "RD11";
-static const int cache_version = 3;
+static const uint32_t cache_version = 4;
struct cache_header {
char magic[sizeof(cache_magic)];
- int cache_version;
+ uint32_t cache_version;
char compiler[SPIRV_NAME_MAX_LEN];
- int spv_compiler_version;
- unsigned spvc_compiler_major;
- unsigned spvc_compiler_minor;
- unsigned spvc_compiler_patch;
+ int32_t spv_compiler_version;
+ uint32_t spvc_compiler_major;
+ uint32_t spvc_compiler_minor;
+ uint32_t spvc_compiler_patch;
struct dll_version d3d_compiler_version;
- int feature_level;
- size_t vert_bytecode_len;
- size_t frag_bytecode_len;
- size_t comp_bytecode_len;
+ int32_t feature_level;
+ uint32_t vert_bytecode_len;
+ uint32_t frag_bytecode_len;
+ uint32_t comp_bytecode_len;
};
static void load_cached_program(struct ra *ra,
diff --git a/video/out/hwdec/hwdec_cuda_vk.c b/video/out/hwdec/hwdec_cuda_vk.c
index f6fc49daa8..e744ff628a 100644
--- a/video/out/hwdec/hwdec_cuda_vk.c
+++ b/video/out/hwdec/hwdec_cuda_vk.c
@@ -25,6 +25,8 @@
#include <libavutil/hwcontext_cuda.h>
#include <libplacebo/vulkan.h>
+#include "osdep/io.h"
+
#if HAVE_WIN32_DESKTOP
#include <versionhelpers.h>
#define HANDLE_TYPE PL_HANDLE_WIN32
diff --git a/video/out/hwdec/hwdec_vaapi.c b/video/out/hwdec/hwdec_vaapi.c
index 6080ce9e05..504880ad4e 100644
--- a/video/out/hwdec/hwdec_vaapi.c
+++ b/video/out/hwdec/hwdec_vaapi.c
@@ -84,16 +84,18 @@ static const struct va_create_native create_native_cbs[] = {
#if HAVE_VAAPI_DRM
{"drm", create_drm_va_display},
#endif
+ {0}
};
static VADisplay *create_native_va_display(struct ra *ra, struct mp_log *log)
{
- for (int n = 0; n < MP_ARRAY_SIZE(create_native_cbs); n++) {
- const struct va_create_native *disp = &create_native_cbs[n];
+ const struct va_create_native *disp = create_native_cbs;
+ while (disp->name) {
mp_verbose(log, "Trying to open a %s VA display...\n", disp->name);
VADisplay *display = disp->create(ra);
if (display)
return display;
+ disp++;
}
return NULL;
}
diff --git a/video/out/opengl/context_x11egl.c b/video/out/opengl/context_x11egl.c
index e5885b6106..0803f48ad4 100644
--- a/video/out/opengl/context_x11egl.c
+++ b/video/out/opengl/context_x11egl.c
@@ -18,7 +18,6 @@
#include <assert.h>
#include <X11/Xlib.h>
-#include <X11/extensions/Xpresent.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
diff --git a/video/out/opengl/egl_helpers.c b/video/out/opengl/egl_helpers.c
index 18d9027762..91a6480eb2 100644
--- a/video/out/opengl/egl_helpers.c
+++ b/video/out/opengl/egl_helpers.c
@@ -16,6 +16,7 @@
*/
#include "config.h"
+#include "options/m_config.h"
#if HAVE_LIBDL
#include <dlfcn.h>
@@ -53,6 +54,12 @@ typedef intptr_t EGLAttrib;
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0
#endif
+#ifndef EGL_COLOR_COMPONENT_TYPE_EXT
+#define EGL_COLOR_COMPONENT_TYPE_EXT EGL_NONE
+#define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT EGL_NONE
+#define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT EGL_NONE
+#endif
+
struct mp_egl_config_attr {
int attrib;
const char *name;
@@ -100,8 +107,44 @@ static void *mpegl_get_proc_address(void *ctx, const char *name)
return p;
}
+struct egl_opts {
+ int config_id;
+ int output_format;
+};
+
+#define RGBA_FORMAT(r, g, b, a) ((r) << 18 | (g) << 12 | (b) << 6 | (a))
+#define FLOAT_FORMAT (1 << 24)
+static void unpack_format(int format, EGLint *r_size, EGLint *g_size, EGLint *b_size, EGLint *a_size, bool *is_float) {
+ *is_float = format & FLOAT_FORMAT;
+ *r_size = format >> 18 & 0x3f;
+ *g_size = (format >> 12) & 0x3f;
+ *b_size = (format >> 6) & 0x3f;
+ *a_size = format & 0x3f;
+}
+
+#define OPT_BASE_STRUCT struct egl_opts
+const struct m_sub_options egl_conf = {
+ .opts = (const struct m_option[]) {
+ {"config-id", OPT_INT(config_id)},
+ {"output-format", OPT_CHOICE(output_format,
+ {"auto", 0},
+ {"rgb8", RGBA_FORMAT(8, 8, 8, 0)},
+ {"rgba8", RGBA_FORMAT(8, 8, 8, 8)},
+ {"rgb10", RGBA_FORMAT(10, 10, 10, 0)},
+ {"rgb10_a2", RGBA_FORMAT(10, 10, 10, 2)},
+ {"rgb16", RGBA_FORMAT(16, 16, 16, 0)},
+ {"rgba16", RGBA_FORMAT(16, 16, 16, 16)},
+ {"rgb16f", RGBA_FORMAT(16, 16, 16, 0) | FLOAT_FORMAT},
+ {"rgba16f", RGBA_FORMAT(16, 16, 16, 16) | FLOAT_FORMAT},
+ {"rgb32f", RGBA_FORMAT(32, 32, 32, 0) | FLOAT_FORMAT},
+ {"rgba32f", RGBA_FORMAT(32, 32, 32, 32) | FLOAT_FORMAT})},
+ {0},
+ },
+ .size = sizeof(struct egl_opts),
+};
+
static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
- bool es, struct mpegl_cb cb,
+ bool es, struct mpegl_cb cb, struct egl_opts *opts,
EGLContext *out_context, EGLConfig *out_config)
{
int msgl = ctx->opts.probing ? MSGL_V : MSGL_FATAL;
@@ -120,6 +163,8 @@ static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
name = "GLES 2.x +";
}
+ const char *egl_exts = eglQueryString(display, EGL_EXTENSIONS);
+
MP_VERBOSE(ctx, "Trying to create %s context.\n", name);
if (!eglBindAPI(api)) {
@@ -127,15 +172,32 @@ static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
return false;
}
+ bool request_float_fmt;
+ EGLint r_size, g_size, b_size, a_size;
+ unpack_format(opts->output_format, &r_size, &g_size, &b_size, &a_size, &request_float_fmt);
+ bool has_float_format_ext = gl_check_extension(egl_exts, "EGL_EXT_pixel_format_float");
+ if (request_float_fmt && !has_float_format_ext) {
+ MP_MSG(ctx, msgl, "Could not request floating point pixel format for %s!\n", name);
+ return false;
+ }
+
EGLint attributes[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, ctx->opts.want_alpha ? 8 : 0,
EGL_RENDERABLE_TYPE, rend,
+ EGL_RED_SIZE, MPMAX(r_size, 8),
+ EGL_GREEN_SIZE, MPMAX(g_size, 8),
+ EGL_BLUE_SIZE, MPMAX(b_size, 8),
+ EGL_ALPHA_SIZE, opts->output_format ? a_size : (ctx->opts.want_alpha ? 8 : 0),
+ opts->output_format && has_float_format_ext ? EGL_COLOR_COMPONENT_TYPE_EXT : EGL_NONE,
+ request_float_fmt ? EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT : EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
EGL_NONE
};
+ if (opts->config_id) {
+ // Keep EGL_SURFACE_TYPE & EGL_RENDERABLE_TYPE
+ attributes[4] = EGL_CONFIG_ID;
+ attributes[5] = opts->config_id;
+ attributes[6] = EGL_NONE;
+ }
EGLint num_configs;
if (!eglChooseConfig(display, attributes, NULL, 0, &num_configs))
@@ -155,9 +217,20 @@ static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
dump_egl_config(ctx->log, MSGL_TRACE, display, configs[n]);
int chosen = 0;
- if (cb.refine_config)
+ if (opts->output_format) {
+ for (; chosen < num_configs; chosen++) {
+ EGLint real_r_size, real_g_size, real_b_size, real_a_size;
+ eglGetConfigAttrib(display, configs[chosen], EGL_RED_SIZE, &real_r_size);
+ eglGetConfigAttrib(display, configs[chosen], EGL_GREEN_SIZE, &real_g_size);
+ eglGetConfigAttrib(display, configs[chosen], EGL_BLUE_SIZE, &real_b_size);
+ eglGetConfigAttrib(display, configs[chosen], EGL_ALPHA_SIZE, &real_a_size);
+ if (r_size == real_r_size && g_size == real_g_size && b_size == real_b_size && a_size == real_a_size)
+ break;
+ }
+ } else if (cb.refine_config) {
chosen = cb.refine_config(cb.user_data, configs, num_configs);
- if (chosen < 0) {
+ }
+ if (chosen < 0 || chosen == num_configs) {
talloc_free(configs);
MP_MSG(ctx, msgl, "Could not refine EGLConfig for %s!\n", name);
return false;
@@ -243,17 +316,23 @@ bool mpegl_create_context_cb(struct ra_ctx *ctx, EGLDisplay display,
enum gles_mode mode = ra_gl_ctx_get_glesmode(ctx);
- if ((mode == GLES_NO || mode == GLES_AUTO) &&
- create_context(ctx, display, false, cb, out_context, out_config))
- return true;
+ void *tmp = talloc_new(NULL);
+ struct egl_opts *opts = mp_get_config_group(tmp, ctx->global, &egl_conf);
+
+ bool r = false;
+ if (!r && (mode == GLES_NO || mode == GLES_AUTO))
+ r = create_context(ctx, display, false, cb, opts, out_context, out_config);
+ if (!r && (mode == GLES_YES || mode == GLES_AUTO))
+ r = create_context(ctx, display, true, cb, opts, out_context, out_config);
- if ((mode == GLES_YES || mode == GLES_AUTO) &&
- create_context(ctx, display, true, cb, out_context, out_config))
- return true;
+ talloc_free(tmp);
+
+ if (!r) {
+ int msgl = ctx->opts.probing ? MSGL_V : MSGL_ERR;
+ MP_MSG(ctx, msgl, "Could not create a GL context.\n");
+ }
- int msgl = ctx->opts.probing ? MSGL_V : MSGL_ERR;
- MP_MSG(ctx, msgl, "Could not create a GL context.\n");
- return false;
+ return r;
}
static int GLAPIENTRY swap_interval(int interval)
diff --git a/video/out/vo.h b/video/out/vo.h
index 313c08aafc..3afbd6ea21 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -149,7 +149,7 @@ struct voctrl_playback_state {
bool taskbar_progress;
bool playing;
bool paused;
- int percent_pos;
+ uint8_t position;
};
// VOCTRL_PERFORMANCE_DATA
diff --git a/video/out/vo_vaapi.c b/video/out/vo_vaapi.c
index 2a241300f2..84ca4a7a42 100644
--- a/video/out/vo_vaapi.c
+++ b/video/out/vo_vaapi.c
@@ -406,18 +406,11 @@ static void va_pool_set_allocator(struct mp_image_pool *pool,
mp_image_pool_set_lru(pool);
}
-static void flush_output_surfaces(struct priv *p)
-{
- for (int n = 0; n < MAX_OUTPUT_SURFACES; n++)
- mp_image_unrefp(&p->output_surfaces[n]);
- p->output_surface = 0;
- p->visible_surface = 0;
-}
-
// See flush_surfaces() remarks - the same applies.
static void free_video_specific(struct priv *p)
{
- flush_output_surfaces(p);
+ p->output_surface = 0;
+ p->visible_surface = 0;
mp_image_unrefp(&p->black_surface);
@@ -430,7 +423,6 @@ static void free_video_specific(struct priv *p)
static bool alloc_swdec_surfaces(struct priv *p, int w, int h, int imgfmt)
{
- free_video_specific(p);
for (int i = 0; i < MAX_OUTPUT_SURFACES; i++) {
p->swdec_surfaces[i] = mp_image_pool_get(p->pool, IMGFMT_VAAPI, w, h);
if (va_surface_alloc_imgfmt(p, p->swdec_surfaces[i], imgfmt) < 0)
@@ -572,14 +564,12 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
struct mp_image *dst = p->swdec_surfaces[p->output_surface];
if (!dst || va_surface_upload(p, dst, mpi) < 0) {
MP_WARN(vo, "Could not upload surface.\n");
- talloc_free(mpi);
return;
}
mp_image_copy_attributes(dst, mpi);
- mpi = mp_image_new_ref(dst);
+ mpi = dst;
}
- talloc_free(p->output_surfaces[p->output_surface]);
p->output_surfaces[p->output_surface] = mpi;
draw_osd(vo);
diff --git a/video/out/w32_common.c b/video/out/w32_common.c
index a4eaadf170..dc796b0ccd 100644
--- a/video/out/w32_common.c
+++ b/video/out/w32_common.c
@@ -767,8 +767,15 @@ static void update_playback_state(struct vo_w32_state *w32)
return;
}
+ ULONGLONG completed = pstate->position;
+ ULONGLONG total = UINT8_MAX;
+ if (!pstate->position) {
+ completed = 1;
+ total = MAXULONGLONG;
+ }
+
ITaskbarList3_SetProgressValue(w32->taskbar_list3, w32->window,
- pstate->percent_pos, 100);
+ completed, total);
ITaskbarList3_SetProgressState(w32->taskbar_list3, w32->window,
pstate->paused ? TBPF_PAUSED :
TBPF_NORMAL);
@@ -1745,6 +1752,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
if (wParam == WM_CREATE) {
// Default to alphanumeric input when the IME is first initialized.
set_ime_conversion_mode(w32, IME_CMODE_ALPHANUMERIC);
+ KillTimer(w32->window, (UINT_PTR)WM_CREATE);
return 0;
}
break;
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index 4b1816db75..dea3d0300a 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -119,7 +119,7 @@ static const struct mp_keymap keymap[] = {
/* Numpad without numlock */
{XKB_KEY_KP_Insert, MP_KEY_KPINS}, {XKB_KEY_KP_End, MP_KEY_KPEND},
{XKB_KEY_KP_Down, MP_KEY_KPDOWN}, {XKB_KEY_KP_Page_Down, MP_KEY_KPPGDOWN},
- {XKB_KEY_KP_Left, MP_KEY_KPLEFT}, {XKB_KEY_KP_Begin, MP_KEY_KP5},
+ {XKB_KEY_KP_Left, MP_KEY_KPLEFT}, {XKB_KEY_KP_Begin, MP_KEY_KPBEGIN},
{XKB_KEY_KP_Right, MP_KEY_KPRIGHT}, {XKB_KEY_KP_Home, MP_KEY_KPHOME},
{XKB_KEY_KP_Up, MP_KEY_KPUP}, {XKB_KEY_KP_Page_Up, MP_KEY_KPPGUP},
{XKB_KEY_KP_Delete, MP_KEY_KPDEL},
@@ -211,6 +211,9 @@ struct vo_wayland_seat {
bool axis_value120_scroll;
bool has_keyboard_input;
struct wl_list link;
+ bool keyboard_entering;
+ uint32_t *keyboard_entering_keys;
+ int num_keyboard_entering_keys;
};
static bool single_output_spanned(struct vo_wayland_state *wl);
@@ -219,7 +222,7 @@ static int check_for_resize(struct vo_wayland_state *wl, int edge_pixels,
enum xdg_toplevel_resize_edge *edge);
static int get_mods(struct vo_wayland_seat *seat);
static int greatest_common_divisor(int a, int b);
-static int lookupkey(int key);
+static void handle_key_input(struct vo_wayland_seat *s, uint32_t key, uint32_t state);
static int set_cursor_visibility(struct vo_wayland_seat *s, bool on);
static int spawn_cursor(struct vo_wayland_state *wl);
@@ -558,7 +561,12 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
struct vo_wayland_seat *s = data;
struct vo_wayland_state *wl = s->wl;
s->has_keyboard_input = true;
+ s->keyboard_entering = true;
guess_focus(wl);
+
+ uint32_t *key;
+ wl_array_for_each(key, keys)
+ MP_TARRAY_APPEND(s, s->keyboard_entering_keys, s->num_keyboard_entering_keys, *key);
}
static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
@@ -579,36 +587,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
uint32_t state)
{
struct vo_wayland_seat *s = data;
- struct vo_wayland_state *wl = s->wl;
-
- s->keyboard_code = key + 8;
- xkb_keysym_t sym = xkb_state_key_get_one_sym(s->xkb_state, s->keyboard_code);
- int mpkey = lookupkey(sym);
-
- state = state == WL_KEYBOARD_KEY_STATE_PRESSED ? MP_KEY_STATE_DOWN
- : MP_KEY_STATE_UP;
-
- if (mpkey) {
- mp_input_put_key(wl->vo->input_ctx, mpkey | state | s->mpmod);
- } else {
- char str[128];
- if (xkb_keysym_to_utf8(sym, str, sizeof(str)) > 0) {
- mp_input_put_key_utf8(wl->vo->input_ctx, state | s->mpmod, bstr0(str));
- } else {
- // Assume a modifier was pressed and handle it in the mod event instead.
- // If a modifier is released before a regular key, also release that
- // key to not activate it again by accident.
- if (state == MP_KEY_STATE_UP) {
- s->mpkey = 0;
- mp_input_put_key(wl->vo->input_ctx, MP_INPUT_RELEASE_ALL);
- }
- return;
- }
- }
- if (state == MP_KEY_STATE_DOWN)
- s->mpkey = mpkey;
- if (mpkey && state == MP_KEY_STATE_UP)
- s->mpkey = 0;
+ handle_key_input(s, key, state);
}
static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
@@ -623,8 +602,15 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboar
xkb_state_update_mask(s->xkb_state, mods_depressed, mods_latched,
mods_locked, 0, 0, group);
s->mpmod = get_mods(s);
- if (s->mpkey)
- mp_input_put_key(wl->vo->input_ctx, s->mpkey | MP_KEY_STATE_DOWN | s->mpmod);
+ }
+ // Handle keys pressed during the enter event.
+ if (s->keyboard_entering) {
+ s->keyboard_entering = false;
+ for (int n = 0; n < s->num_keyboard_entering_keys; n++)
+ handle_key_input(s, s->keyboard_entering_keys[n], WL_KEYBOARD_KEY_STATE_PRESSED);
+ s->num_keyboard_entering_keys = 0;
+ } else if (s->xkb_state && s->mpkey) {
+ mp_input_put_key(wl->vo->input_ctx, s->mpkey | MP_KEY_STATE_DOWN | s->mpmod);
}
}
@@ -1464,20 +1450,27 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id
wl_surface_add_listener(wl->surface, &surface_listener, wl);
}
- if (!strcmp(interface, wl_subcompositor_interface.name) && (ver >= 1) && found++)
- wl->subcompositor = wl_registry_bind(reg, id, &wl_subcompositor_interface, 1);
+ if (!strcmp(interface, wl_subcompositor_interface.name) && found++) {
+ ver = 1;
+ wl->subcompositor = wl_registry_bind(reg, id, &wl_subcompositor_interface, ver);
+ }
if (!strcmp (interface, zwp_linux_dmabuf_v1_interface.name) && (ver >= 4) && found++) {
- wl->dmabuf = wl_registry_bind(reg, id, &zwp_linux_dmabuf_v1_interface, 4);
+ ver = 4;
+ wl->dmabuf = wl_registry_bind(reg, id, &zwp_linux_dmabuf_v1_interface, ver);
wl->dmabuf_feedback = zwp_linux_dmabuf_v1_get_default_feedback(wl->dmabuf);
zwp_linux_dmabuf_feedback_v1_add_listener(wl->dmabuf_feedback, &dmabuf_feedback_listener, wl);
}
- if (!strcmp (interface, wp_viewporter_interface.name) && (ver >= 1) && found++)
- wl->viewporter = wl_registry_bind (reg, id, &wp_viewporter_interface, 1);
+ if (!strcmp (interface, wp_viewporter_interface.name) && found++) {
+ ver = 1;
+ wl->viewporter = wl_registry_bind (reg, id, &wp_viewporter_interface, ver);
+ }
- if (!strcmp(interface, wl_data_device_manager_interface.name) && (ver >= 3) && found++)
- wl->dnd_devman = wl_registry_bind(reg, id, &wl_data_device_manager_interface, 3);
+ if (!strcmp(interface, wl_data_device_manager_interface.name) && (ver >= 3) && found++) {
+ ver = 3;
+ wl->dnd_devman = wl_registry_bind(reg, id, &wl_data_device_manager_interface, ver);
+ }
if (!strcmp(interface, wl_output_interface.name) && (ver >= 2) && found++) {
struct vo_wayland_output *output = talloc_zero(wl, struct vo_wayland_output);
@@ -1510,46 +1503,65 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id
wl_list_insert(&wl->seat_list, &seat->link);
}
- if (!strcmp(interface, wl_shm_interface.name) && found++)
- wl->shm = wl_registry_bind(reg, id, &wl_shm_interface, 1);
+ if (!strcmp(interface, wl_shm_interface.name) && found++) {
+ ver = 1;
+ wl->shm = wl_registry_bind(reg, id, &wl_shm_interface, ver);
+ }
#if HAVE_WAYLAND_PROTOCOLS_1_27
- if (!strcmp(interface, wp_content_type_manager_v1_interface.name) && found++)
- wl->content_type_manager = wl_registry_bind(reg, id, &wp_content_type_manager_v1_interface, 1);
+ if (!strcmp(interface, wp_content_type_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->content_type_manager = wl_registry_bind(reg, id, &wp_content_type_manager_v1_interface, ver);
+ }
- if (!strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) && found++)
- wl->single_pixel_manager = wl_registry_bind(reg, id, &wp_single_pixel_buffer_manager_v1_interface, 1);
+ if (!strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->single_pixel_manager = wl_registry_bind(reg, id, &wp_single_pixel_buffer_manager_v1_interface, ver);
+ }
#endif
#if HAVE_WAYLAND_PROTOCOLS_1_31
- if (!strcmp(interface, wp_fractional_scale_manager_v1_interface.name) && found++)
- wl->fractional_scale_manager = wl_registry_bind(reg, id, &wp_fractional_scale_manager_v1_interface, 1);
+ if (!strcmp(interface, wp_fractional_scale_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->fractional_scale_manager = wl_registry_bind(reg, id, &wp_fractional_scale_manager_v1_interface, ver);
+ }
#endif
#if HAVE_WAYLAND_PROTOCOLS_1_32
- if (!strcmp(interface, wp_cursor_shape_manager_v1_interface.name) && found++)
- wl->cursor_shape_manager = wl_registry_bind(reg, id, &wp_cursor_shape_manager_v1_interface, 1);
+ if (!strcmp(interface, wp_cursor_shape_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->cursor_shape_manager = wl_registry_bind(reg, id, &wp_cursor_shape_manager_v1_interface, ver);
+ }
#endif
if (!strcmp(interface, wp_presentation_interface.name) && found++) {
- wl->presentation = wl_registry_bind(reg, id, &wp_presentation_interface, 1);
+ ver = 1;
+ wl->presentation = wl_registry_bind(reg, id, &wp_presentation_interface, ver);
wp_presentation_add_listener(wl->presentation, &pres_listener, wl);
}
if (!strcmp(interface, xdg_wm_base_interface.name) && found++) {
+#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
ver = MPMIN(ver, 6); /* Cap at 6 in case new events are added later. */
+#else
+ ver = MPMIN(ver, 4);
+#endif
wl->wm_base = wl_registry_bind(reg, id, &xdg_wm_base_interface, ver);
xdg_wm_base_add_listener(wl->wm_base, &xdg_wm_base_listener, wl);
}
- if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name) && found++)
- wl->xdg_decoration_manager = wl_registry_bind(reg, id, &zxdg_decoration_manager_v1_interface, 1);
+ if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->xdg_decoration_manager = wl_registry_bind(reg, id, &zxdg_decoration_manager_v1_interface, ver);
+ }
- if (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) && found++)
- wl->idle_inhibit_manager = wl_registry_bind(reg, id, &zwp_idle_inhibit_manager_v1_interface, 1);
+ if (!strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) && found++) {
+ ver = 1;
+ wl->idle_inhibit_manager = wl_registry_bind(reg, id, &zwp_idle_inhibit_manager_v1_interface, ver);
+ }
if (found > 1)
- MP_VERBOSE(wl, "Registered for protocol %s\n", interface);
+ MP_VERBOSE(wl, "Registered interface %s at version %d\n", interface, ver);
}
static void registry_handle_remove(void *data, struct wl_registry *reg, uint32_t id)
@@ -1880,6 +1892,49 @@ static int lookupkey(int key)
return mpkey;
}
+static void handle_key_input(struct vo_wayland_seat *s, uint32_t key,
+ uint32_t state)
+{
+ struct vo_wayland_state *wl = s->wl;
+
+ switch (state) {
+ case WL_KEYBOARD_KEY_STATE_RELEASED:
+ state = MP_KEY_STATE_UP;
+ break;
+ case WL_KEYBOARD_KEY_STATE_PRESSED:
+ state = MP_KEY_STATE_DOWN;
+ break;
+ default:
+ return;
+ }
+
+ s->keyboard_code = key + 8;
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(s->xkb_state, s->keyboard_code);
+ int mpkey = lookupkey(sym);
+
+ if (mpkey) {
+ mp_input_put_key(wl->vo->input_ctx, mpkey | state | s->mpmod);
+ } else {
+ char str[128];
+ if (xkb_keysym_to_utf8(sym, str, sizeof(str)) > 0) {
+ mp_input_put_key_utf8(wl->vo->input_ctx, state | s->mpmod, bstr0(str));
+ } else {
+ // Assume a modifier was pressed and handle it in the mod event instead.
+ // If a modifier is released before a regular key, also release that
+ // key to not activate it again by accident.
+ if (state == MP_KEY_STATE_UP) {
+ s->mpkey = 0;
+ mp_input_put_key(wl->vo->input_ctx, MP_INPUT_RELEASE_ALL);
+ }
+ return;
+ }
+ }
+ if (state == MP_KEY_STATE_DOWN)
+ s->mpkey = mpkey;
+ if (mpkey && state == MP_KEY_STATE_UP)
+ s->mpkey = 0;
+}
+
static void prepare_resize(struct vo_wayland_state *wl)
{
int32_t width = mp_rect_w(wl->geometry) / wl->scaling;
@@ -2094,7 +2149,7 @@ static int set_screensaver_inhibitor(struct vo_wayland_state *wl, int state)
if (state) {
MP_VERBOSE(wl, "Enabling idle inhibitor\n");
struct zwp_idle_inhibit_manager_v1 *mgr = wl->idle_inhibit_manager;
- wl->idle_inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(mgr, wl->surface);
+ wl->idle_inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(mgr, wl->callback_surface);
} else {
MP_VERBOSE(wl, "Disabling the idle inhibitor\n");
zwp_idle_inhibitor_v1_destroy(wl->idle_inhibitor);
diff --git a/video/out/x11_common.c b/video/out/x11_common.c
index ec74a50f56..a9b9f97453 100644
--- a/video/out/x11_common.c
+++ b/video/out/x11_common.c
@@ -37,9 +37,13 @@
#include <X11/extensions/scrnsaver.h>
#include <X11/extensions/dpms.h>
#include <X11/extensions/shape.h>
-#include <X11/extensions/Xpresent.h>
#include <X11/extensions/Xrandr.h>
+#ifndef PRESENT_FUTURE_VERSION
+#define PRESENT_FUTURE_VERSION 0
+#endif
+#include <X11/extensions/Xpresent.h>
+
#include "misc/bstr.h"
#include "options/options.h"
#include "options/m_config.h"
@@ -578,13 +582,13 @@ static void vo_x11_update_screeninfo(struct vo *vo)
}
}
-static struct xrandr_display *get_current_display(struct vo *vo)
+static struct xrandr_display *get_xrandr_display(struct vo *vo, struct mp_rect rc)
{
struct vo_x11_state *x11 = vo->x11;
struct xrandr_display *selected_disp = NULL;
for (int n = 0; n < x11->num_displays; n++) {
struct xrandr_display *disp = &x11->displays[n];
- disp->overlaps = rc_overlaps(disp->rc, x11->winrc);
+ disp->overlaps = rc_overlaps(disp->rc, rc);
if (disp->overlaps && (!selected_disp || disp->fps < selected_disp->fps))
selected_disp = disp;
}
@@ -795,7 +799,7 @@ static const struct mp_keymap keymap[] = {
// numpad without numlock
{XK_KP_Insert, MP_KEY_KPINS}, {XK_KP_End, MP_KEY_KPEND},
{XK_KP_Down, MP_KEY_KPDOWN}, {XK_KP_Page_Down, MP_KEY_KPPGDOWN},
- {XK_KP_Left, MP_KEY_KPLEFT}, {XK_KP_Begin, MP_KEY_KP5},
+ {XK_KP_Left, MP_KEY_KPLEFT}, {XK_KP_Begin, MP_KEY_KPBEGIN},
{XK_KP_Right, MP_KEY_KPRIGHT}, {XK_KP_Home, MP_KEY_KPHOME}, {XK_KP_Up, MP_KEY_KPUP},
{XK_KP_Page_Up, MP_KEY_KPPGUP}, {XK_KP_Delete, MP_KEY_KPDEL},
@@ -1262,6 +1266,7 @@ void vo_x11_check_events(struct vo *vo)
if (x11->window == None)
break;
vo_x11_update_geometry(vo);
+ vo_x11_update_screeninfo(vo);
if (x11->parent && Event.xconfigure.window == x11->parent) {
MP_TRACE(x11, "adjusting embedded window position\n");
XMoveResizeWindow(x11->display, x11->window,
@@ -1665,6 +1670,7 @@ static void vo_x11_map_window(struct vo *vo, struct mp_rect rc)
XChangeProperty(x11->display, x11->window, XA(x11, _NET_WM_STATE), XA_ATOM,
32, PropModeAppend, (unsigned char *)&state, 1);
x11->fs = 1;
+ x11->init_fs = true;
// The "saved" positions are bogus, so reset them when leaving FS again.
x11->size_changed_during_fs = true;
x11->pos_changed_during_fs = true;
@@ -1932,7 +1938,7 @@ static void vo_x11_update_geometry(struct vo *vo)
&x, &y, &dummy_win);