mirror of https://github.com/mpv-player/mpv
x11: if the WM supports _NET_FRAME_EXTENTS, don't wait for map
Some window managers can prevent mapping of a window as a feature. i3 can put new windows on a certain workspace (with "assign"), so if mpv is started on a different workspace, the window will never be mapped. mpv currently waits until the window is mapped (blocking almost all of the player), in order to avoid race conditions regarding the window size. We don't want to remove this, but on the other hand we also don't want to block the player forever in these situations. So what we need is a way to know when the window manager is "done" with processing the map request. Unfortunately, there doesn't seem to be a standard way for this. So, instead we could do some arbitrary communication with the WM, that may act as "barrier" after map request and the "immediate" mapping of the window. If the window is not mapped after this barrier, it means the window manager decided to delay the mapping indefinitely. Use the _NET_REQUEST_FRAME_EXTENTS message as such a barrier. WMs supporting this message must set the _NET_FRAME_EXTENTS property on the mpv window, and we receive a PropertyNotify event. If that happens, we always continue and cancel waiting for the MapNotify event. I don't know if this is sane or if there's a better mechanism. Also, this works only for WMs which support this message, which are not many. But at least it appears to work on i3. It may reintroduce flickering on fullscreen with other WMs, though.
This commit is contained in:
parent
930c61b64c
commit
8c002b79d3
|
@ -925,6 +925,7 @@ int vo_x11_check_events(struct vo *vo)
|
||||||
if (x11->window_hidden)
|
if (x11->window_hidden)
|
||||||
vo_x11_clearwindow(vo, x11->window);
|
vo_x11_clearwindow(vo, x11->window);
|
||||||
x11->window_hidden = false;
|
x11->window_hidden = false;
|
||||||
|
x11->pseudo_mapped = true;
|
||||||
vo_x11_update_geometry(vo);
|
vo_x11_update_geometry(vo);
|
||||||
break;
|
break;
|
||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
|
@ -941,6 +942,13 @@ int vo_x11_check_events(struct vo *vo)
|
||||||
case SelectionNotify:
|
case SelectionNotify:
|
||||||
vo_x11_dnd_handle_selection(vo, &Event.xselection);
|
vo_x11_dnd_handle_selection(vo, &Event.xselection);
|
||||||
break;
|
break;
|
||||||
|
case PropertyNotify:
|
||||||
|
if (Event.xproperty.atom == x11->atom_frame_exts) {
|
||||||
|
if (!x11->pseudo_mapped)
|
||||||
|
MP_VERBOSE(x11, "not waiting for MapNotify\n");
|
||||||
|
x11->pseudo_mapped = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (Event.type == x11->ShmCompletionEvent) {
|
if (Event.type == x11->ShmCompletionEvent) {
|
||||||
if (x11->ShmCompletionWaitCount > 0)
|
if (x11->ShmCompletionWaitCount > 0)
|
||||||
|
@ -1212,6 +1220,8 @@ static void vo_x11_create_window(struct vo *vo, XVisualInfo *vis,
|
||||||
vo_x11_set_wm_icon(x11);
|
vo_x11_set_wm_icon(x11);
|
||||||
vo_x11_update_window_title(vo);
|
vo_x11_update_window_title(vo);
|
||||||
vo_x11_dnd_init_window(vo);
|
vo_x11_dnd_init_window(vo);
|
||||||
|
|
||||||
|
x11->atom_frame_exts = XA(x11, _NET_FRAME_EXTENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vo_x11_map_window(struct vo *vo, struct mp_rect rc)
|
static void vo_x11_map_window(struct vo *vo, struct mp_rect rc)
|
||||||
|
@ -1244,7 +1254,7 @@ static void vo_x11_map_window(struct vo *vo, struct mp_rect rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// map window
|
// map window
|
||||||
int events = StructureNotifyMask | ExposureMask;
|
int events = StructureNotifyMask | ExposureMask | PropertyChangeMask;
|
||||||
if (vo->opts->WinID > 0) {
|
if (vo->opts->WinID > 0) {
|
||||||
XWindowAttributes attribs;
|
XWindowAttributes attribs;
|
||||||
if (XGetWindowAttributes(x11->display, vo->opts->WinID, &attribs))
|
if (XGetWindowAttributes(x11->display, vo->opts->WinID, &attribs))
|
||||||
|
@ -1285,7 +1295,9 @@ static void vo_x11_highlevel_resize(struct vo *vo, struct mp_rect rc)
|
||||||
static void wait_until_mapped(struct vo *vo)
|
static void wait_until_mapped(struct vo *vo)
|
||||||
{
|
{
|
||||||
struct vo_x11_state *x11 = vo->x11;
|
struct vo_x11_state *x11 = vo->x11;
|
||||||
while (x11->window_hidden && x11->window) {
|
if (!x11->pseudo_mapped)
|
||||||
|
x11_send_ewmh_msg(x11, "_NET_REQUEST_FRAME_EXTENTS", (long[5]){0});
|
||||||
|
while (!x11->pseudo_mapped && x11->window) {
|
||||||
XEvent unused;
|
XEvent unused;
|
||||||
XPeekEvent(x11->display, &unused);
|
XPeekEvent(x11->display, &unused);
|
||||||
vo_x11_check_events(vo);
|
vo_x11_check_events(vo);
|
||||||
|
|
|
@ -65,7 +65,8 @@ struct vo_x11_state {
|
||||||
Colormap colormap;
|
Colormap colormap;
|
||||||
|
|
||||||
int wm_type;
|
int wm_type;
|
||||||
bool window_hidden;
|
bool window_hidden; // the window was mapped at least once
|
||||||
|
bool pseudo_mapped; // not necessarily mapped, but known window size
|
||||||
int fs; // whether we assume the window is in fullscreen mode
|
int fs; // whether we assume the window is in fullscreen mode
|
||||||
|
|
||||||
bool mouse_cursor_hidden;
|
bool mouse_cursor_hidden;
|
||||||
|
@ -106,6 +107,8 @@ struct vo_x11_state {
|
||||||
Atom dnd_requested_format;
|
Atom dnd_requested_format;
|
||||||
Window dnd_src_window;
|
Window dnd_src_window;
|
||||||
|
|
||||||
|
Atom atom_frame_exts;
|
||||||
|
|
||||||
/* dragging the window */
|
/* dragging the window */
|
||||||
bool win_drag_button1_down;
|
bool win_drag_button1_down;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue