mirror of
https://github.com/swaywm/sway.git
synced 2024-11-26 18:01:29 +00:00
Merge branch 'wlroots' into split-containers
This commit is contained in:
commit
a89096278b
|
@ -24,6 +24,7 @@ struct sway_output {
|
|||
struct wl_listener destroy;
|
||||
struct wl_listener mode;
|
||||
struct wl_listener transform;
|
||||
struct wl_listener scale;
|
||||
|
||||
struct wl_listener damage_destroy;
|
||||
struct wl_listener damage_frame;
|
||||
|
|
|
@ -70,9 +70,10 @@ struct sway_container {
|
|||
enum sway_container_layout prev_layout;
|
||||
enum sway_container_layout workspace_layout;
|
||||
|
||||
// TODO convert to layout coordinates
|
||||
// For C_ROOT, this has no meaning
|
||||
// For C_OUTPUT, this is the output position in layout coordinates
|
||||
// For other types, this is the position in output-local coordinates
|
||||
double x, y;
|
||||
|
||||
// does not include borders or gaps.
|
||||
double width, height;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ struct sway_root {
|
|||
|
||||
struct wl_listener output_layout_change;
|
||||
|
||||
struct wl_list unmanaged_views; // sway_view::unmanaged_view_link
|
||||
struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link
|
||||
|
||||
struct {
|
||||
struct wl_signal new_container;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <wlr/types/wlr_surface.h>
|
||||
#include <wlr/types/wlr_xdg_shell_v6.h>
|
||||
#include <wlr/xwayland.h>
|
||||
#include "sway/input/input-manager.h"
|
||||
#include "sway/input/seat.h"
|
||||
|
||||
struct sway_container;
|
||||
struct sway_view;
|
||||
|
@ -37,6 +39,13 @@ struct sway_xwayland_surface {
|
|||
int pending_width, pending_height;
|
||||
};
|
||||
|
||||
struct sway_xwayland_unmanaged {
|
||||
struct wlr_xwayland_surface *wlr_xwayland_surface;
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_listener destroy;
|
||||
};
|
||||
|
||||
struct sway_wl_shell_surface {
|
||||
struct sway_view *view;
|
||||
|
||||
|
@ -64,10 +73,21 @@ enum sway_view_prop {
|
|||
VIEW_PROP_INSTANCE,
|
||||
};
|
||||
|
||||
struct sway_view_impl {
|
||||
const char *(*get_prop)(struct sway_view *view,
|
||||
enum sway_view_prop prop);
|
||||
void (*configure)(struct sway_view *view, double ox, double oy, int width,
|
||||
int height);
|
||||
void (*set_activated)(struct sway_view *view, bool activated);
|
||||
void (*close)(struct sway_view *view);
|
||||
};
|
||||
|
||||
struct sway_view {
|
||||
enum sway_view_type type;
|
||||
struct sway_container *swayc;
|
||||
struct wlr_surface *surface;
|
||||
const struct sway_view_impl *impl;
|
||||
|
||||
struct sway_container *swayc; // NULL for unmanaged views
|
||||
struct wlr_surface *surface; // NULL for unmapped views
|
||||
int width, height;
|
||||
|
||||
union {
|
||||
|
@ -82,21 +102,15 @@ struct sway_view {
|
|||
struct sway_wl_shell_surface *sway_wl_shell_surface;
|
||||
};
|
||||
|
||||
struct {
|
||||
const char *(*get_prop)(struct sway_view *view,
|
||||
enum sway_view_prop prop);
|
||||
void (*set_size)(struct sway_view *view,
|
||||
int width, int height);
|
||||
void (*set_position)(struct sway_view *view,
|
||||
double ox, double oy);
|
||||
void (*set_activated)(struct sway_view *view, bool activated);
|
||||
void (*close)(struct sway_view *view);
|
||||
} iface;
|
||||
|
||||
// only used for unmanaged views (shell specific)
|
||||
struct wl_list unmanaged_view_link; // sway_root::unmanaged views
|
||||
struct wl_list unmanaged_view_link; // sway_root::unmanaged_views
|
||||
};
|
||||
|
||||
struct sway_view *view_create(enum sway_view_type type,
|
||||
const struct sway_view_impl *impl);
|
||||
|
||||
void view_destroy(struct sway_view *view);
|
||||
|
||||
const char *view_get_title(struct sway_view *view);
|
||||
|
||||
const char *view_get_app_id(struct sway_view *view);
|
||||
|
@ -105,18 +119,25 @@ const char *view_get_class(struct sway_view *view);
|
|||
|
||||
const char *view_get_instance(struct sway_view *view);
|
||||
|
||||
void view_set_size(struct sway_view *view, int width, int height);
|
||||
|
||||
void view_set_position(struct sway_view *view, double ox, double oy);
|
||||
void view_configure(struct sway_view *view, double ox, double oy, int width,
|
||||
int height);
|
||||
|
||||
void view_set_activated(struct sway_view *view, bool activated);
|
||||
|
||||
void view_close(struct sway_view *view);
|
||||
|
||||
void view_update_outputs(struct sway_view *view, const struct wlr_box *before);
|
||||
|
||||
void view_damage_whole(struct sway_view *view);
|
||||
|
||||
void view_damage_from(struct sway_view *view);
|
||||
|
||||
// view implementation
|
||||
|
||||
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface);
|
||||
|
||||
void view_unmap(struct sway_view *view);
|
||||
|
||||
void view_update_position(struct sway_view *view, double ox, double oy);
|
||||
|
||||
void view_update_size(struct sway_view *view, int width, int height);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
<protocol name="desktop">
|
||||
|
||||
<interface name="desktop_shell" version="3">
|
||||
<description summary="create desktop widgets and helpers">
|
||||
Traditional user interfaces can rely on this interface to define the
|
||||
foundations of typical desktops. Currently it's possible to set up
|
||||
background, panels and locking surfaces.
|
||||
</description>
|
||||
|
||||
<request name="set_background">
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="set_panel">
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="set_lock_surface">
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="unlock"/>
|
||||
|
||||
<request name="set_grab_surface">
|
||||
<description summary="set grab surface">
|
||||
The surface set by this request will receive a fake
|
||||
pointer.enter event during grabs at position 0, 0 and is
|
||||
expected to set an appropriate cursor image as described by
|
||||
the grab_cursor event sent just before the enter event.
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<!-- We'll fold most of wl_shell into this interface and then
|
||||
they'll share the configure event. -->
|
||||
<event name="configure">
|
||||
<arg name="edges" type="uint"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
</event>
|
||||
|
||||
<event name="prepare_lock_surface">
|
||||
<description summary="tell the client to create, set the lock surface">
|
||||
Tell the client we want it to create and set the lock surface, which is
|
||||
a GUI asking the user to unlock the screen. The lock surface is
|
||||
announced with 'set_lock_surface'. Whether or not the client actually
|
||||
implements locking, it MUST send 'unlock' request to let the normal
|
||||
desktop resume.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="grab_cursor">
|
||||
<description summary="tell client what cursor to show during a grab">
|
||||
This event will be sent immediately before a fake enter event on the
|
||||
grab surface.
|
||||
</description>
|
||||
<arg name="cursor" type="uint"/>
|
||||
</event>
|
||||
|
||||
<enum name="cursor">
|
||||
<entry name="none" value="0"/>
|
||||
|
||||
<entry name="resize_top" value="1"/>
|
||||
<entry name="resize_bottom" value="2"/>
|
||||
|
||||
<entry name="arrow" value="3"/>
|
||||
|
||||
<entry name="resize_left" value="4"/>
|
||||
<entry name="resize_top_left" value="5"/>
|
||||
<entry name="resize_bottom_left" value="6"/>
|
||||
|
||||
<entry name="move" value="7"/>
|
||||
|
||||
<entry name="resize_right" value="8"/>
|
||||
<entry name="resize_top_right" value="9"/>
|
||||
<entry name="resize_bottom_right" value="10"/>
|
||||
|
||||
<entry name="busy" value="11"/>
|
||||
</enum>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<request name="desktop_ready" since="2">
|
||||
<description summary="desktop is ready to be shown">
|
||||
Tell the server, that enough desktop elements have been drawn
|
||||
to make the desktop look ready for use. During start-up, the
|
||||
server can wait for this request with a black screen before
|
||||
starting to fade in the desktop, for instance. If the client
|
||||
parts of a desktop take a long time to initialize, we avoid
|
||||
showing temporary garbage.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<!-- Version 3 additions -->
|
||||
|
||||
<enum name="panel_position">
|
||||
<entry name="top" value="0"/>
|
||||
<entry name="bottom" value="1"/>
|
||||
<entry name="left" value="2"/>
|
||||
<entry name="right" value="3"/>
|
||||
</enum>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_argument" value="0"
|
||||
summary="an invalid argument was provided in a request"/>
|
||||
</enum>
|
||||
|
||||
<request name="set_panel_position" since="3">
|
||||
<description summary="set panel position">
|
||||
Tell the shell which side of the screen the panel is
|
||||
located. This is so that new windows do not overlap the panel
|
||||
and maximized windows maximize properly.
|
||||
</description>
|
||||
<arg name="position" type="uint"/>
|
||||
</request>
|
||||
|
||||
</interface>
|
||||
|
||||
<interface name="screensaver" version="1">
|
||||
<description summary="interface for implementing screensavers">
|
||||
Only one client can bind this interface at a time.
|
||||
</description>
|
||||
|
||||
<request name="set_surface">
|
||||
<description summary="set the surface type as a screensaver">
|
||||
A screensaver surface is normally hidden, and only visible after an
|
||||
idle timeout.
|
||||
</description>
|
||||
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</request>
|
||||
|
||||
</interface>
|
||||
</protocol>
|
|
@ -1,57 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="gamma_control">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2015 Giulio camuffo
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="gamma_control_manager" version="1">
|
||||
<request name="destroy" type="destructor"/>
|
||||
|
||||
<request name="get_gamma_control">
|
||||
<arg name="id" type="new_id" interface="gamma_control"/>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="gamma_control" version="1">
|
||||
<enum name="error">
|
||||
<entry name="invalid_gamma" value="0"/>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor"/>
|
||||
|
||||
<request name="set_gamma">
|
||||
<arg name="red" type="array"/>
|
||||
<arg name="green" type="array"/>
|
||||
<arg name="blue" type="array"/>
|
||||
</request>
|
||||
|
||||
<request name="reset_gamma"/>
|
||||
|
||||
<event name="gamma_size">
|
||||
<arg name="size" type="uint"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
|
@ -1,94 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="server_decoration">
|
||||
<copyright><![CDATA[
|
||||
Copyright (C) 2015 Martin Gräßlin
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]></copyright>
|
||||
<interface name="org_kde_kwin_server_decoration_manager" version="1">
|
||||
<description summary="Server side window decoration manager">
|
||||
This interface allows to coordinate whether the server should create
|
||||
a server-side window decoration around a wl_surface representing a
|
||||
shell surface (wl_shell_surface or similar). By announcing support
|
||||
for this interface the server indicates that it supports server
|
||||
side decorations.
|
||||
</description>
|
||||
<request name="create">
|
||||
<description summary="Create a server-side decoration object for a given surface">
|
||||
When a client creates a server-side decoration object it indicates
|
||||
that it supports the protocol. The client is supposed to tell the
|
||||
server whether it wants server-side decorations or will provide
|
||||
client-side decorations.
|
||||
|
||||
If the client does not create a server-side decoration object for
|
||||
a surface the server interprets this as lack of support for this
|
||||
protocol and considers it as client-side decorated. Nevertheless a
|
||||
client-side decorated surface should use this protocol to indicate
|
||||
to the server that it does not want a server-side deco.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="org_kde_kwin_server_decoration"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
<enum name="mode">
|
||||
<description summary="Possible values to use in request_mode and the event mode."/>
|
||||
<entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/>
|
||||
<entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/>
|
||||
<entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/>
|
||||
</enum>
|
||||
<event name="default_mode">
|
||||
<description summary="The default mode used on the server">
|
||||
This event is emitted directly after binding the interface. It contains
|
||||
the default mode for the decoration. When a new server decoration object
|
||||
is created this new object will be in the default mode until the first
|
||||
request_mode is requested.
|
||||
|
||||
The server may change the default mode at any time.
|
||||
</description>
|
||||
<arg name="mode" type="uint" summary="The default decoration mode applied to newly created server decorations."/>
|
||||
</event>
|
||||
</interface>
|
||||
<interface name="org_kde_kwin_server_decoration" version="1">
|
||||
<request name="release" type="destructor">
|
||||
<description summary="release the server decoration object"/>
|
||||
</request>
|
||||
<enum name="mode">
|
||||
<description summary="Possible values to use in request_mode and the event mode."/>
|
||||
<entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/>
|
||||
<entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/>
|
||||
<entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/>
|
||||
</enum>
|
||||
<request name="request_mode">
|
||||
<description summary="The decoration mode the surface wants to use."/>
|
||||
<arg name="mode" type="uint" summary="The mode this surface wants to use."/>
|
||||
</request>
|
||||
<event name="mode">
|
||||
<description summary="The new decoration mode applied by the server">
|
||||
This event is emitted directly after the decoration is created and
|
||||
represents the base decoration policy by the server. E.g. a server
|
||||
which wants all surfaces to be client-side decorated will send Client,
|
||||
a server which wants server-side decoration will send Server.
|
||||
|
||||
The client can request a different mode through the decoration request.
|
||||
The server will acknowledge this by another event with the same mode. So
|
||||
even if a server prefers server-side decoration it's possible to force a
|
||||
client-side decoration.
|
||||
|
||||
The server may emit this event at any time. In this case the client can
|
||||
again request a different mode. It's the responsibility of the server to
|
||||
prevent a feedback loop.
|
||||
</description>
|
||||
<arg name="mode" type="uint" summary="The decoration mode applied to the surface by the server."/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
|
@ -1,18 +0,0 @@
|
|||
<protocol name="lock">
|
||||
|
||||
<interface name="lock" version="1">
|
||||
<description summary="create lock screen UIs">
|
||||
The Weston desktop-shell protocol's locking functionality depends more
|
||||
on the behavior of the compositor than of a screen locking client, so
|
||||
another protocol is necessary.
|
||||
</description>
|
||||
|
||||
<request name="set_lock_surface">
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="unlock"/>
|
||||
|
||||
</interface>
|
||||
</protocol>
|
|
@ -1,430 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="xdg_shell">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2008-2013 Kristian Høgsberg
|
||||
Copyright © 2013 Rafael Antognolli
|
||||
Copyright © 2013 Jasper St. Pierre
|
||||
Copyright © 2010-2013 Intel Corporation
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="xdg_shell" version="1">
|
||||
<description summary="create desktop-style surfaces">
|
||||
This interface is implemented by servers that provide
|
||||
desktop-style user interfaces.
|
||||
|
||||
It allows clients to associate a xdg_surface with
|
||||
a basic surface.
|
||||
</description>
|
||||
|
||||
<enum name="version">
|
||||
<description summary="latest protocol version">
|
||||
The 'current' member of this enum gives the version of the
|
||||
protocol. Implementations can compare this to the version
|
||||
they implement using static_assert to ensure the protocol and
|
||||
implementation versions match.
|
||||
</description>
|
||||
<entry name="current" value="4" summary="Always the latest version"/>
|
||||
</enum>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="role" value="0" summary="given wl_surface has another role"/>
|
||||
</enum>
|
||||
|
||||
<request name="use_unstable_version">
|
||||
<description summary="enable use of this unstable version">
|
||||
Negotiate the unstable version of the interface. This
|
||||
mechanism is in place to ensure client and server agree on the
|
||||
unstable versions of the protocol that they speak or exit
|
||||
cleanly if they don't agree. This request will go away once
|
||||
the xdg-shell protocol is stable.
|
||||
</description>
|
||||
<arg name="version" type="int"/>
|
||||
</request>
|
||||
|
||||
<request name="get_xdg_surface">
|
||||
<description summary="create a shell surface from a surface">
|
||||
Create a shell surface for an existing surface.
|
||||
|
||||
This request gives the surface the role of xdg_surface. If the
|
||||
surface already has another role, it raises a protocol error.
|
||||
|
||||
Only one shell or popup surface can be associated with a given
|
||||
surface.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="xdg_surface"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="get_xdg_popup">
|
||||
<description summary="create a shell surface from a surface">
|
||||
Create a popup surface for an existing surface.
|
||||
|
||||
This request gives the surface the role of xdg_popup. If the
|
||||
surface already has another role, it raises a protocol error.
|
||||
|
||||
Only one shell or popup surface can be associated with a given
|
||||
surface.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="xdg_popup"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="parent" type="object" interface="wl_surface"/>
|
||||
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
|
||||
<arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<arg name="flags" type="uint"/>
|
||||
</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.
|
||||
|
||||
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.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="pass this to the callback"/>
|
||||
</event>
|
||||
|
||||
<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.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the ping event"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="xdg_surface" version="1">
|
||||
|
||||
<description summary="desktop-style metadata interface">
|
||||
An interface that may be implemented by a wl_surface, for
|
||||
implementations that provide a desktop-style user interface.
|
||||
|
||||
It provides requests to treat surfaces like windows, allowing to set
|
||||
properties like maximized, fullscreen, minimized, and to move and resize
|
||||
them, and associate metadata like title and app id.
|
||||
|
||||
On the server side the object is automatically destroyed when
|
||||
the related wl_surface is destroyed. On client side,
|
||||
xdg_surface.destroy() must be called before destroying
|
||||
the wl_surface object.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="remove xdg_surface interface">
|
||||
The xdg_surface interface is removed from the wl_surface object
|
||||
that was turned into a xdg_surface with
|
||||
xdg_shell.get_xdg_surface request. The xdg_surface properties,
|
||||
like maximized and fullscreen, are lost. The wl_surface loses
|
||||
its role as a xdg_surface. The wl_surface is unmapped.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_parent">
|
||||
<description summary="surface is a 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.
|
||||
</description>
|
||||
<arg name="parent" type="object" interface="wl_surface" 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 surface class">
|
||||
Set an id for the surface.
|
||||
|
||||
The app id identifies the general class of applications to which
|
||||
the surface belongs.
|
||||
|
||||
It should be the ID that appears in the new desktop entry
|
||||
specification, the interface name.
|
||||
</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 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.
|
||||
|
||||
This request must be used in response to a button press event.
|
||||
The server may ignore move requests depending on the state of
|
||||
the surface (e.g. fullscreen or maximized).
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
|
||||
<arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
|
||||
</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. The server may
|
||||
use this information to adapt its behavior, e.g. choose
|
||||
an appropriate cursor image.
|
||||
</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 pointer-driven resizing of the surface.
|
||||
|
||||
This request must be used in response to a button press event.
|
||||
The server may ignore resize requests depending on the state of
|
||||
the surface (e.g. fullscreen or maximized).
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
|
||||
<arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
|
||||
<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.
|
||||
|
||||
Desktop environments may extend this enum by taking up a range of
|
||||
values and documenting the range they chose in this description.
|
||||
They are not required to document the values for the range that they
|
||||
chose. Ideally, any good extensions from a desktop environment should
|
||||
make its way into standardization into this enum.
|
||||
|
||||
The current reserved ranges are:
|
||||
|
||||
0x0000 - 0x0FFF: xdg-shell core values, documented below.
|
||||
0x1000 - 0x1FFF: GNOME
|
||||
</description>
|
||||
<entry name="maximized" value="1">
|
||||
<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">
|
||||
<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">
|
||||
<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">
|
||||
<description summary="the client window is active">
|
||||
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>
|
||||
|
||||
<event name="configure">
|
||||
<description summary="suggest a surface change">
|
||||
The configure event asks the client to resize its surface.
|
||||
|
||||
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.
|
||||
|
||||
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="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="states" type="array"/>
|
||||
<arg name="serial" type="uint"/>
|
||||
</event>
|
||||
|
||||
<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 configure event you are acking.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="a serial to configure for"/>
|
||||
</request>
|
||||
|
||||
<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>
|
||||
|
||||
<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.
|
||||
|
||||
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>
|
||||
<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">
|
||||
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="xdg_popup" version="1">
|
||||
<description summary="desktop-style metadata interface">
|
||||
An interface that may be implemented by a wl_surface, for
|
||||
implementations that provide a desktop-style popups/menus. A popup
|
||||
surface is a transient surface with an added pointer grab.
|
||||
|
||||
An existing implicit grab will be changed to owner-events mode,
|
||||
and the popup grab will continue after the implicit grab ends
|
||||
(i.e. releasing the mouse button does not cause the popup to be
|
||||
unmapped).
|
||||
|
||||
The popup grab continues until the window is destroyed or a mouse
|
||||
button is pressed in any other clients window. A click in any of
|
||||
the clients surfaces is reported as normal, however, clicks in
|
||||
other clients surfaces will be discarded and trigger the callback.
|
||||
|
||||
The x and y arguments specify the locations of the upper left
|
||||
corner of the surface relative to the upper left corner of the
|
||||
parent surface, in surface local coordinates.
|
||||
|
||||
xdg_popup surfaces are always transient for another surface.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="remove xdg_surface interface">
|
||||
The xdg_surface interface is removed from the wl_surface object
|
||||
that was turned into a xdg_surface with
|
||||
xdg_shell.get_xdg_surface request. The xdg_surface properties,
|
||||
like maximized and fullscreen, are lost. The wl_surface loses
|
||||
its role as a xdg_surface. The wl_surface is unmapped.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="popup_done">
|
||||
<description summary="popup interaction is done">
|
||||
The popup_done event is sent out when a popup grab is broken,
|
||||
that is, when the users clicks a surface that doesn't belong
|
||||
to the client owning the popup surface.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
|
||||
</event>
|
||||
|
||||
</interface>
|
||||
</protocol>
|
|
@ -39,6 +39,32 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a surface at (lx, ly) intersects an output. If `box` is not
|
||||
* NULL, it populates it with the surface box in the output, in output-local
|
||||
* coordinates.
|
||||
*/
|
||||
static bool surface_intersect_output(struct wlr_surface *surface,
|
||||
struct wlr_output_layout *output_layout, struct wlr_output *wlr_output,
|
||||
double lx, double ly, float rotation, struct wlr_box *box) {
|
||||
double ox = lx, oy = ly;
|
||||
wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy);
|
||||
|
||||
if (box != NULL) {
|
||||
box->x = ox * wlr_output->scale;
|
||||
box->y = oy * wlr_output->scale;
|
||||
box->width = surface->current->width * wlr_output->scale;
|
||||
box->height = surface->current->height * wlr_output->scale;
|
||||
}
|
||||
|
||||
struct wlr_box layout_box = {
|
||||
.x = lx, .y = ly,
|
||||
.width = surface->current->width, .height = surface->current->height,
|
||||
};
|
||||
wlr_box_rotated_bounds(&layout_box, rotation, &layout_box);
|
||||
return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box);
|
||||
}
|
||||
|
||||
static void render_surface(struct wlr_surface *surface,
|
||||
struct wlr_output *wlr_output, struct timespec *when,
|
||||
double lx, double ly, float rotation) {
|
||||
|
@ -48,29 +74,21 @@ static void render_surface(struct wlr_surface *surface,
|
|||
if (!wlr_surface_has_buffer(surface)) {
|
||||
return;
|
||||
}
|
||||
struct wlr_output_layout *layout = root_container.sway_root->output_layout;
|
||||
int width = surface->current->width;
|
||||
int height = surface->current->height;
|
||||
int render_width = width * wlr_output->scale;
|
||||
int render_height = height * wlr_output->scale;
|
||||
int owidth, oheight;
|
||||
wlr_output_effective_resolution(wlr_output, &owidth, &oheight);
|
||||
|
||||
// FIXME: view coords are inconsistently assumed to be in output or layout coords
|
||||
struct wlr_box layout_box = {
|
||||
.x = lx + wlr_output->lx, .y = ly + wlr_output->ly,
|
||||
.width = render_width, .height = render_height,
|
||||
};
|
||||
if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) {
|
||||
struct wlr_box render_box = {
|
||||
.x = lx, .y = ly,
|
||||
.width = render_width, .height = render_height
|
||||
};
|
||||
struct wlr_output_layout *layout = root_container.sway_root->output_layout;
|
||||
|
||||
struct wlr_box box;
|
||||
bool intersects = surface_intersect_output(surface, layout, wlr_output,
|
||||
lx, ly, rotation, &box);
|
||||
if (intersects) {
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, &render_box, surface->current->transform,
|
||||
0, wlr_output->transform_matrix);
|
||||
wlr_render_texture_with_matrix(renderer, surface->texture, matrix,
|
||||
1.0f); // TODO: configurable alpha
|
||||
enum wl_output_transform transform =
|
||||
wlr_output_transform_invert(surface->current->transform);
|
||||
wlr_matrix_project_box(matrix, &box, transform, rotation,
|
||||
wlr_output->transform_matrix);
|
||||
|
||||
// TODO: configurable alpha
|
||||
wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 1.0f);
|
||||
|
||||
wlr_surface_send_frame_done(surface, when);
|
||||
}
|
||||
|
@ -80,9 +98,8 @@ static void render_surface(struct wlr_surface *surface,
|
|||
struct wlr_surface_state *state = subsurface->surface->current;
|
||||
double sx = state->subsurface_position.x;
|
||||
double sy = state->subsurface_position.y;
|
||||
double sw = state->buffer_width / state->scale;
|
||||
double sh = state->buffer_height / state->scale;
|
||||
rotate_child_position(&sx, &sy, sw, sh, width, height, rotation);
|
||||
rotate_child_position(&sx, &sy, state->width, state->height,
|
||||
surface->current->width, surface->current->height, rotation);
|
||||
|
||||
render_surface(subsurface->surface, wlr_output, when,
|
||||
lx + sx, ly + sy, rotation);
|
||||
|
@ -243,15 +260,15 @@ static void render_output(struct sway_output *output, struct timespec *when,
|
|||
container_descendants(workspace, C_VIEW, render_view, &rdata);
|
||||
|
||||
// render unmanaged views on top
|
||||
struct sway_view *view;
|
||||
wl_list_for_each(view, &root_container.sway_root->unmanaged_views,
|
||||
unmanaged_view_link) {
|
||||
if (view->type != SWAY_XWAYLAND_VIEW) {
|
||||
struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged;
|
||||
struct sway_xwayland_unmanaged *sway_surface;
|
||||
wl_list_for_each(sway_surface, unmanaged, link) {
|
||||
struct wlr_xwayland_surface *xsurface =
|
||||
sway_surface->wlr_xwayland_surface;
|
||||
if (xsurface->surface == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
|
||||
const struct wlr_box view_box = {
|
||||
.x = xsurface->x,
|
||||
.y = xsurface->y,
|
||||
|
@ -263,7 +280,7 @@ static void render_output(struct sway_output *output, struct timespec *when,
|
|||
continue;
|
||||
}
|
||||
|
||||
render_surface(view->surface, wlr_output, &output->last_frame,
|
||||
render_surface(xsurface->surface, wlr_output, &output->last_frame,
|
||||
view_box.x - output_box->x, view_box.y - output_box->y, 0);
|
||||
}
|
||||
|
||||
|
@ -341,6 +358,12 @@ static void handle_transform(struct wl_listener *listener, void *data) {
|
|||
arrange_windows(output->swayc, -1, -1);
|
||||
}
|
||||
|
||||
static void handle_scale(struct wl_listener *listener, void *data) {
|
||||
struct sway_output *output = wl_container_of(listener, output, scale);
|
||||
arrange_layers(output);
|
||||
arrange_windows(output->swayc, -1, -1);
|
||||
}
|
||||
|
||||
void handle_new_output(struct wl_listener *listener, void *data) {
|
||||
struct sway_server *server = wl_container_of(listener, server, new_output);
|
||||
struct wlr_output *wlr_output = data;
|
||||
|
@ -381,6 +404,8 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
|||
output->mode.notify = handle_mode;
|
||||
wl_signal_add(&wlr_output->events.transform, &output->transform);
|
||||
output->transform.notify = handle_transform;
|
||||
wl_signal_add(&wlr_output->events.scale, &output->scale);
|
||||
output->scale.notify = handle_scale;
|
||||
|
||||
wl_signal_add(&output->damage->events.frame, &output->damage_frame);
|
||||
output->damage_frame.notify = damage_handle_frame;
|
||||
|
|
|
@ -30,28 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
|
|||
}
|
||||
}
|
||||
|
||||
static void set_size(struct sway_view *view, int width, int height) {
|
||||
static void configure(struct sway_view *view, double ox, double oy, int width,
|
||||
int height) {
|
||||
if (!assert_wl_shell(view)) {
|
||||
return;
|
||||
}
|
||||
view_update_position(view, ox, oy);
|
||||
view->sway_wl_shell_surface->pending_width = width;
|
||||
view->sway_wl_shell_surface->pending_height = height;
|
||||
wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height);
|
||||
}
|
||||
|
||||
static void set_position(struct sway_view *view, double ox, double oy) {
|
||||
if (!assert_wl_shell(view)) {
|
||||
return;
|
||||
}
|
||||
view->swayc->x = ox;
|
||||
view->swayc->y = oy;
|
||||
}
|
||||
|
||||
static void set_activated(struct sway_view *view, bool activated) {
|
||||
// no way to activate wl_shell
|
||||
}
|
||||
|
||||
static void close(struct sway_view *view) {
|
||||
static void _close(struct sway_view *view) {
|
||||
if (!assert_wl_shell(view)) {
|
||||
return;
|
||||
}
|
||||
|
@ -59,14 +49,20 @@ static void close(struct sway_view *view) {
|
|||
wl_client_destroy(view->wlr_wl_shell_surface->client);
|
||||
}
|
||||
|
||||
static const struct sway_view_impl view_impl = {
|
||||
.get_prop = get_prop,
|
||||
.configure = configure,
|
||||
.close = _close,
|
||||
};
|
||||
|
||||
static void handle_commit(struct wl_listener *listener, void *data) {
|
||||
struct sway_wl_shell_surface *sway_surface =
|
||||
wl_container_of(listener, sway_surface, commit);
|
||||
struct sway_view *view = sway_surface->view;
|
||||
// NOTE: We intentionally discard the view's desired width here
|
||||
// TODO: Let floating views do whatever
|
||||
view->width = sway_surface->pending_width;
|
||||
view->height = sway_surface->pending_height;
|
||||
view_update_size(view, sway_surface->pending_width,
|
||||
sway_surface->pending_height);
|
||||
view_damage_from(view);
|
||||
}
|
||||
|
||||
|
@ -75,15 +71,13 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, sway_surface, destroy);
|
||||
wl_list_remove(&sway_surface->commit.link);
|
||||
wl_list_remove(&sway_surface->destroy.link);
|
||||
struct sway_container *parent = container_view_destroy(sway_surface->view->swayc);
|
||||
free(sway_surface->view);
|
||||
view_destroy(sway_surface->view);
|
||||
free(sway_surface);
|
||||
arrange_windows(parent, -1, -1);
|
||||
}
|
||||
|
||||
void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
|
||||
struct sway_server *server = wl_container_of(
|
||||
listener, server, wl_shell_surface);
|
||||
struct sway_server *server = wl_container_of(listener, server,
|
||||
wl_shell_surface);
|
||||
struct wlr_wl_shell_surface *shell_surface = data;
|
||||
|
||||
if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) {
|
||||
|
@ -103,20 +97,13 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
struct sway_view *sway_view = calloc(1, sizeof(struct sway_view));
|
||||
if (!sway_assert(sway_view, "Failed to allocate view!")) {
|
||||
struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW, &view_impl);
|
||||
if (!sway_assert(view, "Failed to allocate view")) {
|
||||
return;
|
||||
}
|
||||
sway_view->type = SWAY_WL_SHELL_VIEW;
|
||||
sway_view->iface.get_prop = get_prop;
|
||||
sway_view->iface.set_size = set_size;
|
||||
sway_view->iface.set_position = set_position;
|
||||
sway_view->iface.set_activated = set_activated;
|
||||
sway_view->iface.close = close;
|
||||
sway_view->wlr_wl_shell_surface = shell_surface;
|
||||
sway_view->sway_wl_shell_surface = sway_surface;
|
||||
sway_view->surface = shell_surface->surface;
|
||||
sway_surface->view = sway_view;
|
||||
view->wlr_wl_shell_surface = shell_surface;
|
||||
view->sway_wl_shell_surface = sway_surface;
|
||||
sway_surface->view = view;
|
||||
|
||||
// TODO:
|
||||
// - Wire up listeners
|
||||
|
@ -132,11 +119,5 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
|
|||
sway_surface->destroy.notify = handle_destroy;
|
||||
wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy);
|
||||
|
||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||
struct sway_container *focus = seat_get_focus_inactive(seat, &root_container);
|
||||
struct sway_container *cont = container_view_create(focus, sway_view);
|
||||
sway_view->swayc = cont;
|
||||
|
||||
arrange_windows(cont->parent, -1, -1);
|
||||
input_manager_set_focus(input_manager, cont);
|
||||
view_map(view, shell_surface->surface);
|
||||
}
|
||||
|
|
|
@ -30,23 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
|
|||
}
|
||||
}
|
||||
|
||||
static void set_size(struct sway_view *view, int width, int height) {
|
||||
static void configure(struct sway_view *view, double ox, double oy, int width,
|
||||
int height) {
|
||||
if (!assert_xdg(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
view_update_position(view, ox, oy);
|
||||
view->sway_xdg_surface_v6->pending_width = width;
|
||||
view->sway_xdg_surface_v6->pending_height = height;
|
||||
wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height);
|
||||
}
|
||||
|
||||
static void set_position(struct sway_view *view, double ox, double oy) {
|
||||
if (!assert_xdg(view)) {
|
||||
return;
|
||||
}
|
||||
view->swayc->x = ox;
|
||||
view->swayc->y = oy;
|
||||
}
|
||||
|
||||
static void set_activated(struct sway_view *view, bool activated) {
|
||||
if (!assert_xdg(view)) {
|
||||
return;
|
||||
|
@ -57,7 +52,7 @@ static void set_activated(struct sway_view *view, bool activated) {
|
|||
}
|
||||
}
|
||||
|
||||
static void close(struct sway_view *view) {
|
||||
static void _close(struct sway_view *view) {
|
||||
if (!assert_xdg(view)) {
|
||||
return;
|
||||
}
|
||||
|
@ -67,6 +62,13 @@ static void close(struct sway_view *view) {
|
|||
}
|
||||
}
|
||||
|
||||
static const struct sway_view_impl view_impl = {
|
||||
.get_prop = get_prop,
|
||||
.configure = configure,
|
||||
.set_activated = set_activated,
|
||||
.close = _close,
|
||||
};
|
||||
|
||||
static void handle_commit(struct wl_listener *listener, void *data) {
|
||||
struct sway_xdg_surface_v6 *sway_surface =
|
||||
wl_container_of(listener, sway_surface, commit);
|
||||
|
@ -74,37 +76,22 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
|||
// NOTE: We intentionally discard the view's desired width here
|
||||
// TODO: Store this for restoration when moving to floating plane
|
||||
// TODO: Let floating views do whatever
|
||||
view->width = sway_surface->pending_width;
|
||||
view->height = sway_surface->pending_height;
|
||||
view_update_size(view, sway_surface->pending_width,
|
||||
sway_surface->pending_height);
|
||||
view_damage_from(view);
|
||||
}
|
||||
|
||||
static void handle_unmap(struct wl_listener *listener, void *data) {
|
||||
struct sway_xdg_surface_v6 *sway_surface =
|
||||
wl_container_of(listener, sway_surface, unmap);
|
||||
view_damage_whole(sway_surface->view);
|
||||
container_view_destroy(sway_surface->view->swayc);
|
||||
sway_surface->view->swayc = NULL;
|
||||
sway_surface->view->surface = NULL;
|
||||
view_unmap(sway_surface->view);
|
||||
}
|
||||
|
||||
static void handle_map(struct wl_listener *listener, void *data) {
|
||||
struct sway_xdg_surface_v6 *sway_surface =
|
||||
wl_container_of(listener, sway_surface, map);
|
||||
struct sway_view *view = sway_surface->view;
|
||||
|
||||
sway_surface->view->surface = view->wlr_xdg_surface_v6->surface;
|
||||
|
||||
container_view_destroy(view->swayc);
|
||||
|
||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||
struct sway_container *focus = seat_get_focus_inactive(seat, &root_container);
|
||||
struct sway_container *cont = container_view_create(focus, view);
|
||||
view->swayc = cont;
|
||||
arrange_windows(cont->parent, -1, -1);
|
||||
input_manager_set_focus(input_manager, cont);
|
||||
|
||||
view_damage_whole(sway_surface->view);
|
||||
view_map(view, view->wlr_xdg_surface_v6->surface);
|
||||
}
|
||||
|
||||
static void handle_destroy(struct wl_listener *listener, void *data) {
|
||||
|
@ -112,8 +99,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, sway_xdg_surface, destroy);
|
||||
wl_list_remove(&sway_xdg_surface->commit.link);
|
||||
wl_list_remove(&sway_xdg_surface->destroy.link);
|
||||
container_view_destroy(sway_xdg_surface->view->swayc);
|
||||
free(sway_xdg_surface->view);
|
||||
wl_list_remove(&sway_xdg_surface->map.link);
|
||||
wl_list_remove(&sway_xdg_surface->unmap.link);
|
||||
view_destroy(sway_xdg_surface->view);
|
||||
free(sway_xdg_surface);
|
||||
}
|
||||
|
||||
|
@ -138,23 +126,16 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
struct sway_view *sway_view = calloc(1, sizeof(struct sway_view));
|
||||
if (!sway_assert(sway_view, "Failed to allocate view!")) {
|
||||
struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW, &view_impl);
|
||||
if (!sway_assert(view, "Failed to allocate view")) {
|
||||
return;
|
||||
}
|
||||
sway_view->type = SWAY_XDG_SHELL_V6_VIEW;
|
||||
sway_view->iface.get_prop = get_prop;
|
||||
sway_view->iface.set_size = set_size;
|
||||
sway_view->iface.set_position = set_position;
|
||||
sway_view->iface.set_activated = set_activated;
|
||||
sway_view->iface.close = close;
|
||||
sway_view->wlr_xdg_surface_v6 = xdg_surface;
|
||||
sway_view->sway_xdg_surface_v6 = sway_surface;
|
||||
sway_surface->view = sway_view;
|
||||
view->wlr_xdg_surface_v6 = xdg_surface;
|
||||
view->sway_xdg_surface_v6 = sway_surface;
|
||||
sway_surface->view = view;
|
||||
|
||||
// TODO:
|
||||
// - Look up pid and open on appropriate workspace
|
||||
// - Set new view to maximized so it behaves nicely
|
||||
// - Criteria
|
||||
|
||||
sway_surface->commit.notify = handle_commit;
|
||||
|
|
|
@ -14,6 +14,33 @@
|
|||
#include "sway/input/input-manager.h"
|
||||
#include "log.h"
|
||||
|
||||
static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_unmanaged *sway_surface =
|
||||
wl_container_of(listener, sway_surface, destroy);
|
||||
wl_list_remove(&sway_surface->destroy.link);
|
||||
wl_list_remove(&sway_surface->link);
|
||||
free(sway_surface);
|
||||
}
|
||||
|
||||
static void create_unmanaged(struct wlr_xwayland_surface *xsurface) {
|
||||
struct sway_xwayland_unmanaged *sway_surface =
|
||||
calloc(1, sizeof(struct sway_xwayland_unmanaged));
|
||||
if (!sway_assert(sway_surface, "Failed to allocate surface")) {
|
||||
return;
|
||||
}
|
||||
|
||||
sway_surface->wlr_xwayland_surface = xsurface;
|
||||
|
||||
wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy);
|
||||
sway_surface->destroy.notify = unmanaged_handle_destroy;
|
||||
|
||||
wl_list_insert(&root_container.sway_root->xwayland_unmanaged,
|
||||
&sway_surface->link);
|
||||
|
||||
// TODO: damage tracking
|
||||
}
|
||||
|
||||
|
||||
static bool assert_xwayland(struct sway_view *view) {
|
||||
return sway_assert(view->type == SWAY_XWAYLAND_VIEW,
|
||||
"Expected xwayland view!");
|
||||
|
@ -33,22 +60,13 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
|
|||
}
|
||||
}
|
||||
|
||||
static void set_size(struct sway_view *view, int width, int height) {
|
||||
static void configure(struct sway_view *view, double ox, double oy, int width,
|
||||
int height) {
|
||||
if (!assert_xwayland(view)) {
|
||||
return;
|
||||
}
|
||||
view->sway_xwayland_surface->pending_width = width;
|
||||
view->sway_xwayland_surface->pending_height = height;
|
||||
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
wlr_xwayland_surface_configure(xsurface, xsurface->x, xsurface->y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
static void set_position(struct sway_view *view, double ox, double oy) {
|
||||
if (!assert_xwayland(view)) {
|
||||
return;
|
||||
}
|
||||
struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
|
||||
if (!sway_assert(output, "view must be within tree to set position")) {
|
||||
return;
|
||||
|
@ -64,13 +82,12 @@ static void set_position(struct sway_view *view, double ox, double oy) {
|
|||
return;
|
||||
}
|
||||
|
||||
view->swayc->x = ox;
|
||||
view->swayc->y = oy;
|
||||
view_update_position(view, ox, oy);
|
||||
|
||||
wlr_xwayland_surface_configure(view->wlr_xwayland_surface,
|
||||
ox + loutput->x, oy + loutput->y,
|
||||
view->wlr_xwayland_surface->width,
|
||||
view->wlr_xwayland_surface->height);
|
||||
view->sway_xwayland_surface->pending_width = width;
|
||||
view->sway_xwayland_surface->pending_height = height;
|
||||
wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
static void set_activated(struct sway_view *view, bool activated) {
|
||||
|
@ -81,77 +98,58 @@ static void set_activated(struct sway_view *view, bool activated) {
|
|||
wlr_xwayland_surface_activate(surface, activated);
|
||||
}
|
||||
|
||||
static void close_view(struct sway_view *view) {
|
||||
static void _close(struct sway_view *view) {
|
||||
if (!assert_xwayland(view)) {
|
||||
return;
|
||||
}
|
||||
wlr_xwayland_surface_close(view->wlr_xwayland_surface);
|
||||
}
|
||||
|
||||
static const struct sway_view_impl view_impl = {
|
||||
.get_prop = get_prop,
|
||||
.configure = configure,
|
||||
.set_activated = set_activated,
|
||||
.close = _close,
|
||||
};
|
||||
|
||||
static void handle_commit(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_surface *sway_surface =
|
||||
wl_container_of(listener, sway_surface, commit);
|
||||
struct sway_view *view = sway_surface->view;
|
||||
// NOTE: We intentionally discard the view's desired width here
|
||||
// TODO: Let floating views do whatever
|
||||
view->width = sway_surface->pending_width;
|
||||
view->height = sway_surface->pending_height;
|
||||
view_update_size(view, sway_surface->pending_width,
|
||||
sway_surface->pending_height);
|
||||
view_damage_from(view);
|
||||
}
|
||||
|
||||
static void handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_surface *sway_surface =
|
||||
wl_container_of(listener, sway_surface, destroy);
|
||||
|
||||
wl_list_remove(&sway_surface->commit.link);
|
||||
wl_list_remove(&sway_surface->destroy.link);
|
||||
wl_list_remove(&sway_surface->request_configure.link);
|
||||
wl_list_remove(&sway_surface->view->unmanaged_view_link);
|
||||
container_view_destroy(sway_surface->view->swayc);
|
||||
sway_surface->view->swayc = NULL;
|
||||
sway_surface->view->surface = NULL;
|
||||
wl_list_remove(&sway_surface->map.link);
|
||||
wl_list_remove(&sway_surface->unmap.link);
|
||||
view_destroy(sway_surface->view);
|
||||
free(sway_surface);
|
||||
}
|
||||
|
||||
static void handle_unmap(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_surface *sway_surface =
|
||||
wl_container_of(listener, sway_surface, unmap);
|
||||
view_damage_whole(sway_surface->view);
|
||||
wl_list_remove(&sway_surface->view->unmanaged_view_link);
|
||||
wl_list_init(&sway_surface->view->unmanaged_view_link);
|
||||
container_view_destroy(sway_surface->view->swayc);
|
||||
sway_surface->view->swayc = NULL;
|
||||
sway_surface->view->surface = NULL;
|
||||
view_unmap(sway_surface->view);
|
||||
}
|
||||
|
||||
static void handle_map(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_surface *sway_surface =
|
||||
wl_container_of(listener, sway_surface, map);
|
||||
struct wlr_xwayland_surface *xsurface = data;
|
||||
|
||||
sway_surface->view->surface = xsurface->surface;
|
||||
struct sway_view *view = sway_surface->view;
|
||||
|
||||
// put it back into the tree
|
||||
if (wlr_xwayland_surface_is_unmanaged(xsurface) ||
|
||||
xsurface->override_redirect) {
|
||||
wl_list_remove(&sway_surface->view->unmanaged_view_link);
|
||||
wl_list_insert(&root_container.sway_root->unmanaged_views,
|
||||
&sway_surface->view->unmanaged_view_link);
|
||||
} else {
|
||||
struct sway_view *view = sway_surface->view;
|
||||
container_view_destroy(view->swayc);
|
||||
|
||||
wlr_xwayland_surface_set_maximized(xsurface, true);
|
||||
|
||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||
struct sway_container *focus = seat_get_focus_inactive(seat,
|
||||
&root_container);
|
||||
struct sway_container *cont = container_view_create(focus, view);
|
||||
view->swayc = cont;
|
||||
arrange_windows(cont->parent, -1, -1);
|
||||
input_manager_set_focus(input_manager, cont);
|
||||
}
|
||||
|
||||
view_damage_whole(sway_surface->view);
|
||||
wlr_xwayland_surface_set_maximized(xsurface, true);
|
||||
view_map(view, xsurface->surface);
|
||||
}
|
||||
|
||||
static void handle_request_configure(struct wl_listener *listener, void *data) {
|
||||
|
@ -171,34 +169,32 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
|
|||
listener, server, xwayland_surface);
|
||||
struct wlr_xwayland_surface *xsurface = data;
|
||||
|
||||
if (wlr_xwayland_surface_is_unmanaged(xsurface) ||
|
||||
xsurface->override_redirect) {
|
||||
wlr_log(L_DEBUG, "New xwayland unmanaged surface");
|
||||
create_unmanaged(xsurface);
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'",
|
||||
xsurface->title, xsurface->class);
|
||||
xsurface->title, xsurface->class);
|
||||
|
||||
struct sway_xwayland_surface *sway_surface =
|
||||
calloc(1, sizeof(struct sway_xwayland_surface));
|
||||
if (!sway_assert(sway_surface, "Failed to allocate surface!")) {
|
||||
if (!sway_assert(sway_surface, "Failed to allocate surface")) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct sway_view *sway_view = calloc(1, sizeof(struct sway_view));
|
||||
if (!sway_assert(sway_view, "Failed to allocate view!")) {
|
||||
struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW, &view_impl);
|
||||
if (!sway_assert(view, "Failed to allocate view")) {
|
||||
return;
|
||||
}
|
||||
sway_view->type = SWAY_XWAYLAND_VIEW;
|
||||
sway_view->iface.get_prop = get_prop;
|
||||
sway_view->iface.set_size = set_size;
|
||||
sway_view->iface.set_position = set_position;
|
||||
sway_view->iface.set_activated = set_activated;
|
||||
sway_view->iface.close = close_view;
|
||||
sway_view->wlr_xwayland_surface = xsurface;
|
||||
sway_view->sway_xwayland_surface = sway_surface;
|
||||
sway_surface->view = sway_view;
|
||||
|
||||
wl_list_init(&sway_view->unmanaged_view_link);
|
||||
view->wlr_xwayland_surface = xsurface;
|
||||
view->sway_xwayland_surface = sway_surface;
|
||||
sway_surface->view = view;
|
||||
|
||||
// TODO:
|
||||
// - Look up pid and open on appropriate workspace
|
||||
// - Set new view to maximized so it behaves nicely
|
||||
// - Criteria
|
||||
|
||||
wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit);
|
||||
|
|
|
@ -47,14 +47,15 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output,
|
|||
static struct sway_container *container_at_cursor(struct sway_cursor *cursor,
|
||||
struct wlr_surface **surface, double *sx, double *sy) {
|
||||
// check for unmanaged views first
|
||||
struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views;
|
||||
struct sway_view *view;
|
||||
wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) {
|
||||
if (view->type != SWAY_XWAYLAND_VIEW) {
|
||||
struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged;
|
||||
struct sway_xwayland_unmanaged *sway_surface;
|
||||
wl_list_for_each_reverse(sway_surface, unmanaged, link) {
|
||||
struct wlr_xwayland_surface *xsurface =
|
||||
sway_surface->wlr_xwayland_surface;
|
||||
if (xsurface->surface == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
struct wlr_box box = {
|
||||
.x = xsurface->x,
|
||||
.y = xsurface->y,
|
||||
|
|
|
@ -58,7 +58,7 @@ void layout_init(void) {
|
|||
|
||||
root_container.sway_root = calloc(1, sizeof(*root_container.sway_root));
|
||||
root_container.sway_root->output_layout = wlr_output_layout_create();
|
||||
wl_list_init(&root_container.sway_root->unmanaged_views);
|
||||
wl_list_init(&root_container.sway_root->xwayland_unmanaged);
|
||||
wl_signal_init(&root_container.sway_root->events.new_container);
|
||||
|
||||
root_container.sway_root->output_layout_change.notify =
|
||||
|
@ -288,7 +288,7 @@ void arrange_windows(struct sway_container *container,
|
|||
{
|
||||
container->width = width;
|
||||
container->height = height;
|
||||
view_set_size(container->sway_view,
|
||||
view_configure(container->sway_view, container->x, container->y,
|
||||
container->width, container->height);
|
||||
wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f",
|
||||
container->width, container->height,
|
||||
|
@ -349,8 +349,10 @@ static void apply_horiz_layout(struct sway_container *container,
|
|||
wlr_log(L_DEBUG,
|
||||
"Calculating arrangement for %p:%d (will scale %f by %f)",
|
||||
child, child->type, width, scale);
|
||||
|
||||
if (child->type == C_VIEW) {
|
||||
view_set_position(child->sway_view, child_x, y);
|
||||
view_configure(child->sway_view, child_x, y, child->width,
|
||||
child->height);
|
||||
} else {
|
||||
child->x = child_x;
|
||||
child->y = y;
|
||||
|
@ -406,7 +408,8 @@ void apply_vert_layout(struct sway_container *container,
|
|||
"Calculating arrangement for %p:%d (will scale %f by %f)",
|
||||
child, child->type, height, scale);
|
||||
if (child->type == C_VIEW) {
|
||||
view_set_position(child->sway_view, x, child_y);
|
||||
view_configure(child->sway_view, x, child_y, child->width,
|
||||
child->height);
|
||||
} else {
|
||||
child->x = x;
|
||||
child->y = child_y;
|
||||
|
|
|
@ -30,6 +30,7 @@ struct sway_container *container_output_destroy(struct sway_container *output) {
|
|||
wl_list_remove(&output->sway_output->destroy.link);
|
||||
wl_list_remove(&output->sway_output->mode.link);
|
||||
wl_list_remove(&output->sway_output->transform.link);
|
||||
wl_list_remove(&output->sway_output->scale.link);
|
||||
|
||||
wl_list_remove(&output->sway_output->damage_destroy.link);
|
||||
wl_list_remove(&output->sway_output->damage_frame.link);
|
||||
|
|
190
sway/tree/view.c
190
sway/tree/view.c
|
@ -1,3 +1,4 @@
|
|||
#include <stdlib.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include "log.h"
|
||||
|
@ -6,82 +7,117 @@
|
|||
#include "sway/tree/layout.h"
|
||||
#include "sway/tree/view.h"
|
||||
|
||||
struct sway_view *view_create(enum sway_view_type type,
|
||||
const struct sway_view_impl *impl) {
|
||||
struct sway_view *view = calloc(1, sizeof(struct sway_view));
|
||||
if (view == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
view->type = type;
|
||||
view->impl = impl;
|
||||
return view;
|
||||
}
|
||||
|
||||
void view_destroy(struct sway_view *view) {
|
||||
if (view == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (view->surface != NULL) {
|
||||
view_unmap(view);
|
||||
}
|
||||
|
||||
container_view_destroy(view->swayc);
|
||||
free(view);
|
||||
}
|
||||
|
||||
const char *view_get_title(struct sway_view *view) {
|
||||
if (view->iface.get_prop) {
|
||||
return view->iface.get_prop(view, VIEW_PROP_TITLE);
|
||||
if (view->impl->get_prop) {
|
||||
return view->impl->get_prop(view, VIEW_PROP_TITLE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *view_get_app_id(struct sway_view *view) {
|
||||
if (view->iface.get_prop) {
|
||||
return view->iface.get_prop(view, VIEW_PROP_APP_ID);
|
||||
if (view->impl->get_prop) {
|
||||
return view->impl->get_prop(view, VIEW_PROP_APP_ID);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *view_get_class(struct sway_view *view) {
|
||||
if (view->iface.get_prop) {
|
||||
return view->iface.get_prop(view, VIEW_PROP_CLASS);
|
||||
if (view->impl->get_prop) {
|
||||
return view->impl->get_prop(view, VIEW_PROP_CLASS);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *view_get_instance(struct sway_view *view) {
|
||||
if (view->iface.get_prop) {
|
||||
return view->iface.get_prop(view, VIEW_PROP_INSTANCE);
|
||||
if (view->impl->get_prop) {
|
||||
return view->impl->get_prop(view, VIEW_PROP_INSTANCE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void view_set_size(struct sway_view *view, int width, int height) {
|
||||
if (view->iface.set_size) {
|
||||
struct wlr_box box = {
|
||||
.x = view->swayc->x,
|
||||
.y = view->swayc->y,
|
||||
.width = view->width,
|
||||
.height = view->height,
|
||||
};
|
||||
view->iface.set_size(view, width, height);
|
||||
view_update_outputs(view, &box);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO make view coordinates in layout coordinates
|
||||
void view_set_position(struct sway_view *view, double ox, double oy) {
|
||||
if (view->iface.set_position) {
|
||||
struct wlr_box box = {
|
||||
.x = view->swayc->x,
|
||||
.y = view->swayc->y,
|
||||
.width = view->width,
|
||||
.height = view->height,
|
||||
};
|
||||
view->iface.set_position(view, ox, oy);
|
||||
view_update_outputs(view, &box);
|
||||
void view_configure(struct sway_view *view, double ox, double oy, int width,
|
||||
int height) {
|
||||
if (view->impl->configure) {
|
||||
view->impl->configure(view, ox, oy, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void view_set_activated(struct sway_view *view, bool activated) {
|
||||
if (view->iface.set_activated) {
|
||||
view->iface.set_activated(view, activated);
|
||||
if (view->impl->set_activated) {
|
||||
view->impl->set_activated(view, activated);
|
||||
}
|
||||
}
|
||||
|
||||
void view_close(struct sway_view *view) {
|
||||
if (view->iface.close) {
|
||||
view->iface.close(view);
|
||||
if (view->impl->close) {
|
||||
view->impl->close(view);
|
||||
}
|
||||
}
|
||||
|
||||
void view_update_outputs(struct sway_view *view, const struct wlr_box *before) {
|
||||
struct sway_container *container_view_destroy(struct sway_container *view) {
|
||||
if (!view) {
|
||||
return NULL;
|
||||
}
|
||||
wlr_log(L_DEBUG, "Destroying view '%s'", view->name);
|
||||
struct sway_container *parent = container_destroy(view);
|
||||
arrange_windows(parent, -1, -1);
|
||||
return parent;
|
||||
}
|
||||
|
||||
void view_damage_whole(struct sway_view *view) {
|
||||
for (int i = 0; i < root_container.children->length; ++i) {
|
||||
struct sway_container *cont = root_container.children->items[i];
|
||||
if (cont->type == C_OUTPUT) {
|
||||
output_damage_whole_view(cont->sway_output, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void view_damage_from(struct sway_view *view) {
|
||||
// TODO
|
||||
view_damage_whole(view);
|
||||
}
|
||||
|
||||
static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) {
|
||||
struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
|
||||
|
||||
box->x = output->x + view->swayc->x;
|
||||
box->y = output->y + view->swayc->y;
|
||||
box->width = view->width;
|
||||
box->height = view->height;
|
||||
}
|
||||
|
||||
static void view_update_outputs(struct sway_view *view,
|
||||
const struct wlr_box *before) {
|
||||
struct wlr_box box;
|
||||
view_get_layout_box(view, &box);
|
||||
|
||||
struct wlr_output_layout *output_layout =
|
||||
root_container.sway_root->output_layout;
|
||||
struct wlr_box box = {
|
||||
.x = view->swayc->x,
|
||||
.y = view->swayc->y,
|
||||
.width = view->width,
|
||||
.height = view->height,
|
||||
};
|
||||
struct wlr_output_layout_output *layout_output;
|
||||
wl_list_for_each(layout_output, &output_layout->outputs, link) {
|
||||
bool intersected = before != NULL && wlr_output_layout_intersects(
|
||||
|
@ -97,27 +133,63 @@ void view_update_outputs(struct sway_view *view, const struct wlr_box *before) {
|
|||
}
|
||||
}
|
||||
|
||||
struct sway_container *container_view_destroy(struct sway_container *view) {
|
||||
if (!view) {
|
||||
return NULL;
|
||||
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
|
||||
if (!sway_assert(view->surface == NULL, "cannot map mapped view")) {
|
||||
return;
|
||||
}
|
||||
wlr_log(L_DEBUG, "Destroying view '%s'", view->name);
|
||||
struct sway_container *parent = container_destroy(view);
|
||||
arrange_windows(parent, -1, -1);
|
||||
return parent;
|
||||
|
||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||
struct sway_container *focus = seat_get_focus_inactive(seat,
|
||||
&root_container);
|
||||
struct sway_container *cont = container_view_create(focus, view);
|
||||
|
||||
view->surface = wlr_surface;
|
||||
view->swayc = cont;
|
||||
|
||||
arrange_windows(cont->parent, -1, -1);
|
||||
input_manager_set_focus(input_manager, cont);
|
||||
|
||||
view_damage_whole(view);
|
||||
view_update_outputs(view, NULL);
|
||||
}
|
||||
|
||||
void view_damage_whole(struct sway_view *view) {
|
||||
struct sway_container *cont = NULL;
|
||||
for (int i = 0; i < root_container.children->length; ++i) {
|
||||
cont = root_container.children->items[i];
|
||||
if (cont->type == C_OUTPUT) {
|
||||
output_damage_whole_view(cont->sway_output, view);
|
||||
}
|
||||
void view_unmap(struct sway_view *view) {
|
||||
if (!sway_assert(view->surface != NULL, "cannot unmap unmapped view")) {
|
||||
return;
|
||||
}
|
||||
|
||||
view_damage_whole(view);
|
||||
|
||||
container_view_destroy(view->swayc);
|
||||
|
||||
view->swayc = NULL;
|
||||
view->surface = NULL;
|
||||
}
|
||||
|
||||
void view_damage_from(struct sway_view *view) {
|
||||
// TODO
|
||||
void view_update_position(struct sway_view *view, double ox, double oy) {
|
||||
if (view->swayc->x == ox && view->swayc->y == oy) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_box box;
|
||||
view_get_layout_box(view, &box);
|
||||
view_damage_whole(view);
|
||||
view->swayc->x = ox;
|
||||
view->swayc->y = oy;
|
||||
view_update_outputs(view, &box);
|
||||
view_damage_whole(view);
|
||||
}
|
||||
|
||||
void view_update_size(struct sway_view *view, int width, int height) {
|
||||
if (view->width == width && view->height == height) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_box box;
|
||||
view_get_layout_box(view, &box);
|
||||
view_damage_whole(view);
|
||||
view->width = width;
|
||||
view->height = height;
|
||||
view_update_outputs(view, &box);
|
||||
view_damage_whole(view);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue