diff options
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/cocoa_cb_common.swift | 10 | ||||
-rw-r--r-- | video/out/d3d11/context.c | 42 | ||||
-rw-r--r-- | video/out/d3d11/ra_d3d11.c | 20 | ||||
-rw-r--r-- | video/out/hwdec/hwdec_cuda_vk.c | 2 | ||||
-rw-r--r-- | video/out/hwdec/hwdec_vaapi.c | 6 | ||||
-rw-r--r-- | video/out/opengl/context_x11egl.c | 1 | ||||
-rw-r--r-- | video/out/opengl/egl_helpers.c | 111 | ||||
-rw-r--r-- | video/out/vo.h | 2 | ||||
-rw-r--r-- | video/out/vo_vaapi.c | 16 | ||||
-rw-r--r-- | video/out/w32_common.c | 10 | ||||
-rw-r--r-- | video/out/wayland_common.c | 171 | ||||
-rw-r--r-- | video/out/x11_common.c | 36 | ||||
-rw-r--r-- | video/out/x11_common.h | 2 |
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); |