summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/input.rst3
-rw-r--r--player/command.c17
-rw-r--r--player/command.h1
-rw-r--r--player/playloop.c2
-rw-r--r--video/out/vo.h5
-rw-r--r--video/out/wayland_common.c20
-rw-r--r--video/out/wayland_common.h3
-rw-r--r--video/out/x11_common.c6
8 files changed, 56 insertions, 1 deletions
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index 739f5f1022..18027ce17a 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -2439,6 +2439,9 @@ Property list
since setting the option, and the window size was not restricted in other
ways. The property is unavailable if no video is active.
+``focused``
+ Whether the window has focus. Currently works only on X11 and Wayland.
+
``display-names``
Names of the displays that the mpv window covers. On X11, these
are the xrandr names (LVDS1, HDMI1, DP1, VGA1, etc.). On Windows, these
diff --git a/player/command.c b/player/command.c
index 5b9e8bcbb4..723996d9be 100644
--- a/player/command.c
+++ b/player/command.c
@@ -2410,6 +2410,21 @@ static int mp_property_hidpi_scale(void *ctx, struct m_property *prop,
return m_property_double_ro(action, arg, cmd->cached_window_scale);
}
+static int mp_property_focused(void *ctx, struct m_property *prop,
+ int action, void *arg)
+{
+ MPContext *mpctx = ctx;
+ struct vo *vo = mpctx->video_out;
+ if (!vo)
+ return M_PROPERTY_UNAVAILABLE;
+
+ bool focused;
+ if (vo_control(vo, VOCTRL_GET_FOCUSED, &focused) < 1)
+ return M_PROPERTY_UNAVAILABLE;
+
+ return m_property_flag_ro(action, arg, focused);
+}
+
static int mp_property_display_names(void *ctx, struct m_property *prop,
int action, void *arg)
{
@@ -3593,6 +3608,7 @@ static const struct m_property mp_properties_base[] = {
PROPERTY_BITRATE("audio-bitrate", false, STREAM_AUDIO),
PROPERTY_BITRATE("sub-bitrate", false, STREAM_SUB),
+ {"focused", mp_property_focused},
{"display-names", mp_property_display_names},
{"display-fps", mp_property_display_fps},
{"estimated-display-fps", mp_property_estimated_display_fps},
@@ -3676,6 +3692,7 @@ static const char *const *const mp_event_property_change[] = {
"osd-par", "osd-dimensions"),
E(MP_EVENT_WIN_STATE, "display-names", "display-fps"),
E(MP_EVENT_WIN_STATE2, "display-hidpi-scale"),
+ E(MP_EVENT_FOCUS, "focused"),
E(MP_EVENT_CHANGE_PLAYLIST, "playlist", "playlist-pos", "playlist-pos-1",
"playlist-count", "playlist/count", "playlist-current-pos",
"playlist-playing-pos"),
diff --git a/player/command.h b/player/command.h
index 17e0726b0b..c47ed40f1d 100644
--- a/player/command.h
+++ b/player/command.h
@@ -98,6 +98,7 @@ enum {
MP_EVENT_WIN_RESIZE,
MP_EVENT_WIN_STATE,
MP_EVENT_WIN_STATE2,
+ MP_EVENT_FOCUS,
MP_EVENT_CHANGE_PLAYLIST,
MP_EVENT_CORE_IDLE,
MP_EVENT_DURATION_UPDATE,
diff --git a/player/playloop.c b/player/playloop.c
index ddd3f6dbdb..44ccb4819b 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -844,6 +844,8 @@ static void handle_vo_events(struct MPContext *mpctx)
mp_notify(mpctx, MP_EVENT_WIN_STATE, NULL);
if (events & VO_EVENT_DPI)
mp_notify(mpctx, MP_EVENT_WIN_STATE2, NULL);
+ if (events & VO_EVENT_FOCUS)
+ mp_notify(mpctx, MP_EVENT_FOCUS, NULL);
}
static void handle_sstep(struct MPContext *mpctx)
diff --git a/video/out/vo.h b/video/out/vo.h
index 1b7a239798..5deb99a6f1 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -48,10 +48,11 @@ enum {
// Special thing for encode mode (vo_driver.initially_blocked).
// Part of VO_EVENTS_USER to make vo_is_ready_for_frame() work properly.
VO_EVENT_INITIAL_UNBLOCK = 1 << 7,
+ VO_EVENT_FOCUS = 1 << 8,
// Set of events the player core may be interested in.
VO_EVENTS_USER = VO_EVENT_RESIZE | VO_EVENT_WIN_STATE | VO_EVENT_DPI |
- VO_EVENT_INITIAL_UNBLOCK,
+ VO_EVENT_INITIAL_UNBLOCK | VO_EVENT_FOCUS,
};
enum mp_voctrl {
@@ -99,6 +100,8 @@ enum mp_voctrl {
VOCTRL_GET_UNFS_WINDOW_SIZE, // int[2] (w/h)
VOCTRL_SET_UNFS_WINDOW_SIZE, // int[2] (w/h)
+ VOCTRL_GET_FOCUSED, // bool*
+
// char *** (NULL terminated array compatible with CONF_TYPE_STRING_LIST)
// names for displays the window is on
VOCTRL_GET_DISPLAY_NAMES,
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index a79c8aa8ca..c6c0e342c9 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -447,11 +447,15 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, struct wl_surface *surface,
struct wl_array *keys)
{
+ struct vo_wayland_state *wl = data;
+ wl->has_keyboard_input = true;
}
static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, struct wl_surface *surface)
{
+ struct vo_wayland_state *wl = data;
+ wl->has_keyboard_input = false;
}
static bool create_input(struct vo_wayland_state *wl)
@@ -951,6 +955,7 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel,
bool is_maximized = false;
bool is_fullscreen = false;
+ bool is_activated = false;
enum xdg_toplevel_state *state;
wl_array_for_each(state, states) {
switch (*state) {
@@ -961,6 +966,7 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel,
wl->pending_vo_events |= VO_EVENT_LIVE_RESIZING;
break;
case XDG_TOPLEVEL_STATE_ACTIVATED:
+ is_activated = true;
/*
* If we get an ACTIVATED state, we know it cannot be
* minimized, but it may not have been minimized
@@ -992,6 +998,16 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel,
m_config_cache_write_opt(wl->vo_opts_cache, &vo_opts->window_maximized);
}
+ if (wl->activated != is_activated) {
+ wl->activated = is_activated;
+ if ((!wl->focused && wl->activated && wl->has_keyboard_input) ||
+ (wl->focused && !wl->activated))
+ {
+ wl->focused = !wl->focused;
+ wl->pending_vo_events |= VO_EVENT_FOCUS;
+ }
+ }
+
if (!(wl->pending_vo_events & VO_EVENT_LIVE_RESIZING))
vo_query_and_reset_events(wl->vo, VO_EVENT_LIVE_RESIZING);
@@ -1544,6 +1560,10 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg)
}
return VO_TRUE;
}
+ case VOCTRL_GET_FOCUSED: {
+ *(bool *)arg = wl->focused;
+ return VO_TRUE;
+ }
case VOCTRL_GET_DISPLAY_NAMES: {
*(char ***)arg = get_displays_spanned(wl);
return VO_TRUE;
diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h
index 65f7cbf3e5..7eec7be2d5 100644
--- a/video/out/wayland_common.h
+++ b/video/out/wayland_common.h
@@ -76,6 +76,9 @@ struct vo_wayland_state {
bool frame_wait;
bool state_change;
bool toplevel_configured;
+ bool activated;
+ bool has_keyboard_input;
+ bool focused;
int wakeup_pipe[2];
int pending_vo_events;
int mouse_x;
diff --git a/video/out/x11_common.c b/video/out/x11_common.c
index 461ff378d0..92b3539aca 100644
--- a/video/out/x11_common.c
+++ b/video/out/x11_common.c
@@ -1128,11 +1128,13 @@ void vo_x11_check_events(struct vo *vo)
case FocusIn:
x11->has_focus = true;
vo_update_cursor(vo);
+ x11->pending_vo_events |= VO_EVENT_FOCUS;
break;
case FocusOut:
release_all_keys(vo);
x11->has_focus = false;
vo_update_cursor(vo);
+ x11->pending_vo_events |= VO_EVENT_FOCUS;
break;
case KeyRelease:
release_all_keys(vo);
@@ -1878,6 +1880,10 @@ int vo_x11_control(struct vo *vo, int *events, int request, void *arg)
}
return VO_TRUE;
}
+ case VOCTRL_GET_FOCUSED: {
+ *(bool *)arg = x11->has_focus;
+ return VO_TRUE;
+ }
case VOCTRL_GET_DISPLAY_NAMES: {
if (!x11->pseudo_mapped)
return VO_FALSE;