From 416c86f3cb3535a5b252b8c08a7f4cb253fa495a Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 2 Nov 2014 20:48:45 +0100 Subject: command: add window-minimized property (X11 only) More or less requested by #1237. Should be simple to extend this to other backends. --- DOCS/man/input.rst | 3 +++ player/command.c | 18 ++++++++++++++++++ player/command.h | 1 + player/playloop.c | 2 ++ video/out/vo.h | 9 ++++++++- video/out/x11_common.c | 19 +++++++++++++++++++ video/out/x11_common.h | 1 + 7 files changed, 52 insertions(+), 1 deletion(-) diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index e62552cd35..94c54d1029 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -1115,6 +1115,9 @@ Property list (or to be exact, the size the video filters output). ``2`` will set the double size, ``0.5`` halves the size. +``window-minimized`` + Return whether the video window is minimized or not. + ``video-aspect`` (RW) Video aspect, see ``--video-aspect``. diff --git a/player/command.c b/player/command.c index 391cc5b30a..d97460ab91 100644 --- a/player/command.c +++ b/player/command.c @@ -2445,6 +2445,21 @@ static int mp_property_window_scale(void *ctx, struct m_property *prop, return M_PROPERTY_NOT_IMPLEMENTED; } +static int mp_property_win_minimized(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; + + int state = 0; + if (vo_control(vo, VOCTRL_GET_WIN_STATE, &state) < 1) + return M_PROPERTY_UNAVAILABLE; + + return m_property_flag_ro(action, arg, state & VO_WIN_STATE_MINIMIZED); +} + static int mp_property_vo_configured(void *ctx, struct m_property *prop, int action, void *arg) { @@ -3166,6 +3181,8 @@ static const struct m_property mp_properties[] = { M_PROPERTY_ALIAS("audio", "aid"), M_PROPERTY_ALIAS("sub", "sid"), + {"window-minimized", mp_property_win_minimized}, + {"mpv-version", mp_property_version}, {"options", mp_property_options}, @@ -3202,6 +3219,7 @@ static const char *const *const mp_event_property_change[] = { E(MP_EVENT_CACHE_UPDATE, "cache", "cache-free", "cache-used", "cache-idle", "demuxer-cache-duration", "demuxer-cache-idle"), E(MP_EVENT_WIN_RESIZE, "window-scale"), + E(MP_EVENT_WIN_STATE, "window-minimized"), }; #undef E diff --git a/player/command.h b/player/command.h index 3469e32948..d4097fee6f 100644 --- a/player/command.h +++ b/player/command.h @@ -45,6 +45,7 @@ enum { INTERNAL_EVENT_BASE = 24, MP_EVENT_CACHE_UPDATE, MP_EVENT_WIN_RESIZE, + MP_EVENT_WIN_STATE, }; bool mp_hook_test_completion(struct MPContext *mpctx, char *type); diff --git a/player/playloop.c b/player/playloop.c index 85d962fffe..9e1cef957d 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -676,6 +676,8 @@ static void handle_vo_events(struct MPContext *mpctx) int events = vo ? vo_query_events(vo, VO_EVENTS_USER, true) : 0; if (events & VO_EVENT_RESIZE) mp_notify(mpctx, MP_EVENT_WIN_RESIZE, NULL); + if (events & VO_EVENT_WIN_STATE) + mp_notify(mpctx, MP_EVENT_WIN_STATE, NULL); } void add_frame_pts(struct MPContext *mpctx, double pts) diff --git a/video/out/vo.h b/video/out/vo.h index 035b4dc1d6..6906cab222 100644 --- a/video/out/vo.h +++ b/video/out/vo.h @@ -36,9 +36,11 @@ #define VO_EVENT_RESIZE 2 // The ICC profile needs to be reloaded #define VO_EVENT_ICC_PROFILE_PATH_CHANGED 4 +// Some other window state changed +#define VO_EVENT_WIN_STATE 8 // Set of events the player core may be interested in. -#define VO_EVENTS_USER (VO_EVENT_RESIZE) +#define VO_EVENTS_USER (VO_EVENT_RESIZE | VO_EVENT_WIN_STATE) enum mp_voctrl { /* signal a device reset seek */ @@ -83,6 +85,8 @@ enum mp_voctrl { VOCTRL_GET_UNFS_WINDOW_SIZE, // int[2] (w/h) VOCTRL_SET_UNFS_WINDOW_SIZE, // int[2] (w/h) + VOCTRL_GET_WIN_STATE, // int* (VO_WIN_STATE_* flags) + // The VO is supposed to set "known" fields, and leave the others // untouched or set to 0. // imgfmt/w/h/d_w/d_h can be omitted for convenience. @@ -130,6 +134,9 @@ struct voctrl_screenshot_args { bool has_osd; }; +// VOCTRL_GET_WIN_STATE +#define VO_WIN_STATE_MINIMIZED 1 + #define VO_TRUE true #define VO_FALSE false #define VO_ERROR -1 diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 04f475ec5f..1779c5c29e 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -952,6 +952,8 @@ int vo_x11_check_events(struct vo *vo) MP_VERBOSE(x11, "not waiting for MapNotify\n"); x11->pseudo_mapped = true; } + } else if (Event.xproperty.atom == x11->atom_wm_state) { + x11->pending_vo_events |= VO_EVENT_WIN_STATE; } break; default: @@ -1229,6 +1231,7 @@ static void vo_x11_create_window(struct vo *vo, XVisualInfo *vis, } x11->atom_frame_exts = XA(x11, _NET_FRAME_EXTENTS); + x11->atom_wm_state = XA(x11, _NET_WM_STATE); } static void vo_x11_map_window(struct vo *vo, struct mp_rect rc) @@ -1584,6 +1587,22 @@ int vo_x11_control(struct vo *vo, int *events, int request, void *arg) } return VO_TRUE; } + case VOCTRL_GET_WIN_STATE: { + if (!x11->window) + return VO_FALSE; + int num_elems; + long *elems = x11_get_property(x11, x11->window, x11->atom_wm_state, + XA_ATOM, 32, &num_elems); + if (elems) { + Atom hidden = XA(x11, _NET_WM_STATE_HIDDEN); + for (int n = 0; n < num_elems; n++) { + if (elems[n] == hidden) + *(int *)arg |= VO_WIN_STATE_MINIMIZED; + } + XFree(elems); + } + return VO_TRUE; + } case VOCTRL_SET_CURSOR_VISIBILITY: vo_set_cursor_hidden(vo, !(*(bool *)arg)); return VO_TRUE; diff --git a/video/out/x11_common.h b/video/out/x11_common.h index 696e73aff3..d5927933c3 100644 --- a/video/out/x11_common.h +++ b/video/out/x11_common.h @@ -108,6 +108,7 @@ struct vo_x11_state { Window dnd_src_window; Atom atom_frame_exts; + Atom atom_wm_state; /* dragging the window */ bool win_drag_button1_down; -- cgit v1.2.3