diff options
-rw-r--r-- | src/3rdparty/protocol/xdg-shell.xml | 225 | ||||
-rw-r--r-- | src/client/qwaylandxdgsurface.cpp | 107 | ||||
-rw-r--r-- | src/client/qwaylandxdgsurface_p.h | 11 |
3 files changed, 159 insertions, 184 deletions
diff --git a/src/3rdparty/protocol/xdg-shell.xml b/src/3rdparty/protocol/xdg-shell.xml index 79a28317..275837f3 100644 --- a/src/3rdparty/protocol/xdg-shell.xml +++ b/src/3rdparty/protocol/xdg-shell.xml @@ -45,7 +45,7 @@ they implement using static_assert to ensure the protocol and implementation versions match. </description> - <entry name="current" value="3" summary="Always the latest version"/> + <entry name="current" value="4" summary="Always the latest version"/> </enum> @@ -137,11 +137,8 @@ </description> </request> - <request name="set_transient_for"> + <request name="set_parent"> <description summary="surface is a child of another surface"> - Setting a surface as transient of another means that it is child - of another surface. - Child surfaces are stacked above their parents, and will be unmapped if the parent is unmapped too. They should not appear on task bars and alt+tab. @@ -149,32 +146,6 @@ <arg name="parent" type="object" interface="wl_surface" allow-null="true"/> </request> - <request name="set_margin"> - <description summary="set the visible frame boundaries"> - This tells the compositor what the visible size of the window - should be, so it can use it to determine what borders to use for - constrainment and alignment. - - CSD often has invisible areas for decoration purposes, like drop - shadows. These "shadow" drawings need to be subtracted out of the - normal boundaries of the window when computing where to place - windows (e.g. to set this window so it's centered on top of another, - or to put it to the left or right of the screen.) - - This value should change as little as possible at runtime, to - prevent flicker. - - This value is also ignored when the window is maximized or - fullscreen, and assumed to be 0. - - If never called, this value is assumed to be 0. - </description> - <arg name="left_margin" type="int"/> - <arg name="right_margin" type="int"/> - <arg name="top_margin" type="int"/> - <arg name="bottom_margin" type="int"/> - </request> - <request name="set_title"> <description summary="set surface title"> Set a short title for the surface. @@ -201,6 +172,26 @@ <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 parent surface. There are + no guarantees as to what the window menu contains. + + Your surface must have focus on the seat passed in to pop up the + window menu. + </description> + + <arg name="seat" type="object" interface="wl_seat" summary="the seat to pop the window up on"/> + <arg name="serial" type="uint" summary="serial of the event to pop up the window for"/> + <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 a pointer-driven move of the surface. @@ -244,46 +235,12 @@ <arg name="edges" type="uint" summary="which edge or corner is being dragged"/> </request> - <event name="configure"> - <description summary="suggest resize"> - The configure event asks the client to resize its surface. - - The size is a hint, in the sense that the client is free to - ignore it if it doesn't resize, pick a smaller size (to - satisfy aspect ratio or resize in steps of NxM pixels). - - The client is free to dismiss all but the last configure - event it received. - - The width and height arguments specify the size of the window - in surface local coordinates. - </description> - - <arg name="width" type="int"/> - <arg name="height" type="int"/> - </event> - - <request name="set_output"> - <description summary="set the default output used by this surface"> - Set the default output used by this surface when it is first mapped. - - If this value is NULL (default), it's up to the compositor to choose - which display will be used to map this surface. - - When fullscreen or maximized state are set on this surface, and it - wasn't mapped yet, the output set with this method will be used. - Otherwise, the output where the surface is currently mapped will be - used. - </description> - <arg name="output" type="object" interface="wl_output" allow-null="true"/> - </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 - request_change_state event to ensure that both the client and the - compositor setting the state can be synchronized. + 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. @@ -300,89 +257,101 @@ 0x1000 - 0x1FFF: GNOME </description> <entry name="maximized" value="1" summary="the surface is maximized"> - A non-zero value indicates the surface is maximized. Otherwise, - the surface is unmaximized. + The surface is maximized. The window geometry specified in the configure + event must be obeyed by the client. </entry> <entry name="fullscreen" value="2" summary="the surface is fullscreen"> - A non-zero value indicates the surface is fullscreen. Otherwise, - the surface is not fullscreen. + The surface is fullscreen. The window geometry specified in the configure + event must be obeyed by the client. + </entry> + <entry name="resizing" value="3"> + 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. + </entry> + <entry name="activated" value="4"> + 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. </entry> </enum> - <request name="request_change_state"> - <description summary="client requests to change a surface's state"> - This asks the compositor to change the state. If the compositor wants - to change the state, it will send a change_state event with the same - state_type, value, and serial, and the event flow continues as if it - it was initiated by the compositor. + <event name="configure"> + <description summary="suggest a surface change"> + The configure event asks the client to resize its surface. - If the compositor does not want to change the state, it will send a - change_state to the client with the old value of the state. - </description> - <arg name="state_type" type="uint" summary="the state to set"/> - <arg name="value" type="uint" summary="the value to change the state to"/> - <arg name="serial" type="uint" summary="an event serial"> - This serial is so the client can know which change_state event corresponds - to which request_change_state request it sent out. - </arg> - </request> + The width and height arguments specify a hint to the window + about how its surface should be resized in window geometry + coordinates. The states listed in the event specify how the + width/height arguments should be interpreted. + + A client should arrange a new surface, and then send a + ack_configure request with the serial sent in this configure + event before attaching a new surface. - <event name="change_state"> - <description summary="compositor wants to change a surface's state"> - This event tells the client to change a surface's state. The client - should respond with an ack_change_state request to the compositor to - guarantee that the compositor knows that the client has seen it. + 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="state_type" type="uint" summary="the state to set"/> - <arg name="value" type="uint" summary="the value to change the state to"/> - <arg name="serial" type="uint" summary="a serial for the compositor's own tracking"/> + <arg name="width" type="int"/> + <arg name="height" type="int"/> + <arg name="states" type="array"/> + <arg name="serial" type="uint"/> </event> - <request name="ack_change_state"> - <description summary="ack a change_state event"> - When a change_state event is received, a client should then ack it - using the ack_change_state request to ensure that the compositor + <request name="ack_configure"> + <description summary="ack a configure event"> + When a configure event is received, a client should then ack it + using the ack_configure request to ensure that the compositor knows the client has seen the event. By this point, the state is confirmed, and the next attach should - contain the buffer drawn for the new state value. - - The values here need to be the same as the values in the cooresponding - change_state event. + contain the buffer drawn for the configure event you are acking. </description> - <arg name="state_type" type="uint" summary="the state to set"/> - <arg name="value" type="uint" summary="the value to change the state to"/> - <arg name="serial" type="uint" summary="a serial to pass to change_state"/> + <arg name="serial" type="uint" summary="a serial to configure for"/> </request> - <request name="set_minimized"> - <description summary="minimize the surface"> - Minimize the surface. + <request name="set_window_geometry"> + <description summary="set the new window geometry"> + The window geometry of a window 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 default value is the full bounds of the surface, including any + subsurfaces. Once the window geometry of the surface is set once, + 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 responding to a configure event, the window geometry in here + must respect the sizing negotiations specified by the states in + the configure event. </description> + <arg name="x" type="int"/> + <arg name="y" type="int"/> + <arg name="width" type="int"/> + <arg name="height" type="int"/> </request> - <event name="activated"> - <description summary="surface was activated"> - The activated_set event is sent when this surface has been - activated, which means that the surface has user attention. - Window decorations should be updated accordingly. You should - not use this event for anything but the style of decorations - you display, use wl_keyboard.enter and wl_keyboard.leave for - determining keyboard focus. - </description> - </event> + <request name="set_maximized" /> + <request name="unset_maximized" /> + + <request name="set_fullscreen"> + <description summary="set the window as fullscreen on a monitor"> + Make the surface fullscreen. - <event name="deactivated"> - <description summary="surface was deactivated"> - The deactivate event is sent when this surface has been - deactivated, which means that the surface lost user attention. - Window decorations should be updated accordingly. You should - not use this event for anything but the style of decorations - you display, use wl_keyboard.enter and wl_keyboard.leave for - determining keyboard focus. + 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. </description> - </event> + <arg name="output" type="object" interface="wl_output" allow-null="true"/> + </request> + <request name="unset_fullscreen" /> + + <request name="set_minimized" /> <event name="close"> <description summary="surface wants to be closed"> diff --git a/src/client/qwaylandxdgsurface.cpp b/src/client/qwaylandxdgsurface.cpp index 318ff86d..0f005b39 100644 --- a/src/client/qwaylandxdgsurface.cpp +++ b/src/client/qwaylandxdgsurface.cpp @@ -94,36 +94,35 @@ void QWaylandXdgSurface::move(QWaylandInputDevice *inputDevice) void QWaylandXdgSurface::setMaximized() { if (!m_maximized) - request_change_state(XDG_SURFACE_STATE_MAXIMIZED, true, 0); + set_maximized(); } void QWaylandXdgSurface::setFullscreen() { if (!m_fullscreen) - request_change_state(XDG_SURFACE_STATE_FULLSCREEN, true, 0); + set_fullscreen(Q_NULLPTR); } void QWaylandXdgSurface::setNormal() { if (m_fullscreen || m_maximized || m_minimized) { if (m_maximized) { - request_change_state(XDG_SURFACE_STATE_MAXIMIZED, false, 0); + unset_maximized(); } if (m_fullscreen) { - request_change_state(XDG_SURFACE_STATE_FULLSCREEN, false, 0); + unset_fullscreen(); } m_fullscreen = m_maximized = m_minimized = false; setTopLevel(); - QMargins m = m_window->frameMargins(); - m_window->configure(0, m_size.width() + m.left() + m.right(), m_size.height() + m.top() + m.bottom()); + m_margin = m_window->frameMargins(); + m_window->configure(0, m_size.width() + m_margin.left() + m_margin.right(), m_size.height() + m_margin.top() + m_margin.bottom()); } } void QWaylandXdgSurface::setMinimized() { m_minimized = true; - m_size = m_window->window()->geometry().size(); set_minimized(); } @@ -147,13 +146,7 @@ void QWaylandXdgSurface::updateTransientParent(QWindow *parent) transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top()); } - uint32_t flags = 0; - Qt::WindowFlags wf = m_window->window()->flags(); - if (wf.testFlag(Qt::ToolTip) - || wf.testFlag(Qt::WindowTransparentForInput)) - flags |= XDG_SURFACE_SET_TRANSIENT_FOR; - - set_transient_for(parent_wayland_window->object()); + set_parent(parent_wayland_window->object()); } void QWaylandXdgSurface::setTitle(const QString & title) @@ -196,44 +189,58 @@ void QWaylandXdgSurface::sendProperty(const QString &name, const QVariant &value m_extendedWindow->updateGenericProperty(name, value); } -void QWaylandXdgSurface::xdg_surface_configure(int32_t width, int32_t height) -{ - m_window->configure(0 , width, height); -} - -void QWaylandXdgSurface::xdg_surface_change_state(uint32_t state, - uint32_t value, - uint32_t serial) -{ - - if (state == XDG_SURFACE_STATE_MAXIMIZED - || state == XDG_SURFACE_STATE_FULLSCREEN) { - if (value) { - m_size = m_window->window()->geometry().size(); - } else { - QMargins m = m_window->frameMargins(); - m_window->configure(0, m_size.width() + m.left() + m.right(), m_size.height() + m.top() + m.bottom()); +void QWaylandXdgSurface::xdg_surface_configure(int32_t width, int32_t height, struct wl_array *states,uint32_t serial) +{ + uint32_t *state = 0; + bool about_to_maximize = false; + bool about_to_fullscreen = false; + + for (state = (uint32_t*) (states)->data; + (const char *) state < ((const char *) (states)->data + (states)->size); + (state)++) + { + switch (*state) { + case XDG_SURFACE_STATE_MAXIMIZED: + about_to_maximize = true; + break; + case XDG_SURFACE_STATE_FULLSCREEN: + about_to_fullscreen = true; + break; + case XDG_SURFACE_STATE_RESIZING: + m_size = QSize(width,height); + break; + case XDG_SURFACE_STATE_ACTIVATED: + if (!m_fullscreen && about_to_fullscreen) { + m_fullscreen = true; + m_size = m_window->window()->geometry().size(); + m_window->window()->showFullScreen(); + } else if (m_fullscreen && !about_to_fullscreen) { + m_fullscreen = false; + m_window->window()->showNormal(); + } else if (!m_maximized && about_to_maximize) { + m_maximized = true; + m_size = m_window->window()->geometry().size(); + m_window->window()->showMaximized(); + } else if (m_maximized && !about_to_maximize) { + m_maximized = false; + m_window->window()->showNormal(); + } + + if (width == 0 && height == 0) { + width = m_size.width(); + height = m_size.height(); + } + + if (width > 0 && height > 0) { + m_margin = m_window->frameMargins(); + m_window->configure(0, width + m_margin.left() + m_margin.right(), height + m_margin.top() + m_margin.bottom()); + } + break; + default: + break; } } - - switch (state) { - case XDG_SURFACE_STATE_MAXIMIZED: - m_maximized = value; - break; - case XDG_SURFACE_STATE_FULLSCREEN: - m_fullscreen = value; - break; - } - - xdg_surface_ack_change_state(object(), state, value, serial); -} - -void QWaylandXdgSurface::xdg_surface_activated() -{ -} - -void QWaylandXdgSurface::xdg_surface_deactivated() -{ + xdg_surface_ack_configure(object(), serial); } void QWaylandXdgSurface::xdg_surface_close() diff --git a/src/client/qwaylandxdgsurface_p.h b/src/client/qwaylandxdgsurface_p.h index 635c9496..deae3a1f 100644 --- a/src/client/qwaylandxdgsurface_p.h +++ b/src/client/qwaylandxdgsurface_p.h @@ -43,6 +43,7 @@ #define QWAYLANDXDGSURFACE_H #include <QtCore/QSize> +#include <QtCore/QMargins> #include <wayland-client.h> @@ -99,15 +100,13 @@ private: bool m_minimized; bool m_fullscreen; QSize m_size; + QMargins m_margin; QWaylandExtendedSurface *m_extendedWindow; void xdg_surface_configure(int32_t width, - int32_t height) Q_DECL_OVERRIDE; - void xdg_surface_change_state(uint32_t state, - uint32_t value, - uint32_t serial) Q_DECL_OVERRIDE; - void xdg_surface_activated() Q_DECL_OVERRIDE; - void xdg_surface_deactivated() Q_DECL_OVERRIDE; + int32_t height, + struct wl_array *states, + uint32_t serial) Q_DECL_OVERRIDE; void xdg_surface_close() Q_DECL_OVERRIDE; friend class QWaylandWindow; |