summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRostislav Pehlivanov <atomnuker@gmail.com>2016-10-16 20:08:01 +0100
committerRostislav Pehlivanov <atomnuker@gmail.com>2016-12-23 05:08:19 +0000
commite8872178202d0db78980bdadfc594a417ec9fc63 (patch)
treeae6ff2914e254e411a3b5a3f699e9065a7ac331d
parent0a81fe1cf9e62c26ebda1c209b3b69467991b252 (diff)
downloadmpv-wayland-zxdg6.tar.bz2
mpv-wayland-zxdg6.tar.xz
wayland: convert to the zxdg_v6 apiwayland-zxdg6
Work in progress, fixes some bugs but breaks other things
-rw-r--r--video/out/opengl/context_wayland.c25
-rw-r--r--video/out/vo_wayland.c17
-rw-r--r--video/out/wayland/protocol/xdg-shell.xml1045
-rw-r--r--video/out/wayland_common.c231
-rw-r--r--video/out/wayland_common.h14
-rw-r--r--waftools/generators/sources.py28
-rw-r--r--wscript5
-rw-r--r--wscript_build.py9
8 files changed, 1203 insertions, 171 deletions
diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c
index 3864e2887f..7975d96a2a 100644
--- a/video/out/opengl/context_wayland.c
+++ b/video/out/opengl/context_wayland.c
@@ -22,10 +22,6 @@
static void egl_resize(struct vo_wayland_state *wl)
{
- int32_t x = wl->window.sh_x;
- int32_t y = wl->window.sh_y;
- int32_t width = wl->window.sh_width;
- int32_t height = wl->window.sh_height;
int32_t scale = 1;
if (!wl->egl_context.egl_window)
@@ -34,32 +30,23 @@ static void egl_resize(struct vo_wayland_state *wl)
if (wl->display.current_output)
scale = wl->display.current_output->scale;
- // get the real size of the window
- // this improves moving the window while resizing it
- wl_egl_window_get_attached_size(wl->egl_context.egl_window,
- &wl->window.width,
- &wl->window.height);
+ const int32_t width = wl->window.sh_width;
+ const int32_t height = wl->window.sh_height;
+
+ wl->vo->dwidth = scale*width;
+ wl->vo->dheight = scale*height;
MP_VERBOSE(wl, "resizing %dx%d -> %dx%d\n", wl->window.width,
wl->window.height,
width,
height);
- if (x != 0)
- x = wl->window.width - width;
-
- if (y != 0)
- y = wl->window.height - height;
-
wl_surface_set_buffer_scale(wl->window.video_surface, scale);
- wl_egl_window_resize(wl->egl_context.egl_window, scale*width, scale*height, x, y);
+ wl_egl_window_resize(wl->egl_context.egl_window, scale*width, scale*height, 0, 0);
wl->window.width = width;
wl->window.height = height;
- /* set size for mplayer */
- wl->vo->dwidth = scale*wl->window.width;
- wl->vo->dheight = scale*wl->window.height;
wl->vo->want_redraw = true;
}
diff --git a/video/out/vo_wayland.c b/video/out/vo_wayland.c
index 6a7b18a6c5..fb4878ee77 100644
--- a/video/out/vo_wayland.c
+++ b/video/out/vo_wayland.c
@@ -104,8 +104,6 @@ struct priv {
int width; // width of the original image
int height;
- int x, y; // coords for resizing
-
struct wl_surface *osd_surfaces[MAX_OSD_PARTS];
struct wl_subsurface *osd_subsurfaces[MAX_OSD_PARTS];
shm_buffer_t *osd_buffers[MAX_OSD_PARTS];
@@ -250,8 +248,6 @@ static bool resize(struct priv *p)
return false; // skip resizing if we can't guarantee pixel perfectness!
int32_t scale = 1;
- int32_t x = wl->window.sh_x;
- int32_t y = wl->window.sh_y;
if (wl->display.current_output)
scale = wl->display.current_output->scale;
@@ -272,12 +268,6 @@ static bool resize(struct priv *p)
p->dst_w,
p->dst_h);
- if (x != 0)
- x = wl->window.width - p->dst_w;
-
- if (y != 0)
- y = wl->window.height - p->dst_h;
-
wl_surface_set_buffer_scale(wl->window.video_surface, scale);
mp_sws_set_from_cmdline(p->sws, p->vo->opts->sws_opts);
p->sws->src = p->in_format;
@@ -312,8 +302,6 @@ static bool resize(struct priv *p)
wl_region_destroy(opaque);
}
- p->x = x;
- p->y = y;
p->vo->want_redraw = true;
return true;
}
@@ -494,12 +482,9 @@ static void redraw(void *data, uint32_t time)
struct priv *p = data;
shm_buffer_t *buf = buffer_pool_get_front(&p->video_bufpool);
- wl_surface_attach(p->wl->window.video_surface, buf->buffer, p->x, p->y);
+ wl_surface_attach(p->wl->window.video_surface, buf->buffer, 0, 0);
wl_surface_damage(p->wl->window.video_surface, 0, 0, p->dst_w, p->dst_h);
buffer_finalise_front(buf);
-
- p->x = 0;
- p->y = 0;
}
static void flip_page(struct vo *vo)
diff --git a/video/out/wayland/protocol/xdg-shell.xml b/video/out/wayland/protocol/xdg-shell.xml
new file mode 100644
index 0000000000..565df8ce35
--- /dev/null
+++ b/video/out/wayland/protocol/xdg-shell.xml
@@ -0,0 +1,1045 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="xdg_shell_unstable_v6">
+
+ <copyright>
+ Copyright © 2008-2013 Kristian Høgsberg
+ Copyright © 2013 Rafael Antognolli
+ Copyright © 2013 Jasper St. Pierre
+ Copyright © 2010-2013 Intel Corporation
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="zxdg_shell_v6" version="1">
+ <description summary="create desktop-style surfaces">
+ xdg_shell allows clients to turn a wl_surface into a "real window"
+ which can be dragged, resized, stacked, and moved around by the
+ user. Everything about this interface is suited towards traditional
+ desktop environments.
+ </description>
+
+ <enum name="error">
+ <entry name="role" value="0" summary="given wl_surface has another role"/>
+ <entry name="defunct_surfaces" value="1"
+ summary="xdg_shell was destroyed before children"/>
+ <entry name="not_the_topmost_popup" value="2"
+ summary="the client tried to map or destroy a non-topmost popup"/>
+ <entry name="invalid_popup_parent" value="3"
+ summary="the client specified an invalid popup parent surface"/>
+ <entry name="invalid_surface_state" value="4"
+ summary="the client provided an invalid surface state"/>
+ <entry name="invalid_positioner" value="5"
+ summary="the client provided an invalid positioner"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy xdg_shell">
+ Destroy this xdg_shell object.
+
+ Destroying a bound xdg_shell object while there are surfaces
+ still alive created by this xdg_shell object instance is illegal
+ and will result in a protocol error.
+ </description>
+ </request>
+
+ <request name="create_positioner">
+ <description summary="create a positioner object">
+ Create a positioner object. A positioner object is used to position
+ surfaces relative to some parent surface. See the interface description
+ and xdg_surface.get_popup for details.
+ </description>
+ <arg name="id" type="new_id" interface="zxdg_positioner_v6"/>
+ </request>
+
+ <request name="get_xdg_surface">
+ <description summary="create a shell surface from a surface">
+ This creates an xdg_surface for the given surface. While xdg_surface
+ itself is not a role, the corresponding surface may only be assigned
+ a role extending xdg_surface, such as xdg_toplevel or xdg_popup.
+
+ This creates an xdg_surface for the given surface. An xdg_surface is
+ used as basis to define a role to a given surface, such as xdg_toplevel
+ or xdg_popup. It also manages functionality shared between xdg_surface
+ based surface roles.
+
+ See the documentation of xdg_surface for more details about what an
+ xdg_surface is and how it is used.
+ </description>
+ <arg name="id" type="new_id" interface="zxdg_surface_v6"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </request>
+
+ <request name="pong">
+ <description summary="respond to a ping event">
+ A client must respond to a ping event with a pong request or
+ the client may be deemed unresponsive. See xdg_shell.ping.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the ping event"/>
+ </request>
+
+ <event name="ping">
+ <description summary="check if the client is alive">
+ The ping event asks the client if it's still alive. Pass the
+ serial specified in the event back to the compositor by sending
+ a "pong" request back with the specified serial. See xdg_shell.ping.
+
+ Compositors can use this to determine if the client is still
+ alive. It's unspecified what will happen if the client doesn't
+ respond to the ping request, or in what timeframe. Clients should
+ try to respond in a reasonable amount of time.
+
+ A compositor is free to ping in any way it wants, but a client must
+ always respond to any xdg_shell object it created.
+ </description>
+ <arg name="serial" type="uint" summary="pass this to the pong request"/>
+ </event>
+ </interface>
+
+ <interface name="zxdg_positioner_v6" version="1">
+ <description summary="child surface positioner">
+ The xdg_positioner provides a collection of rules for the placement of a
+ child surface relative to a parent surface. Rules can be defined to ensure
+ the child surface remains within the visible area's borders, and to
+ specify how the child surface changes its position, such as sliding along
+ an axis, or flipping around a rectangle.
+
+ See the various requests for details about possible rules.
+
+ At the time of the request, the compositor makes a copy of the rules
+ specified by the xdg_positioner. Thus, after the request is complete the
+ xdg_positioner object can be destroyed or reused; further changes to the
+ object will have no effect on previous usages.
+
+ For an xdg_positioner object to be considered complete, it must have a
+ non-zero size set by set_size, and a non-zero anchor rectangle set by
+ set_anchor_rect. Passing an incomplete xdg_positioner object when
+ positioning a surface raises an error.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_input" value="0" summary="invalid input provided"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the xdg_positioner object">
+ Notify the compositor that the xdg_positioner will no longer be used.
+ </description>
+ </request>
+
+ <request name="set_size">
+ <description summary="set the size of the to-be positioned rectangle">
+ Set the size of the surface that is to be positioned with the positioner
+ object. The size is in surface-local coordinates and corresponds to the
+ window geometry. See xdg_surface.set_window_geometry.
+
+ If a zero or negative size is set the invalid_input error is raised.
+ </description>
+ <arg name="width" type="int" summary="width of positioned rectangle"/>
+ <arg name="height" type="int" summary="height of positioned rectangle"/>
+ </request>
+
+ <request name="set_anchor_rect">
+ <description summary="set the anchor rectangle within the parent surface">
+ Specify the anchor rectangle within the parent surface that the child
+ surface will be placed relative to. The rectangle is relative to the
+ window geometry as defined by xdg_surface.set_window_geometry of the
+ parent surface. The rectangle must be at least 1x1 large.
+
+ When the xdg_positioner object is used to position a child surface, the
+ anchor rectangle may not extend outside the window geometry of the
+ positioned child's parent surface.
+
+ If a zero or negative size is set the invalid_input error is raised.
+ </description>
+ <arg name="x" type="int" summary="x position of anchor rectangle"/>
+ <arg name="y" type="int" summary="y position of anchor rectangle"/>
+ <arg name="width" type="int" summary="width of anchor rectangle"/>
+ <arg name="height" type="int" summary="height of anchor rectangle"/>
+ </request>
+
+ <enum name="anchor" bitfield="true">
+ <entry name="none" value="0"
+ summary="the center of the anchor rectangle"/>
+ <entry name="top" value="1"
+ summary="the top edge of the anchor rectangle"/>
+ <entry name="bottom" value="2"
+ summary="the bottom edge of the anchor rectangle"/>
+ <entry name="left" value="4"
+ summary="the left edge of the anchor rectangle"/>
+ <entry name="right" value="8"
+ summary="the right edge of the anchor rectangle"/>
+ </enum>
+
+ <request name="set_anchor">
+ <description summary="set anchor rectangle anchor edges">
+ Defines a set of edges for the anchor rectangle. These are used to
+ derive an anchor point that the child surface will be positioned
+ relative to. If two orthogonal edges are specified (e.g. 'top' and
+ 'left'), then the anchor point will be the intersection of the edges
+ (e.g. the top left position of the rectangle); otherwise, the derived
+ anchor point will be centered on the specified edge, or in the center of
+ the anchor rectangle if no edge is specified.
+
+ If two parallel anchor edges are specified (e.g. 'left' and 'right'),
+ the invalid_input error is raised.
+ </description>
+ <arg name="anchor" type="uint" enum="anchor"
+ summary="bit mask of anchor edges"/>
+ </request>
+
+ <enum name="gravity" bitfield="true">
+ <entry name="none" value="0"
+ summary="center over the anchor edge"/>
+ <entry name="top" value="1"
+ summary="position above the anchor edge"/>
+ <entry name="bottom" value="2"
+ summary="position below the anchor edge"/>
+ <entry name="left" value="4"
+ summary="position to the left of the anchor edge"/>
+ <entry name="right" value="8"
+ summary="position to the right of the anchor edge"/>
+ </enum>
+
+ <request name="set_gravity">
+ <description summary="set child surface gravity">
+ Defines in what direction a surface should be positioned, relative to
+ the anchor point of the parent surface. If two orthogonal gravities are
+ specified (e.g. 'bottom' and 'right'), then the child surface will be
+ placed in the specified direction; otherwise, the child surface will be
+ centered over the anchor point on any axis that had no gravity
+ specified.
+
+ If two parallel gravities are specified (e.g. 'left' and 'right'), the
+ invalid_input error is raised.
+ </description>
+ <arg name="gravity" type="uint" enum="gravity"
+ summary="bit mask of gravity directions"/>
+ </request>
+
+ <enum name="constraint_adjustment" bitfield="true">
+ <description summary="constraint adjustments">
+ The constraint adjustment value define ways the compositor will adjust
+ the position of the surface, if the unadjusted position would result
+ in the surface being partly constrained.
+
+ Whether a surface is considered 'constrained' is left to the compositor
+ to determine. For example, the surface may be partly outside the
+ compositor's defined 'work area', thus necessitating the child surface's
+ position be adjusted until it is entirely inside the work area.
+
+ The adjustments can be combined, according to a defined precedence: 1)
+ Flip, 2) Slide, 3) Resize.
+ </description>
+
+ <entry name="none" value="0">
+ <description summary="don't move the child surface when constrained">
+ Don't alter the surface position even if it is constrained on some
+ axis, for example partially outside the edge of a monitor.
+ </description>
+ </entry>
+ <entry name="slide_x" value="1">
+ <description summary="move along the x axis until unconstrained">
+ Slide the surface along the x axis until it is no longer constrained.
+
+ First try to slide towards the direction of the gravity on the x axis
+ until either the edge in the opposite direction of the gravity is
+ unconstrained or the edge in the direction of the gravity is
+ constrained.
+
+ Then try to slide towards the opposite direction of the gravity on the
+ x axis until either the edge in the direction of the gravity is
+ unconstrained or the edge in the opposite direction of the gravity is
+ constrained.
+ </description>
+ </entry>
+ <entry name="slide_y" value="2">
+ <description summary="move along the y axis until unconstrained">
+ Slide the surface along the y axis until it is no longer constrained.
+
+ First try to slide towards the direction of the gravity on the y axis
+ until either the edge in the opposite direction of the gravity is
+ unconstrained or the edge in the direction of the gravity is
+ constrained.
+
+ Then try to slide towards the opposite direction of the gravity on the
+ y axis until either the edge in the direction of the gravity is
+ unconstrained or the edge in the opposite direction of the gravity is
+ constrained.
+ </description>
+ </entry>
+ <entry name="flip_x" value="4">
+ <description summary="invert the anchor and gravity on the x axis">
+ Invert the anchor and gravity on the x axis if the surface is
+ constrained on the x axis. For example, if the left edge of the
+ surface is constrained, the gravity is 'left' and the anchor is
+ 'left', change the gravity to 'right' and the anchor to 'right'.
+
+ If the adjusted position also ends up being constrained, the resulting
+ position of the flip_x adjustment will be the one before the
+ adjustment.
+ </description>
+ </entry>
+ <entry name="flip_y" value="8">
+ <description summary="invert the anchor and gravity on the y axis">
+ Invert the anchor and gravity on the y axis if the surface is
+ constrained on the y axis. For example, if the bottom edge of the
+ surface is constrained, the gravity is 'bottom' and the anchor is
+ 'bottom', change the gravity to 'top' and the anchor to 'top'.
+
+ If the adjusted position also ends up being constrained, the resulting
+ position of the flip_y adjustment will be the one before the
+ adjustment.
+ </description>
+ </entry>
+ <entry name="resize_x" value="16">
+ <description summary="horizontally resize the surface">
+ Resize the surface horizontally so that it is completely
+ unconstrained.
+ </description>
+ </entry>
+ <entry name="resize_y" value="32">
+ <description summary="vertically resize the surface">
+ Resize the surface vertically so that it is completely unconstrained.
+ </description>
+ </entry>
+ </enum>
+
+ <request name="set_constraint_adjustment">
+ <description summary="set the adjustment to be done when constrained">
+ Specify how the window should be positioned if the originally intended
+ position caused the surface to be constrained, meaning at least
+ partially outside positioning boundaries set by the compositor. The
+ adjustment is set by constructing a bitmask describing the adjustment to
+ be made when the surface is constrained on that axis.
+
+ If no bit for one axis is set, the compositor will assume that the child
+ surface should not change its position on that axis when constrained.
+
+ If more than one bit for one axis is set, the order of how adjustments
+ are applied is specified in the corresponding adjustment descriptions.
+
+ The default adjustment is none.
+ </description>
+ <arg name="constraint_adjustment" type="uint"
+ summary="bit mask of constraint adjustments"/>
+ </request>
+
+ <request name="set_offset">
+ <description summary="set surface position offset">
+ Specify the surface position offset relative to the position of the
+ anchor on the anchor rectangle and the anchor on the surface. For
+ example if the anchor of the anchor rectangle is at (x, y), the surface
+ has the gravity bottom|right, and the offset is (ox, oy), the calculated
+ surface position will be (x + ox, y + oy). The offset position of the
+ surface is the one used for constraint testing. See
+ set_constraint_adjustment.
+
+ An example use case is placing a popup menu on top of a user interface
+ element, while aligning the user interface element of the parent surface
+ with some user interface element placed somewhere in the popup surface.
+ </description>
+ <arg name="x" type="int" summary="surface position x offset"/>
+ <arg name="y" type="int" summary="surface position y offset"/>
+ </request>
+ </interface>
+
+ <interface name="zxdg_surface_v6" version="1">
+ <description summary="desktop user interface surface base interface">
+ An interface that may be implemented by a wl_surface, for
+ implementations that provide a desktop-style user interface.
+
+ It provides a base set of functionality required to construct user
+ interface elements requiring management by the compositor, such as
+ toplevel windows, menus, etc. The types of functionality are split into
+ xdg_surface roles.
+
+ Creating an xdg_surface does not set the role for a wl_surface. In order
+ to map an xdg_surface, the client must create a role-specific object
+ using, e.g., get_toplevel, get_popup. The wl_surface for any given
+ xdg_surface can have at most one role, and may not be assigned any role
+ not based on xdg_surface.
+
+ A role must be assigned before any other requests are made to the
+ xdg_surface object.
+
+ The client must call wl_surface.commit on the corresponding wl_surface
+ for the xdg_surface state to take effect.
+
+ Creating an xdg_surface from a wl_surface which has a buffer attached or
+ committed is a client error, and any attempts by a client to attach or
+ manipulate a buffer prior to the first xdg_surface.configure call must
+ also be treated as errors.
+
+ For a surface to be mapped by the compositor, the following conditions
+ must be met: (1) the client has assigned a xdg_surface based role to the
+ surface, (2) the client has set and committed the xdg_surface state and
+ the role dependent state to the surface and (3) the client has committed a
+ buffer to the surface.
+ </description>
+
+ <enum name="error">
+ <entry name="not_constructed" value="1"/>
+ <entry name="already_constructed" value="2"/>
+ <entry name="unconfigured_buffer" value="3"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the xdg_surface">
+ Destroy the xdg_surface object. An xdg_surface must only be destroyed
+ after its role object has been destroyed.
+ </description>
+ </request>
+
+ <request name="get_toplevel">
+ <description summary="assign the xdg_toplevel surface role">
+ This creates an xdg_toplevel object for the given xdg_surface and gives
+ the associated wl_surface the xdg_toplevel role.
+
+ See the documentation of xdg_toplevel for more details about what an
+ xdg_toplevel is and how it is used.
+ </description>
+ <arg name="id" type="new_id" interface="zxdg_toplevel_v6"/>
+ </request>
+
+ <request name="get_popup">
+ <description summary="assign the xdg_popup surface role">
+ This creates an xdg_popup object for the given xdg_surface and gives the
+ associated wl_surface the xdg_popup role.
+
+ See the documentation of xdg_popup for more details about what an
+ xdg_popup is and how it is used.
+ </description>
+ <arg name="id" type="new_id" interface="zxdg_popup_v6"/>
+ <arg name="parent" type="object" interface="zxdg_surface_v6"/>
+ <arg name="positioner" type="object" interface="zxdg_positioner_v6"/>
+ </request>
+
+ <request name="set_window_geometry">
+ <description summary="set the new window geometry">
+ The window geometry of a surface is its "visible bounds" from the
+ user's perspective. Client-side decorations often have invisible
+ portions like drop-shadows which should be ignored for the
+ purposes of aligning, placing and constraining windows.
+
+ The window geometry is double buffered, and will be applied at the
+ time wl_surface.commit of the corresponding wl_surface is called.
+
+ Once the window geometry of the surface is set, it is not possible to
+ unset it, and it will remain the same until set_window_geometry is
+ called again, even if a new subsurface or buffer is attached.
+
+ If never set, the value is the full bounds of the surface,
+ including any subsurfaces. This updates dynamically on every
+ commit. This unset is meant for extremely simple clients.
+
+ The arguments are given in the surface-local coordinate space of
+ the wl_surface associated with this xdg_surface.
+
+ The width and height must be greater than zero. Setting an invalid size
+ will raise an error. When applied, the effective window geometry will be
+ the set window geometry clamped to the bounding rectangle of the
+ combined geometry of the surface of the xdg_surface and the associated
+ subsurfaces.
+ </description>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </request>
+
+ <request name="ack_configure">
+ <description summary="ack a configure event">
+ When a configure event is received, if a client commits the
+ surface in response to the configure event, then the client
+ must make an ack_configure request sometime before the commit
+ request, passing along the serial of the configure event.
+
+ For instance, for toplevel surfaces the compositor might use this
+ information to move a surface to the top left only when the client has
+ drawn itself for the maximized or fullscreen state.
+
+ If the client receives multiple configure events before it
+ can respond to one, it only has to ack the last configure event.
+
+ A client is not required to commit immediately after sending
+ an ack_configure request - it may even ack_configure several times
+ before its next surface commit.
+
+ A client may send multiple ack_configure requests before committing, but
+ only the last request sent before a commit indicates which configure
+ event the client really is responding to.
+ </description>
+ <arg name="serial" type="uint" summary="the serial from the configure event"/>
+ </request>
+
+ <event name="configure">
+ <description summary="suggest a surface change">
+ The configure event marks the end of a configure sequence. A configure
+ sequence is a set of one or more events configuring the state of the
+ xdg_surface, including the final xdg_surface.configure event.
+
+ Where applicable, xdg_surface surface roles will during a configure
+ sequence extend this event as a latched state sent as events before the
+ xdg_surface.configure event. Such events should be considered to make up
+ a set of atomically applied configuration states, where the
+ xdg_surface.configure commits the accumulated state.
+
+ Clients should arrange their surface for the new states, and then send
+ an ack_configure request with the serial sent in this configure event at
+ some point before committing the new surface.
+
+ If the client receives multiple configure events before it can respond
+ to one, it is free to discard all but the last event it received.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the configure event"/>
+ </event>
+ </interface>
+
+ <interface name="zxdg_toplevel_v6" version="1">
+ <description summary="toplevel surface">
+ This interface defines an xdg_surface role which allows a surface to,
+ among other things, set window-like properties such as maximize,
+ fullscreen, and minimize, set application-specific metadata like title and
+ id, and well as trigger user interactive operations such as interactive
+ resize and move.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the xdg_toplevel">
+ Unmap and destroy the window. The window will be effectively
+ hidden from the user's point of view, and all state like
+ maximization, fullscreen, and so on, will be lost.
+ </description>
+ </request>
+
+ <request name="set_parent">
+ <description summary="set the parent of this surface">
+ Set the "parent" of this surface. This window should be stacked
+ above a parent. The parent surface must be mapped as long as this
+ surface is mapped.
+
+ Parent windows should be set on dialogs, toolboxes, or other
+ "auxiliary" surfaces, so that the parent is raised when the dialog
+ is raised.
+ </description>
+ <arg name="parent" type="object" interface="zxdg_toplevel_v6" allow-null="true"/>
+ </request>
+
+ <request name="set_title">
+ <description summary="set surface title">
+ Set a short title for the surface.
+
+ This string may be used to identify the surface in a task bar,
+ window list, or other user interface elements provided by the
+ compositor.
+
+ The string must be encoded in UTF-8.
+ </description>
+ <arg name="title" type="string"/>
+ </request>
+
+ <request name="set_app_id">
+ <description summary="set application ID">
+ Set an application identifier for the surface.
+
+ The app ID identifies the general class of applications to which
+ the surface belongs. The compositor can use this to group multiple
+ surfaces together, or to determine how to launch a new application.
+
+ For D-Bus activatable applications, the app ID is used as the D-Bus
+ service name.
+
+ The compositor shell will try to group application surfaces together
+ by their app ID. As a best practice, it is suggested to select app
+ ID's that match the basename of the application's .desktop file.
+ For example, "org.freedesktop.FooViewer" where the .desktop file is
+ "org.freedesktop.FooViewer.desktop".
+
+ See the desktop-entry specification [0] for more details on
+ application identifiers and how they relate to well-known D-Bus
+ names and .desktop files.
+
+ [0] http://standards.freedesktop.org/desktop-entry-spec/
+ </description>
+ <arg name="app_id" type="string"/>
+ </request>
+
+ <request name="show_window_menu">
+ <description summary="show the window menu">
+ Clients implementing client-side decorations might want to show
+ a context menu when right-clicking on the decorations, giving the
+ user a menu that they can use to maximize or minimize the window.
+
+ This request asks the compositor to pop up such a window menu at
+ the given position, relative to the local surface coordinates of
+ the parent surface. There are no guarantees as to what menu items
+ the window menu contains.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event.
+ </description>
+
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
+ <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
+ </request>
+
+ <request name="move">
+ <description summary="start an interactive move">
+ Start an interactive, user-driven move of the surface.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event. The passed
+ serial is used to determine the type of interactive move (touch,
+ pointer, etc).
+
+ The server may ignore move requests depending on the state of
+ the surface (e.g. fullscreen or maximized), or if the passed serial
+ is no longer valid.
+
+ If triggered, the surface will lose the focus of the device
+ (wl_pointer, wl_touch, etc) used for the move. It is up to the
+ compositor to visually indicate that the move is taking place, such as
+ updating a pointer cursor, during the move. There is no guarantee
+ that the device focus will return when the move is completed.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ </request>
+
+ <enum name="resize_edge">
+ <description summary="edge values for resizing">
+ These values are used to indicate which edge of a surface
+ is being dragged in a resize operation.
+ </description>
+ <entry name="none" value="0"/>
+ <entry name="top" value="1"/>
+ <entry name="bottom" value="2"/>
+ <entry name="left" value="4"/>
+ <entry name="top_left" value="5"/>
+ <entry name="bottom_left" value="6"/>
+ <entry name="right" value="8"/>
+ <entry name="top_right" value="9"/>
+ <entry name="bottom_right" value="10"/>
+ </enum>
+
+ <request name="resize">
+ <description summary="start an interactive resize">
+ Start a user-driven, interactive resize of the surface.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event. The passed
+ serial is used to determine the type of interactive resize (touch,
+ pointer, etc).
+
+ The server may ignore resize requests depending on the state of
+ the surface (e.g. fullscreen or maximized).
+
+ If triggered, the client will receive configure events with the
+ "resize" state enum value and the expected sizes. See the "resize"
+ enum value for more details about what is required. The client
+ must also acknowledge configure events using "ack_configure". After
+ the resize is completed, the client will receive another "configure"
+ event without the resize state.
+
+ If triggered, the surface also will lose the focus of the device
+ (wl_pointer, wl_touch, etc) used for the resize. It is up to the
+ compositor to visually indicate that the resize is taking place,
+ such as updating a pointer cursor, during the resize. There is no
+ guarantee that the device focus will return when the resize is
+ completed.
+
+ The edges parameter specifies how the surface should be resized,
+ and is one of the values of the resize_edge enum. The compositor
+ may use this information to update the surface position for
+ example when dragging the top left corner. The compositor may also
+ use this information to adapt its behavior, e.g. choose an
+ appropriate cursor image.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ <arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
+ </request>
+
+ <enum name="state">
+ <description summary="types of state on the surface">
+ The different state values used on the surface. This is designed for
+ state values like maximized, fullscreen. It is paired with the
+ configure event to ensure that both the client and the compositor
+ setting the state can be synchronized.
+
+ States set in this way are double-buffered. They will get applied on
+ the next commit.
+ </description>
+ <entry name="maximized" value="1" summary="the surface is maximized">
+ <description summary="the surface is maximized">
+ The surface is maximized. The window geometry specified in the configure
+ event must be obeyed by the client.
+ </description>
+ </entry>
+ <entry name="fullscreen" value="2" summary="the surface is fullscreen">
+ <description summary="the surface is fullscreen">
+ The surface is fullscreen. The window geometry specified in the configure
+ event must be obeyed by the client.
+ </description>
+ </entry>
+ <entry name="resizing" value="3" summary="the surface is being resized">
+ <description summary="the surface is being resized">
+ The surface is being resized. The window geometry specified in the
+ configure event is a maximum; the client cannot resize beyond it.
+ Clients that have aspect ratio or cell sizing configuration can use
+ a smaller size, however.
+ </description>
+ </entry>
+ <entry name="activated" value="4" summary="the surface is now activated">
+ <description summary="the surface is now activated">
+ Client window decorations should be painted as if the window is
+ active. Do not assume this means that the window actually has
+ keyboard or pointer focus.
+ </description>
+ </entry>
+ </enum>
+
+ <request name="set_max_size">
+ <description summary="set the maximum size">
+ Set a maximum size for the window.
+
+ The client can specify a maximum size so that the compositor does
+ not try to configure the window beyond this size.
+
+ The width and height arguments are in window geometry coordinates.
+ See xdg_surface.set_window_geometry.
+
+ Values set in this way are double-buffered. They will get applied
+ on the next commit.
+
+ The compositor can use this information to allow or disallow
+ different states like maximize or fullscreen and draw accurate
+ animations.
+
+ Similarly, a tiling window manager may use this information to
+ place and resize client windows in a more effective way.
+
+ The client should not rely on the compositor to obey the maximum
+ size. The compositor may decide to ignore the values set by the
+ client and request a larger size.
+
+ If never set, or a value of zero in the request, means that the
+ client has no expected maximum size in the given dimension.
+ As a result, a client wishing to reset the maximum size
+ to an unspecified state can use zero for width and height in the
+ request.
+
+ Requesting a maximum size to be smaller than the minimum size of
+ a surface is illegal and will result in a protocol error.
+
+ The width and height must be greater than or equal to zero. Using
+ strictly negative values for width and height will result in a
+ protocol error.
+ </description>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </request>
+
+ <request name="set_min_size">
+ <description summary="set the minimum size">
+ Set a minimum size for the window.
+
+ The client can specify a minimum size so that the compositor does
+ not try to configure the window below this size.
+
+ The width and height arguments are in window geometry coordinates.
+ See xdg_surface.set_window_geometry.
+
+ Values set in this way are double-buffered. They will get applied
+ on the next commit.
+
+ The compositor can use this information to allow or disallow
+ different states like maximize or fullscreen and draw accurate
+ animations.
+
+ Similarly, a tiling window manager may use this information to
+ place and resize client windows in a more effective way.
+
+ The client should not rely on the compositor to obey the minimum
+ size. The compositor may decide to ignore the values set by the
+ client and request a smaller size.
+
+ If never set, or a value of zero in the request, means that the
+ client has no expected minimum size in the given dimension.
+ As a result, a client wishing to reset the minimum size
+ to an unspecified state can use zero for width and height in the
+ request.
+
+ Requesting a minimum size to be larger than the maximum size of
+ a surface is illegal and will result in a protocol error.
+
+ The width and height must be greater than or equal to zero. Using
+ strictly negative values for width and height will result in a
+ protocol error.
+ </description>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </request>
+
+ <request name="set_maximized">
+ <description summary="maximize the window">
+ Maximize the surface.
+
+ After requesting that the surface should be maximized, the compositor
+ will respond by emitting a configure event with the "maximized" state
+ and the required window geometry. The client should then update its
+ content, drawing it in a maximized state, i.e. without shadow or other
+ decoration outside of the window geometry. The client must also
+ acknowledge the configure when committing the new content (see
+ ack_configure).
+
+ It is up to the compositor to decide how and where to maximize the
+ surface, for example which output and what region of the screen should
+ be used.
+
+ If the surface was already maximized, the compositor will still emit
+ a configure event with the "maximized" state.
+ </description>
+ </request>
+
+ <request name="unset_maximized">
+ <description summary="unmaximize the window">
+ Unmaximize the surface.
+
+ After requesting that the surface should be unmaximized, the compositor
+ will respond by emitting a configure event without the "maximized"
+ state. If available, the compositor will include the window geometry
+ dimensions the window had prior to being maximized in the configure
+ request. The client must then update its content, drawing it in a
+ regular state, i.e. potentially with shadow, etc. The client must also
+ acknowledge the configure when committing the new content (see
+ ack_configure).
+
+ It is up to the compositor to position the surface after it was
+ unmaximized; usually the position the surface had before maximizing, if
+ applicable.
+
+ If the surface was already not maximized, the compositor will still
+ emit a configure event without the "maximized" state.
+ </description>
+ </request>
+
+ <request name="set_fullscreen">
+ <description summary="set the window as fullscreen on a monitor">
+ Make the surface fullscreen.
+
+ You can specify an output that you would prefer to be fullscreen.
+ If this value is NULL, it's up to the compositor to choose which
+ display will be used to map this surface.
+
+ If the surface doesn't cover the whole output, the compositor will
+ position the surface in the center of the output and compensate with
+ black borders filling the rest of the output.
+ </description>
+ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
+ </request>
+ <request name="unset_fullscreen" />
+
+ <request name="set_minimized">
+ <description summary="set the window as minimized">
+ Request that the compositor minimize your surface. There is no
+ way to know if the surface is currently minimized, nor is there
+ any way to unset minimization on this surface.
+
+ If you are looking to throttle redrawing when minimized, please
+ instead use the wl_surface.frame event for this, as this will
+ also work with live previews on windows in Alt-Tab, Expose or
+ similar compositor features.
+ </description>
+ </request>
+
+ <event name="configure">
+ <description summary="suggest a surface change">
+ This configure event asks the client to resize its toplevel surface or
+ to change its state. The configured state should not be applied
+ immediately. See xdg_surface.configure for details.
+
+ The width and height arguments specify a hint to the window
+ about how its surface should be resized in window geometry
+ coordinates. See set_window_geometry.
+
+ If the width or height arguments are zero, it means the client
+ should decide its own window dimension. This may happen when the
+ compositor need to configure the state of the surface but doesn't
+ have any information about any previous or expected dimension.
+
+ The states listed in the event specify how the width/height
+ arguments should be interpreted, and possibly how it should be
+ drawn.
+
+ Clients must send an ack_configure in response to this event. See
+ xdg_surface.configure and xdg_surface.ack_configure for details.
+ </description>
+
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="states" type="array"/>
+ </event>
+
+ <event name="close">
+ <description summary="surface wants to be closed">
+ The close event is sent by the compositor when the user
+ wants the surface to be closed. This should be equivalent to
+ the user clicking the close button in client-side decorations,
+ if your application has any...
+
+ This is only a request that the user intends to close your
+ window. The client may choose to ignore this request, or show
+ a dialog to ask the user to save their data...
+ </description>
+ </event>
+ </interface>
+
+ <interface name="zxdg_popup_v6" version="1">
+ <description summary="short-lived, popup surfaces for menus">
+ A popup surface is a short-lived, temporary surface. It can be used to
+ implement for example menus, popovers, tooltips and other similar user
+ interface concepts.
+
+ A popup can be made to take an explicit grab. See xdg_popup.grab for
+ details.
+
+ When the popup is dismissed, a popup_done event will be sent out, and at
+ the same time the surface will be unmapped. See the xdg_popup.popup_done
+ event for details.
+
+ Explicitly destroying the xdg_popup object will also dismiss the popup and
+ unmap the surface. Clients that want to dismiss the popup when another
+ surface of their own is clicked should dismiss the popup using the destroy
+ request.
+
+ The parent surface must have either the xdg_toplevel or xdg_popup surface
+ role.
+
+ A newly created xdg_popup will be stacked on top of all previously created
+ xdg_popup surfaces associated with the same xdg_toplevel.
+
+ The parent of an xdg_popup must be mapped (see the xdg_surface
+ description) before the xdg_popup itself.
+
+ The x and y arguments passed when creating the popup object specify
+ where the top left of the popup should be placed, relative to the
+ local surface coordinates of the parent surface. See
+ xdg_surface.get_popup.
+
+ The client must call wl_surface.commit on the corresponding wl_surface
+ for the xdg_popup state to take effect.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_grab" value="0"
+ summary="tried to grab after being mapped"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="remove xdg_popup interface">
+ This destroys the popup. Explicitly destroying the xdg_popup
+ object will also dismiss the popup, and unmap the surface.
+
+ If this xdg_popup is not the "topmost" popup, a protocol error
+ will be sent.
+ </description>
+ </request>
+
+ <request name="grab">
+ <description summary="make the popup take an explicit grab">
+ This request makes the created popup take an explicit grab. An explicit
+ grab will be dismissed when the user dismisses the popup, or when the
+ client destroys the xdg_popup. This can be done by the user clicking
+ outside the surface, using the keyboard, or even locking the screen
+ through closing the lid or a timeout.
+
+ If the compositor denies the grab, the popup will be immediately
+ dismissed.
+
+ This request must be used in response to some sort of user action like a
+ button press, key press, or touch down event. The serial number of the
+ event should be passed as 'serial'.
+
+ The parent of a grabbing popup must either be an xdg_toplevel surface or
+ another xdg_popup with an explicit grab. If the parent is another
+ xdg_popup it means that the popups are nested, with this popup now being
+ the topmost popup.
+
+ Nested popups must be destroyed in the reverse order they were created
+ in, e.g. the only popup you are allowed to destroy at all times is the
+ topmost one.
+
+ When compositors choose to dismiss a popup, they may dismiss every
+ nested grabbing popup as well. When a compositor dismisses popups, it
+ will follow the same dismissing order as required from the client.
+
+ The parent of a grabbing popup must either be another xdg_popup with an
+ active explicit grab, or an xdg_popup or xdg_toplevel, if there are no
+ explicit grabs already taken.
+
+ If the topmost grabbing popup is destroyed, the grab will be returned to
+ the parent of the popup, if that parent previously had an explicit grab.
+
+ If the parent is a grabbing popup which has already been dismissed, this
+ popup will be immediately dismissed. If the parent is a popup that did
+ not take an explicit grab, an error will be raised.
+
+ During a popup grab, the client owning the grab will receive pointer
+ and touch events for all their surfaces as normal (similar to an
+ "owner-events" grab in X11 parlance), while the top most grabbing popup
+ will always have keyboard focus.
+ </description>
+
+ <arg name="seat" type="object" interface="wl_seat"
+ summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ </request>
+
+ <event name="configure">
+ <description summary="configure the popup surface">
+ This event asks the popup surface to configure itself given the
+ configuration. The configured state should not be applied immediately.
+ See xdg_surface.configure for details.
+
+ The x and y arguments represent the position the popup was placed at
+ given the xdg_positioner rule, relative to the upper left corner of the
+ window geometry of the parent surface.
+ </description>
+ <arg name="x" type="int"
+ summary="x position relative to parent surface window geometry"/>
+ <arg name="y" type="int"
+ summary="y position relative to parent surface window geometry"/>
+ <arg name="width" type="int" summary="window geometry width"/>
+ <arg name="height" type="int" summary="window geometry height"/>
+ </event>
+
+ <event name="popup_done">
+ <description summary="popup interaction is done">
+ The popup_done event is sent out when a popup is dismissed by the
+ compositor. The client should destroy the xdg_popup object at this
+ point.
+ </description>
+ </event>
+
+ </interface>
+</protocol>
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index 480f29638b..e64c046327 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -3,6 +3,7 @@
* Copyright © 2008 Kristian Høgsberg
* Copyright © 2012-2013 Collabora, Ltd.
* Copyright © 2013 Alexander Preisinger <alexander.preisinger@gmail.com>
+ * Copyright © 2016 Rostislav Pehlivanov <atomnuker@gmail.com>
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -46,6 +47,7 @@
#include "input/input.h"
#include "input/event.h"
#include "input/keycodes.h"
+#include "sub/osd.h"
static int lookupkey(int key);
@@ -54,11 +56,7 @@ static void show_cursor(struct vo_wayland_state * wl);
static void window_move(struct vo_wayland_state * wl, uint32_t serial);
static void window_set_title(struct vo_wayland_state * wl, const char *title);
static void schedule_resize(struct vo_wayland_state *wl,
- uint32_t edges,
- int32_t width,
- int32_t height);
-
-static void vo_wayland_fullscreen(struct vo *vo);
+ int32_t width, int32_t height);
static const struct wl_callback_listener frame_listener;
@@ -127,37 +125,77 @@ static const struct mp_keymap keymap[] = {
/** Wayland listeners **/
-static void ssurface_handle_ping(void *data,
- struct wl_shell_surface *shell_surface,
+static void xdg_handle_ping(void *data, struct zxdg_shell_v6 *shell, uint32_t serial)
+{
+ zxdg_shell_v6_pong(shell, serial);
+}
+
+static const struct zxdg_shell_v6_listener xdg_shell_listener = {
+ xdg_handle_ping,
+};
+
+static void xdg_handle_configure(void *data, struct zxdg_surface_v6 *surface,
uint32_t serial)
{
- wl_shell_surface_pong(shell_surface, serial);
+ zxdg_surface_v6_ack_configure(surface, serial);
}
-static void ssurface_handle_configure(void *data,
- struct wl_shell_surface *shell_surface,
- uint32_t edges,
- int32_t width,
- int32_t height)
+const struct zxdg_surface_v6_listener xdg_surface_listener = {
+ xdg_handle_configure,
+};
+
+static void handle_toplevel_configure(void *data, struct zxdg_toplevel_v6 *toplevel,
+ int32_t width, int32_t height,
+ struct wl_array *states)
{
struct vo_wayland_state *wl = data;
- float win_aspect = wl->window.aspect;
- if (!width || !height)
- return;
- if (!wl->window.is_fullscreen)
- width = win_aspect * height;
- schedule_resize(wl, edges, width, height);
+ uint32_t *state;
+
+ if (!width) {
+ width = wl->window.p_width;
+ }
+
+ if (!height) {
+ height = wl->window.p_height;
+ }
+
+ if (wl->display.current_output) {
+ int scale = wl->display.current_output->scale;
+ width = MPMIN(width, wl->display.current_output->width/scale);
+ height = MPMIN(height, wl->display.current_output->height/scale);
+ }
+
+ wl->window.state.fullscreen = false;
+
+ wl_array_for_each(state, states) {
+ switch (*state) {
+ case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
+ wl->window.state.fullscreen = true;
+ break;
+ case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED:
+ break;
+ case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED: /* Window is focused */
+ break;
+ case ZXDG_TOPLEVEL_V6_STATE_RESIZING:
+ break;
+ default:
+ /* Undefined state */
+ break;
+ }
+ }
+
+ schedule_resize(wl, width, height);
}
-static void ssurface_handle_popup_done(void *data,
- struct wl_shell_surface *shell_surface)
+static void handle_toplevel_close(void *data, struct zxdg_toplevel_v6 *xdg_toplevel)
{
+ struct vo_wayland_state *wl = data;
+ mp_input_put_key(wl->vo->input_ctx, MP_KEY_CLOSE_WIN);
}
-static const struct wl_shell_surface_listener shell_surface_listener = {
- ssurface_handle_ping,
- ssurface_handle_configure,
- ssurface_handle_popup_done
+static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
+ handle_toplevel_configure,
+ handle_toplevel_close,
};
static void output_handle_geometry(void *data,
@@ -540,9 +578,9 @@ static void registry_handle_global(void *data, struct wl_registry *reg,
MPMIN(3, version));
}
- else if (strcmp(interface, "wl_shell") == 0) {
-
- wl->display.shell = wl_registry_bind(reg, id, &wl_shell_interface, 1);
+ else if (strcmp(interface, "zxdg_shell_v6") == 0) {
+ wl->display.shell = wl_registry_bind(reg, id, &zxdg_shell_v6_interface, 1);
+ zxdg_shell_v6_add_listener(wl->display.shell, &xdg_shell_listener, wl);
}
else if (strcmp(interface, "wl_shm") == 0) {
@@ -638,77 +676,29 @@ static void show_cursor (struct vo_wayland_state *wl)
static void window_move(struct vo_wayland_state *wl, uint32_t serial)
{
- if (wl->display.shell)
- wl_shell_surface_move(wl->window.shell_surface, wl->input.seat, serial);
-}
-
-static void window_set_toplevel(struct vo_wayland_state *wl)
-{
- if (wl->display.shell)
- wl_shell_surface_set_toplevel(wl->window.shell_surface);
+ zxdg_toplevel_v6_move(wl->window.xdg_toplevel, wl->input.seat, serial);
}
static void window_set_title(struct vo_wayland_state *wl, const char *title)
{
if (wl->display.shell)
- wl_shell_surface_set_title(wl->window.shell_surface, title);
+ zxdg_toplevel_v6_set_title(wl->window.xdg_toplevel, title);
}
static void schedule_resize(struct vo_wayland_state *wl,
- uint32_t edges,
int32_t width,
int32_t height)
{
- int32_t minimum_size = 150;
- int32_t x, y;
- float win_aspect = wl->window.aspect;
- if (win_aspect <= 0)
- win_aspect = 1;
-
- MP_DBG(wl, "schedule resize: %dx%d\n", width, height);
-
- width = MPMAX(minimum_size, width);
- height = MPMAX(minimum_size, height);
- if (wl->display.current_output) {
- int scale = wl->display.current_output->scale;
- width = MPMIN(width, wl->display.current_output->width /scale);
- height = MPMIN(height, wl->display.current_output->height/scale);
- }
-
- // don't keep the aspect ration in fullscreen mode, because the compositor
- // shows the desktop in the border regions if the video has not the same
- // aspect ration as the screen
- /* if only the height is changed we have to calculate the width
- * in any other case we calculate the height */
- switch (edges) {
- case WL_SHELL_SURFACE_RESIZE_TOP:
- case WL_SHELL_SURFACE_RESIZE_BOTTOM:
- width = win_aspect * height;
- break;
- case WL_SHELL_SURFACE_RESIZE_LEFT:
- case WL_SHELL_SURFACE_RESIZE_RIGHT:
- case WL_SHELL_SURFACE_RESIZE_TOP_LEFT: // just a preference
- case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT:
- case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT:
- case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT:
- height = (1 / win_aspect) * width;
- break;
- }
-
- if (edges & WL_SHELL_SURFACE_RESIZE_LEFT)
- x = wl->window.width - width;
- else
- x = 0;
+ MP_DBG(wl, "shedule resize: %dx%d\n", width, height);
+ wl->vo->dwidth = width;
+ wl->vo->dheight = height;
- if (edges & WL_SHELL_SURFACE_RESIZE_TOP)
- y = wl->window.height - height;
- else
- y = 0;
+ struct mp_rect src, dst;
+ struct mp_osd_res osd;
+ vo_get_src_dst_rects(wl->vo, &src, &dst, &osd);
- wl->window.sh_width = width;
- wl->window.sh_height = height;
- wl->window.sh_x = x;
- wl->window.sh_y = y;
+ wl->window.sh_width = dst.x1 - dst.x0;
+ wl->window.sh_height = dst.y1 - dst.y0;
wl->window.events |= VO_EVENT_RESIZE;
}
@@ -781,7 +771,7 @@ static void destroy_display(struct vo_wayland_state *wl)
wl_shm_destroy(wl->display.shm);
if (wl->display.shell)
- wl_shell_destroy(wl->display.shell);
+ zxdg_shell_v6_destroy(wl->display.shell);
if (wl->display.subcomp)
wl_subcompositor_destroy(wl->display.subcomp);
@@ -807,19 +797,22 @@ static bool create_window(struct vo_wayland_state *wl)
&surface_listener, wl);
if (wl->display.shell) {
- wl->window.shell_surface = wl_shell_get_shell_surface(wl->display.shell,
- wl->window.video_surface);
+ wl->window.xdg_surface = zxdg_shell_v6_get_xdg_surface(wl->display.shell,
+ wl->window.video_surface);
- if (!wl->window.shell_surface) {
- MP_ERR(wl, "creating shell surface failed\n");
+ if (!wl->window.xdg_surface) {
+ MP_ERR(wl, "creating xdg surface failed\n");
return false;
}
- wl_shell_surface_add_listener(wl->window.shell_surface,
- &shell_surface_listener, wl);
+ zxdg_surface_v6_add_listener(wl->window.xdg_surface,
+ &xdg_surface_listener, wl);
- wl_shell_surface_set_toplevel(wl->window.shell_surface);
- wl_shell_surface_set_class(wl->window.shell_surface, "mpv");
+ wl->window.xdg_toplevel = zxdg_surface_v6_get_toplevel(wl->window.xdg_surface);
+
+ zxdg_toplevel_v6_add_listener(wl->window.xdg_toplevel,
+ &xdg_toplevel_listener, wl);
+ zxdg_toplevel_v6_set_app_id(wl->window.xdg_toplevel, "mpv");
}
return true;
@@ -827,8 +820,8 @@ static bool create_window(struct vo_wayland_state *wl)
static void destroy_window(struct vo_wayland_state *wl)
{
- if (wl->window.shell_surface)
- wl_shell_surface_destroy(wl->window.shell_surface);
+ if (wl->window.xdg_surface)
+ zxdg_surface_v6_destroy(wl->window.xdg_surface);
if (wl->window.video_surface)
wl_surface_destroy(wl->window.video_surface);
@@ -954,42 +947,26 @@ void vo_wayland_uninit(struct vo *vo)
vo->wayland = NULL;
}
-static void vo_wayland_ontop(struct vo *vo)
-{
- struct vo_wayland_state *wl = vo->wayland;
- if (!vo->opts->ontop)
- return;
- MP_DBG(wl, "going ontop\n");
- window_set_toplevel(wl);
- schedule_resize(wl, 0, wl->window.width, wl->window.height);
-}
-
-static void vo_wayland_fullscreen(struct vo *vo)
+static void window_set_fullscreen(struct vo *vo)
{
struct vo_wayland_state *wl = vo->wayland;
if (!wl->display.shell)
return;
- struct wl_output *fs_output = wl->display.fs_output;
-
if (vo->opts->fullscreen) {
MP_DBG(wl, "going fullscreen\n");
- wl->window.is_fullscreen = true;
wl->window.p_width = wl->window.width;
wl->window.p_height = wl->window.height;
- if (wl->display.current_output)
- schedule_resize(wl, 0, wl->display.current_output->width,
- wl->display.current_output->height);
- wl_shell_surface_set_fullscreen(wl->window.shell_surface,
- WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
- 0, fs_output);
+ zxdg_toplevel_v6_set_fullscreen(wl->window.xdg_toplevel, NULL);
+ //if (wl->display.current_output)
+ //schedule_resize(wl, wl->display.current_output->width,
+ // wl->display.current_output->height);
}
else {
MP_DBG(wl, "leaving fullscreen\n");
- wl->window.is_fullscreen = false;
- window_set_toplevel(wl);
- schedule_resize(wl, 0, wl->window.p_width, wl->window.p_height);
+ zxdg_toplevel_v6_unset_fullscreen(wl->window.xdg_toplevel);
+ //schedule_resize(wl, wl->window.p_width, wl->window.p_height);
}
}
@@ -1047,10 +1024,7 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg)
wl->window.events = 0;
return VO_TRUE;
case VOCTRL_FULLSCREEN:
- vo_wayland_fullscreen(vo);
- return VO_TRUE;
- case VOCTRL_ONTOP:
- vo_wayland_ontop(vo);
+ window_set_fullscreen(vo);
return VO_TRUE;
case VOCTRL_GET_UNFS_WINDOW_SIZE: {
int *s = arg, scale = 1;
@@ -1062,8 +1036,8 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg)
}
case VOCTRL_SET_UNFS_WINDOW_SIZE: {
int *s = arg;
- if (!wl->window.is_fullscreen)
- schedule_resize(wl, 0, s[0], s[1]);
+ if (!wl->window.state.fullscreen)
+ schedule_resize(wl, s[0], s[1]);
return VO_TRUE;
}
case VOCTRL_SET_CURSOR_VISIBILITY:
@@ -1097,6 +1071,9 @@ bool vo_wayland_config(struct vo *vo)
{
struct vo_wayland_state *wl = vo->wayland;
+ // reset states
+ wl->window.state.fullscreen = false;
+
struct mp_rect screenrc;
vo_wayland_update_screeninfo(vo, &screenrc);
@@ -1110,7 +1087,7 @@ bool vo_wayland_config(struct vo *vo)
wl->window.width = vo->dwidth;
wl->window.height = vo->dheight;
- vo_wayland_fullscreen(vo);
+ window_set_fullscreen(vo);
return true;
}
diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h
index 4bb90d6520..b8ebc3c27d 100644
--- a/video/out/wayland_common.h
+++ b/video/out/wayland_common.h
@@ -33,6 +33,9 @@
#include <EGL/eglext.h>
#endif
+// Generated from xdg-shell.xml
+#include "video/out/wayland/xdg-shell-protocol.h"
+
struct vo;
struct vo_wayland_output {
@@ -80,7 +83,7 @@ struct vo_wayland_state {
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
- struct wl_shell *shell;
+ struct zxdg_shell_v6 *shell;
struct wl_list output_list;
struct wl_output *fs_output; /* fullscreen output */
@@ -100,18 +103,19 @@ struct vo_wayland_state {
int32_t p_height;
int32_t sh_width; // sheduled width for resizing
int32_t sh_height;
- int32_t sh_x; // x, y calculated with the drag edges for moving
- int32_t sh_y;
float aspect;
- bool is_fullscreen; // don't keep aspect ratio in fullscreen mode
+ struct {
+ bool fullscreen; // don't keep aspect ratio in fullscreen mode
+ } state;
int32_t fs_width; // fullscreen sizes
int32_t fs_height;
struct wl_surface *video_surface;
+ struct zxdg_surface_v6 *xdg_surface;
+ struct zxdg_toplevel_v6 *xdg_toplevel;
int32_t mouse_x; // mouse position inside the surface
int32_t mouse_y;
- struct wl_shell_surface *shell_surface;
int events; /* mplayer events (VO_EVENT_RESIZE) */
} window;
diff --git a/waftools/generators/sources.py b/waftools/generators/sources.py
index 6f1521036a..04826932d7 100644
--- a/waftools/generators/sources.py
+++ b/waftools/generators/sources.py
@@ -13,6 +13,9 @@ def __zshcomp_cmd__(ctx, argument):
return '"${{BIN_PERL}}" "{0}/TOOLS/zsh.pl" "{1}" > "${{TGT}}"' \
.format(ctx.srcnode.abspath(), argument)
+def __wayland_scanner_cmd__(ctx, argument):
+ return "${{WAYSCAN}} {0} < ${{SRC}} > ${{TGT}}".format(argument)
+
def __file2string__(ctx, **kwargs):
ctx(
rule = __file2string_cmd__(ctx),
@@ -44,7 +47,24 @@ def __zshcomp__(ctx, **kwargs):
**kwargs
)
-BuildContext.file2string = __file2string__
-BuildContext.matroska_header = __matroska_header__
-BuildContext.matroska_definitions = __matroska_definitions__
-BuildContext.zshcomp = __zshcomp__
+def __wayland_protocol_code__(ctx, **kwargs):
+ ctx(
+ rule = __wayland_scanner_cmd__(ctx, 'code'),
+ name = os.path.basename(kwargs['target']),
+ **kwargs
+ )
+
+def __wayland_protocol_header__(ctx, **kwargs):
+ ctx(
+ rule = __wayland_scanner_cmd__(ctx, 'client-header'),
+ before = ('c',),
+ name = os.path.basename(kwargs['target']),
+ **kwargs
+ )
+
+BuildContext.file2string = __file2string__
+BuildContext.matroska_header = __matroska_header__
+BuildContext.matroska_definitions = __matroska_definitions__
+BuildContext.wayland_protocol_code = __wayland_protocol_code__
+BuildContext.wayland_protocol_header = __wayland_protocol_header__
+BuildContext.zshcomp = __zshcomp__
diff --git a/wscript b/wscript
index 7dea08b8db..0fdd0a5b2e 100644
--- a/wscript
+++ b/wscript
@@ -620,9 +620,14 @@ video_output_features = [
'desc': 'GBM',
'deps': [ 'gbm.h' ],
'func': check_pkg_config('gbm'),
+ }, {
+ 'name': '--wayland-scanner',
+ 'desc': 'wayland-scanner',
+ 'func': check_program('wayland-scanner', 'WAYSCAN')
} , {
'name': '--wayland',
'desc': 'Wayland',
+ 'deps': [ 'wayland-scanner' ],
'func': check_pkg_config('wayland-client', '>= 1.6.0',
'wayland-cursor', '>= 1.6.0',
'xkbcommon', '>= 0.3.0'),
diff --git a/wscript_build.py b/wscript_build.py
index cfab785ec0..0cc88912e1 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -85,6 +85,14 @@ def build(ctx):
source = "demux/ebml.c",
target = "ebml_defs.c")
+ if ctx.dependency_satisfied('wayland-scanner'):
+ ctx.wayland_protocol_code(
+ source = "video/out/wayland/protocol/xdg-shell.xml",
+ target = "video/out/wayland/xdg-shell-protocol.c")
+ ctx.wayland_protocol_header(
+ source = "video/out/wayland/protocol/xdg-shell.xml",
+ target = "video/out/wayland/xdg-shell-protocol.h")
+
if ctx.env.DEST_OS == 'win32':
main_fn_c = 'osdep/main-fn-win.c'
elif ctx.dependency_satisfied('cocoa'):
@@ -386,6 +394,7 @@ def build(ctx):
( "video/out/wayland_common.c", "wayland" ),
( "video/out/wayland/buffer.c", "wayland" ),
( "video/out/wayland/memfile.c", "wayland" ),
+ ( "video/out/wayland/xdg-shell-protocol.c", "wayland" ),
( "video/out/win_state.c"),
( "video/out/x11_common.c", "x11" ),
( "video/out/drm_common.c", "drm" ),