summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Tony Crisci <tony@dubstepdish.com>2018-04-02 19:22:10 -0400
committerLibravatar Tony Crisci <tony@dubstepdish.com>2018-04-02 19:22:10 -0400
commita89096278b3dee599d75b7e91810a354b90a0ecb (patch)
tree69bb7208e42acab112048192f3a93557c6658186
parentMerge branch 'wlroots' into split-containers (diff)
parentMerge pull request #1691 from emersion/view-redesign (diff)
downloadsway-a89096278b3dee599d75b7e91810a354b90a0ecb.tar.gz
sway-a89096278b3dee599d75b7e91810a354b90a0ecb.tar.zst
sway-a89096278b3dee599d75b7e91810a354b90a0ecb.zip
Merge branch 'wlroots' into split-containers
-rw-r--r--include/sway/output.h1
-rw-r--r--include/sway/tree/container.h5
-rw-r--r--include/sway/tree/layout.h2
-rw-r--r--include/sway/tree/view.h59
-rw-r--r--protocols/desktop-shell.xml138
-rw-r--r--protocols/gamma-control.xml57
-rw-r--r--protocols/server-decoration.xml94
-rw-r--r--protocols/swaylock.xml18
-rw-r--r--protocols/xdg-shell.xml430
-rw-r--r--sway/desktop/output.c87
-rw-r--r--sway/desktop/wl_shell.c61
-rw-r--r--sway/desktop/xdg_shell_v6.c67
-rw-r--r--sway/desktop/xwayland.c136
-rw-r--r--sway/input/cursor.c11
-rw-r--r--sway/tree/layout.c11
-rw-r--r--sway/tree/output.c1
-rw-r--r--sway/tree/view.c188
17 files changed, 356 insertions, 1010 deletions
diff --git a/include/sway/output.h b/include/sway/output.h
index b343ecff..98d0f83f 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -24,6 +24,7 @@ struct sway_output {
24 struct wl_listener destroy; 24 struct wl_listener destroy;
25 struct wl_listener mode; 25 struct wl_listener mode;
26 struct wl_listener transform; 26 struct wl_listener transform;
27 struct wl_listener scale;
27 28
28 struct wl_listener damage_destroy; 29 struct wl_listener damage_destroy;
29 struct wl_listener damage_frame; 30 struct wl_listener damage_frame;
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index fa22ea75..464f80c4 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -70,9 +70,10 @@ struct sway_container {
70 enum sway_container_layout prev_layout; 70 enum sway_container_layout prev_layout;
71 enum sway_container_layout workspace_layout; 71 enum sway_container_layout workspace_layout;
72 72
73 // TODO convert to layout coordinates 73 // For C_ROOT, this has no meaning
74 // For C_OUTPUT, this is the output position in layout coordinates
75 // For other types, this is the position in output-local coordinates
74 double x, y; 76 double x, y;
75
76 // does not include borders or gaps. 77 // does not include borders or gaps.
77 double width, height; 78 double width, height;
78 79
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h
index fbc3d6af..8badb244 100644
--- a/include/sway/tree/layout.h
+++ b/include/sway/tree/layout.h
@@ -20,7 +20,7 @@ struct sway_root {
20 20
21 struct wl_listener output_layout_change; 21 struct wl_listener output_layout_change;
22 22
23 struct wl_list unmanaged_views; // sway_view::unmanaged_view_link 23 struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link
24 24
25 struct { 25 struct {
26 struct wl_signal new_container; 26 struct wl_signal new_container;
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 3965d2b7..4b84205e 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -4,6 +4,8 @@
4#include <wlr/types/wlr_surface.h> 4#include <wlr/types/wlr_surface.h>
5#include <wlr/types/wlr_xdg_shell_v6.h> 5#include <wlr/types/wlr_xdg_shell_v6.h>
6#include <wlr/xwayland.h> 6#include <wlr/xwayland.h>
7#include "sway/input/input-manager.h"
8#include "sway/input/seat.h"
7 9
8struct sway_container; 10struct sway_container;
9struct sway_view; 11struct sway_view;
@@ -37,6 +39,13 @@ struct sway_xwayland_surface {
37 int pending_width, pending_height; 39 int pending_width, pending_height;
38}; 40};
39 41
42struct sway_xwayland_unmanaged {
43 struct wlr_xwayland_surface *wlr_xwayland_surface;
44 struct wl_list link;
45
46 struct wl_listener destroy;
47};
48
40struct sway_wl_shell_surface { 49struct sway_wl_shell_surface {
41 struct sway_view *view; 50 struct sway_view *view;
42 51
@@ -64,10 +73,21 @@ enum sway_view_prop {
64 VIEW_PROP_INSTANCE, 73 VIEW_PROP_INSTANCE,
65}; 74};
66 75
76struct sway_view_impl {
77 const char *(*get_prop)(struct sway_view *view,
78 enum sway_view_prop prop);
79 void (*configure)(struct sway_view *view, double ox, double oy, int width,
80 int height);
81 void (*set_activated)(struct sway_view *view, bool activated);
82 void (*close)(struct sway_view *view);
83};
84
67struct sway_view { 85struct sway_view {
68 enum sway_view_type type; 86 enum sway_view_type type;
69 struct sway_container *swayc; 87 const struct sway_view_impl *impl;
70 struct wlr_surface *surface; 88
89 struct sway_container *swayc; // NULL for unmanaged views
90 struct wlr_surface *surface; // NULL for unmapped views
71 int width, height; 91 int width, height;
72 92
73 union { 93 union {
@@ -82,21 +102,15 @@ struct sway_view {
82 struct sway_wl_shell_surface *sway_wl_shell_surface; 102 struct sway_wl_shell_surface *sway_wl_shell_surface;
83 }; 103 };
84 104
85 struct {
86 const char *(*get_prop)(struct sway_view *view,
87 enum sway_view_prop prop);
88 void (*set_size)(struct sway_view *view,
89 int width, int height);
90 void (*set_position)(struct sway_view *view,
91 double ox, double oy);
92 void (*set_activated)(struct sway_view *view, bool activated);
93 void (*close)(struct sway_view *view);
94 } iface;
95
96 // only used for unmanaged views (shell specific) 105 // only used for unmanaged views (shell specific)
97 struct wl_list unmanaged_view_link; // sway_root::unmanaged views 106 struct wl_list unmanaged_view_link; // sway_root::unmanaged_views
98}; 107};
99 108
109struct sway_view *view_create(enum sway_view_type type,
110 const struct sway_view_impl *impl);
111
112void view_destroy(struct sway_view *view);
113
100const char *view_get_title(struct sway_view *view); 114const char *view_get_title(struct sway_view *view);
101 115
102const char *view_get_app_id(struct sway_view *view); 116const char *view_get_app_id(struct sway_view *view);
@@ -105,18 +119,25 @@ const char *view_get_class(struct sway_view *view);
105 119
106const char *view_get_instance(struct sway_view *view); 120const char *view_get_instance(struct sway_view *view);
107 121
108void view_set_size(struct sway_view *view, int width, int height); 122void view_configure(struct sway_view *view, double ox, double oy, int width,
109 123 int height);
110void view_set_position(struct sway_view *view, double ox, double oy);
111 124
112void view_set_activated(struct sway_view *view, bool activated); 125void view_set_activated(struct sway_view *view, bool activated);
113 126
114void view_close(struct sway_view *view); 127void view_close(struct sway_view *view);
115 128
116void view_update_outputs(struct sway_view *view, const struct wlr_box *before);
117
118void view_damage_whole(struct sway_view *view); 129void view_damage_whole(struct sway_view *view);
119 130
120void view_damage_from(struct sway_view *view); 131void view_damage_from(struct sway_view *view);
121 132
133// view implementation
134
135void view_map(struct sway_view *view, struct wlr_surface *wlr_surface);
136
137void view_unmap(struct sway_view *view);
138
139void view_update_position(struct sway_view *view, double ox, double oy);
140
141void view_update_size(struct sway_view *view, int width, int height);
142
122#endif 143#endif
diff --git a/protocols/desktop-shell.xml b/protocols/desktop-shell.xml
deleted file mode 100644
index 581f0c5d..00000000
--- a/protocols/desktop-shell.xml
+++ /dev/null
@@ -1,138 +0,0 @@
1<protocol name="desktop">
2
3 <interface name="desktop_shell" version="3">
4 <description summary="create desktop widgets and helpers">
5 Traditional user interfaces can rely on this interface to define the
6 foundations of typical desktops. Currently it's possible to set up
7 background, panels and locking surfaces.
8 </description>
9
10 <request name="set_background">
11 <arg name="output" type="object" interface="wl_output"/>
12 <arg name="surface" type="object" interface="wl_surface"/>
13 </request>
14
15 <request name="set_panel">
16 <arg name="output" type="object" interface="wl_output"/>
17 <arg name="surface" type="object" interface="wl_surface"/>
18 </request>
19
20 <request name="set_lock_surface">
21 <arg name="surface" type="object" interface="wl_surface"/>
22 </request>
23
24 <request name="unlock"/>
25
26 <request name="set_grab_surface">
27 <description summary="set grab surface">
28 The surface set by this request will receive a fake
29 pointer.enter event during grabs at position 0, 0 and is
30 expected to set an appropriate cursor image as described by
31 the grab_cursor event sent just before the enter event.
32 </description>
33 <arg name="surface" type="object" interface="wl_surface"/>
34 </request>
35
36 <!-- We'll fold most of wl_shell into this interface and then
37 they'll share the configure event. -->
38 <event name="configure">
39 <arg name="edges" type="uint"/>
40 <arg name="surface" type="object" interface="wl_surface"/>
41 <arg name="width" type="int"/>
42 <arg name="height" type="int"/>
43 </event>
44
45 <event name="prepare_lock_surface">
46 <description summary="tell the client to create, set the lock surface">
47 Tell the client we want it to create and set the lock surface, which is
48 a GUI asking the user to unlock the screen. The lock surface is
49 announced with 'set_lock_surface'. Whether or not the client actually
50 implements locking, it MUST send 'unlock' request to let the normal
51 desktop resume.
52 </description>
53 </event>
54
55 <event name="grab_cursor">
56 <description summary="tell client what cursor to show during a grab">
57 This event will be sent immediately before a fake enter event on the
58 grab surface.
59 </description>
60 <arg name="cursor" type="uint"/>
61 </event>
62
63 <enum name="cursor">
64 <entry name="none" value="0"/>
65
66 <entry name="resize_top" value="1"/>
67 <entry name="resize_bottom" value="2"/>
68
69 <entry name="arrow" value="3"/>
70
71 <entry name="resize_left" value="4"/>
72 <entry name="resize_top_left" value="5"/>
73 <entry name="resize_bottom_left" value="6"/>
74
75 <entry name="move" value="7"/>
76
77 <entry name="resize_right" value="8"/>
78 <entry name="resize_top_right" value="9"/>
79 <entry name="resize_bottom_right" value="10"/>
80
81 <entry name="busy" value="11"/>
82 </enum>
83
84 <!-- Version 2 additions -->
85
86 <request name="desktop_ready" since="2">
87 <description summary="desktop is ready to be shown">
88 Tell the server, that enough desktop elements have been drawn
89 to make the desktop look ready for use. During start-up, the
90 server can wait for this request with a black screen before
91 starting to fade in the desktop, for instance. If the client
92 parts of a desktop take a long time to initialize, we avoid
93 showing temporary garbage.
94 </description>
95 </request>
96
97 <!-- Version 3 additions -->
98
99 <enum name="panel_position">
100 <entry name="top" value="0"/>
101 <entry name="bottom" value="1"/>
102 <entry name="left" value="2"/>
103 <entry name="right" value="3"/>
104 </enum>
105
106 <enum name="error">
107 <entry name="invalid_argument" value="0"
108 summary="an invalid argument was provided in a request"/>
109 </enum>
110
111 <request name="set_panel_position" since="3">
112 <description summary="set panel position">
113 Tell the shell which side of the screen the panel is
114 located. This is so that new windows do not overlap the panel
115 and maximized windows maximize properly.
116 </description>
117 <arg name="position" type="uint"/>
118 </request>
119
120 </interface>
121
122 <interface name="screensaver" version="1">
123 <description summary="interface for implementing screensavers">
124 Only one client can bind this interface at a time.
125 </description>
126
127 <request name="set_surface">
128 <description summary="set the surface type as a screensaver">
129 A screensaver surface is normally hidden, and only visible after an
130 idle timeout.
131 </description>
132
133 <arg name="surface" type="object" interface="wl_surface"/>
134 <arg name="output" type="object" interface="wl_output"/>
135 </request>
136
137 </interface>
138</protocol>
diff --git a/protocols/gamma-control.xml b/protocols/gamma-control.xml
deleted file mode 100644
index e6e33265..00000000
--- a/protocols/gamma-control.xml
+++ /dev/null
@@ -1,57 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<protocol name="gamma_control">
3
4 <copyright>
5 Copyright © 2015 Giulio camuffo
6
7 Permission to use, copy, modify, distribute, and sell this
8 software and its documentation for any purpose is hereby granted
9 without fee, provided that the above copyright notice appear in
10 all copies and that both that copyright notice and this permission
11 notice appear in supporting documentation, and that the name of
12 the copyright holders not be used in advertising or publicity
13 pertaining to distribution of the software without specific,
14 written prior permission. The copyright holders make no
15 representations about the suitability of this software for any
16 purpose. It is provided "as is" without express or implied
17 warranty.
18
19 THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
20 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
24 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
26 THIS SOFTWARE.
27 </copyright>
28
29 <interface name="gamma_control_manager" version="1">
30 <request name="destroy" type="destructor"/>
31
32 <request name="get_gamma_control">
33 <arg name="id" type="new_id" interface="gamma_control"/>
34 <arg name="output" type="object" interface="wl_output"/>
35 </request>
36 </interface>
37
38 <interface name="gamma_control" version="1">
39 <enum name="error">
40 <entry name="invalid_gamma" value="0"/>
41 </enum>
42
43 <request name="destroy" type="destructor"/>
44
45 <request name="set_gamma">
46 <arg name="red" type="array"/>
47 <arg name="green" type="array"/>
48 <arg name="blue" type="array"/>
49 </request>
50
51 <request name="reset_gamma"/>
52
53 <event name="gamma_size">
54 <arg name="size" type="uint"/>
55 </event>
56 </interface>
57</protocol>
diff --git a/protocols/server-decoration.xml b/protocols/server-decoration.xml
deleted file mode 100644
index 8bc106c7..00000000
--- a/protocols/server-decoration.xml
+++ /dev/null
@@ -1,94 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<protocol name="server_decoration">
3 <copyright><![CDATA[
4 Copyright (C) 2015 Martin Gräßlin
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 2.1 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 ]]></copyright>
19 <interface name="org_kde_kwin_server_decoration_manager" version="1">
20 <description summary="Server side window decoration manager">
21 This interface allows to coordinate whether the server should create
22 a server-side window decoration around a wl_surface representing a
23 shell surface (wl_shell_surface or similar). By announcing support
24 for this interface the server indicates that it supports server
25 side decorations.
26 </description>
27 <request name="create">
28 <description summary="Create a server-side decoration object for a given surface">
29 When a client creates a server-side decoration object it indicates
30 that it supports the protocol. The client is supposed to tell the
31 server whether it wants server-side decorations or will provide
32 client-side decorations.
33
34 If the client does not create a server-side decoration object for
35 a surface the server interprets this as lack of support for this
36 protocol and considers it as client-side decorated. Nevertheless a
37 client-side decorated surface should use this protocol to indicate
38 to the server that it does not want a server-side deco.
39 </description>
40 <arg name="id" type="new_id" interface="org_kde_kwin_server_decoration"/>
41 <arg name="surface" type="object" interface="wl_surface"/>
42 </request>
43 <enum name="mode">
44 <description summary="Possible values to use in request_mode and the event mode."/>
45 <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."/>
46 <entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/>
47 <entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/>
48 </enum>
49 <event name="default_mode">
50 <description summary="The default mode used on the server">
51 This event is emitted directly after binding the interface. It contains
52 the default mode for the decoration. When a new server decoration object
53 is created this new object will be in the default mode until the first
54 request_mode is requested.
55
56 The server may change the default mode at any time.
57 </description>
58 <arg name="mode" type="uint" summary="The default decoration mode applied to newly created server decorations."/>
59 </event>
60 </interface>
61 <interface name="org_kde_kwin_server_decoration" version="1">
62 <request name="release" type="destructor">
63 <description summary="release the server decoration object"/>
64 </request>
65 <enum name="mode">
66 <description summary="Possible values to use in request_mode and the event mode."/>
67 <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."/>
68 <entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/>
69 <entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/>
70 </enum>
71 <request name="request_mode">
72 <description summary="The decoration mode the surface wants to use."/>
73 <arg name="mode" type="uint" summary="The mode this surface wants to use."/>
74 </request>
75 <event name="mode">
76 <description summary="The new decoration mode applied by the server">
77 This event is emitted directly after the decoration is created and
78 represents the base decoration policy by the server. E.g. a server
79 which wants all surfaces to be client-side decorated will send Client,
80 a server which wants server-side decoration will send Server.
81
82 The client can request a different mode through the decoration request.
83 The server will acknowledge this by another event with the same mode. So
84 even if a server prefers server-side decoration it's possible to force a
85 client-side decoration.
86
87 The server may emit this event at any time. In this case the client can
88 again request a different mode. It's the responsibility of the server to
89 prevent a feedback loop.
90 </description>
91 <arg name="mode" type="uint" summary="The decoration mode applied to the surface by the server."/>
92 </event>
93 </interface>
94</protocol>
diff --git a/protocols/swaylock.xml b/protocols/swaylock.xml
deleted file mode 100644
index c7a102dd..00000000
--- a/protocols/swaylock.xml
+++ /dev/null
@@ -1,18 +0,0 @@
1<protocol name="lock">
2
3 <interface name="lock" version="1">
4 <description summary="create lock screen UIs">
5 The Weston desktop-shell protocol's locking functionality depends more
6 on the behavior of the compositor than of a screen locking client, so
7 another protocol is necessary.
8 </description>
9
10 <request name="set_lock_surface">
11 <arg name="output" type="object" interface="wl_output"/>
12 <arg name="surface" type="object" interface="wl_surface"/>
13 </request>
14
15 <request name="unlock"/>
16
17 </interface>
18</protocol>
diff --git a/protocols/xdg-shell.xml b/protocols/xdg-shell.xml
deleted file mode 100644
index 7bf4ae3a..00000000
--- a/protocols/xdg-shell.xml
+++ /dev/null
@@ -1,430 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<protocol name="xdg_shell">
3
4 <copyright>
5 Copyright © 2008-2013 Kristian Høgsberg
6 Copyright © 2013 Rafael Antognolli
7 Copyright © 2013 Jasper St. Pierre
8 Copyright © 2010-2013 Intel Corporation
9
10 Permission to use, copy, modify, distribute, and sell this
11 software and its documentation for any purpose is hereby granted
12 without fee, provided that the above copyright notice appear in
13 all copies and that both that copyright notice and this permission
14 notice appear in supporting documentation, and that the name of
15 the copyright holders not be used in advertising or publicity
16 pertaining to distribution of the software without specific,
17 written prior permission. The copyright holders make no
18 representations about the suitability of this software for any
19 purpose. It is provided "as is" without express or implied
20 warranty.
21
22 THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
23 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
24 FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
25 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
29 THIS SOFTWARE.
30 </copyright>
31
32 <interface name="xdg_shell" version="1">
33 <description summary="create desktop-style surfaces">
34 This interface is implemented by servers that provide
35 desktop-style user interfaces.
36
37 It allows clients to associate a xdg_surface with
38 a basic surface.
39 </description>
40
41 <enum name="version">
42 <description summary="latest protocol version">
43 The 'current' member of this enum gives the version of the
44 protocol. Implementations can compare this to the version
45 they implement using static_assert to ensure the protocol and
46 implementation versions match.
47 </description>
48 <entry name="current" value="4" summary="Always the latest version"/>
49 </enum>
50
51 <enum name="error">
52 <entry name="role" value="0" summary="given wl_surface has another role"/>
53 </enum>
54
55 <request name="use_unstable_version">
56 <description summary="enable use of this unstable version">
57 Negotiate the unstable version of the interface. This
58 mechanism is in place to ensure client and server agree on the
59 unstable versions of the protocol that they speak or exit
60 cleanly if they don't agree. This request will go away once
61 the xdg-shell protocol is stable.
62 </description>
63 <arg name="version" type="int"/>
64 </request>
65
66 <request name="get_xdg_surface">
67 <description summary="create a shell surface from a surface">
68 Create a shell surface for an existing surface.
69
70 This request gives the surface the role of xdg_surface. If the
71 surface already has another role, it raises a protocol error.
72
73 Only one shell or popup surface can be associated with a given
74 surface.
75 </description>
76 <arg name="id" type="new_id" interface="xdg_surface"/>
77 <arg name="surface" type="object" interface="wl_surface"/>
78 </request>
79
80 <request name="get_xdg_popup">
81 <description summary="create a shell surface from a surface">
82 Create a popup surface for an existing surface.
83
84 This request gives the surface the role of xdg_popup. If the
85 surface already has another role, it raises a protocol error.
86
87 Only one shell or popup surface can be associated with a given
88 surface.
89 </description>
90 <arg name="id" type="new_id" interface="xdg_popup"/>
91 <arg name="surface" type="object" interface="wl_surface"/>
92 <arg name="parent" type="object" interface="wl_surface"/>
93 <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
94 <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
95 <arg name="x" type="int"/>
96 <arg name="y" type="int"/>
97 <arg name="flags" type="uint"/>
98 </request>
99
100 <event name="ping">
101 <description summary="check if the client is alive">
102 The ping event asks the client if it's still alive. Pass the
103 serial specified in the event back to the compositor by sending
104 a "pong" request back with the specified serial.
105
106 Compositors can use this to determine if the client is still
107 alive. It's unspecified what will happen if the client doesn't
108 respond to the ping request, or in what timeframe. Clients should
109 try to respond in a reasonable amount of time.
110 </description>
111 <arg name="serial" type="uint" summary="pass this to the callback"/>
112 </event>
113
114 <request name="pong">
115 <description summary="respond to a ping event">
116 A client must respond to a ping event with a pong request or
117 the client may be deemed unresponsive.
118 </description>
119 <arg name="serial" type="uint" summary="serial of the ping event"/>
120 </request>
121 </interface>
122
123 <interface name="xdg_surface" version="1">
124
125 <description summary="desktop-style metadata interface">
126 An interface that may be implemented by a wl_surface, for
127 implementations that provide a desktop-style user interface.
128
129 It provides requests to treat surfaces like windows, allowing to set
130 properties like maximized, fullscreen, minimized, and to move and resize
131 them, and associate metadata like title and app id.
132
133 On the server side the object is automatically destroyed when
134 the related wl_surface is destroyed. On client side,
135 xdg_surface.destroy() must be called before destroying
136 the wl_surface object.
137 </description>
138
139 <request name="destroy" type="destructor">
140 <description summary="remove xdg_surface interface">
141 The xdg_surface interface is removed from the wl_surface object
142 that was turned into a xdg_surface with
143 xdg_shell.get_xdg_surface request. The xdg_surface properties,
144 like maximized and fullscreen, are lost. The wl_surface loses
145 its role as a xdg_surface. The wl_surface is unmapped.
146 </description>
147 </request>
148
149 <request name="set_parent">
150 <description summary="surface is a child of another surface">
151 Child surfaces are stacked above their parents, and will be
152 unmapped if the parent is unmapped too. They should not appear
153 on task bars and alt+tab.
154 </description>
155 <arg name="parent" type="object" interface="wl_surface" allow-null="true"/>
156 </request>
157
158 <request name="set_title">
159 <description summary="set surface title">
160 Set a short title for the surface.
161
162 This string may be used to identify the surface in a task bar,
163 window list, or other user interface elements provided by the
164 compositor.
165
166 The string must be encoded in UTF-8.
167 </description>
168 <arg name="title" type="string"/>
169 </request>
170
171 <request name="set_app_id">
172 <description summary="set surface class">
173 Set an id for the surface.
174
175 The app id identifies the general class of applications to which
176 the surface belongs.
177
178 It should be the ID that appears in the new desktop entry
179 specification, the interface name.
180 </description>
181 <arg name="app_id" type="string"/>
182 </request>
183
184 <request name="show_window_menu">
185 <description summary="show the window menu">
186 Clients implementing client-side decorations might want to show
187 a context menu when right-clicking on the decorations, giving the
188 user a menu that they can use to maximize or minimize the window.
189
190 This request asks the compositor to pop up such a window menu at
191 the given position, relative to the parent surface. There are
192 no guarantees as to what the window menu contains.
193
194 Your surface must have focus on the seat passed in to pop up the
195 window menu.
196 </description>
197
198 <arg name="seat" type="object" interface="wl_seat" summary="the seat to pop the window up on"/>
199 <arg name="serial" type="uint" summary="serial of the event to pop up the window for"/>
200 <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
201 <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
202 </request>
203
204 <request name="move">
205 <description summary="start an interactive move">
206 Start a pointer-driven move of the surface.
207
208 This request must be used in response to a button press event.
209 The server may ignore move requests depending on the state of
210 the surface (e.g. fullscreen or maximized).
211 </description>
212 <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
213 <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
214 </request>
215
216 <enum name="resize_edge">
217 <description summary="edge values for resizing">
218 These values are used to indicate which edge of a surface
219 is being dragged in a resize operation. The server may
220 use this information to adapt its behavior, e.g. choose
221 an appropriate cursor image.
222 </description>
223 <entry name="none" value="0"/>
224 <entry name="top" value="1"/>
225 <entry name="bottom" value="2"/>
226 <entry name="left" value="4"/>
227 <entry name="top_left" value="5"/>
228 <entry name="bottom_left" value="6"/>
229 <entry name="right" value="8"/>
230 <entry name="top_right" value="9"/>
231 <entry name="bottom_right" value="10"/>
232 </enum>
233
234 <request name="resize">
235 <description summary="start an interactive resize">
236 Start a pointer-driven resizing of the surface.
237
238 This request must be used in response to a button press event.
239 The server may ignore resize requests depending on the state of
240 the surface (e.g. fullscreen or maximized).
241 </description>
242 <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
243 <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
244 <arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
245 </request>
246
247 <enum name="state">
248 <description summary="types of state on the surface">
249 The different state values used on the surface. This is designed for
250 state values like maximized, fullscreen. It is paired with the
251 configure event to ensure that both the client and the compositor
252 setting the state can be synchronized.
253
254 States set in this way are double-buffered. They will get applied on
255 the next commit.
256
257 Desktop environments may extend this enum by taking up a range of
258 values and documenting the range they chose in this description.
259 They are not required to document the values for the range that they
260 chose. Ideally, any good extensions from a desktop environment should
261 make its way into standardization into this enum.
262
263 The current reserved ranges are:
264
265 0x0000 - 0x0FFF: xdg-shell core values, documented below.
266 0x1000 - 0x1FFF: GNOME
267 </description>
268 <entry name="maximized" value="1">
269 <description summary="the surface is maximized">
270 The surface is maximized. The window geometry specified in the configure
271 event must be obeyed by the client.
272 </description>
273 </entry>
274 <entry name="fullscreen" value="2">
275 <description summary="the surface is fullscreen">
276 The surface is fullscreen. The window geometry specified in the configure
277 event must be obeyed by the client.
278 </description>
279 </entry>
280 <entry name="resizing" value="3">
281 <description summary="the surface is being resized">
282 The surface is being resized. The window geometry specified in the
283 configure event is a maximum; the client cannot resize beyond it.
284 Clients that have aspect ratio or cell sizing configuration can use
285 a smaller size, however.
286 </description>
287 </entry>
288 <entry name="activated" value="4">
289 <description summary="the client window is active">
290 Client window decorations should be painted as if the window is
291 active. Do not assume this means that the window actually has
292 keyboard or pointer focus.
293 </description>
294 </entry>
295 </enum>
296
297 <event name="configure">
298 <description summary="suggest a surface change">
299 The configure event asks the client to resize its surface.
300
301 The width and height arguments specify a hint to the window
302 about how its surface should be resized in window geometry
303 coordinates. The states listed in the event specify how the
304 width/height arguments should be interpreted.
305
306 A client should arrange a new surface, and then send a
307 ack_configure request with the serial sent in this configure
308 event before attaching a new surface.
309
310 If the client receives multiple configure events before it
311 can respond to one, it is free to discard all but the last
312 event it received.
313 </description>
314
315 <arg name="width" type="int"/>
316 <arg name="height" type="int"/>
317 <arg name="states" type="array"/>
318 <arg name="serial" type="uint"/>
319 </event>
320
321 <request name="ack_configure">
322 <description summary="ack a configure event">
323 When a configure event is received, a client should then ack it
324 using the ack_configure request to ensure that the compositor
325 knows the client has seen the event.
326
327 By this point, the state is confirmed, and the next attach should
328 contain the buffer drawn for the configure event you are acking.
329 </description>
330 <arg name="serial" type="uint" summary="a serial to configure for"/>
331 </request>
332
333 <request name="set_window_geometry">
334 <description summary="set the new window geometry">
335 The window geometry of a window is its "visible bounds" from the
336 user's perspective. Client-side decorations often have invisible
337 portions like drop-shadows which should be ignored for the
338 purposes of aligning, placing and constraining windows.
339
340 The default value is the full bounds of the surface, including any
341 subsurfaces. Once the window geometry of the surface is set once,
342 it is not possible to unset it, and it will remain the same until
343 set_window_geometry is called again, even if a new subsurface or
344 buffer is attached.
345
346 If responding to a configure event, the window geometry in here
347 must respect the sizing negotiations specified by the states in
348 the configure event.
349 </description>
350 <arg name="x" type="int"/>
351 <arg name="y" type="int"/>
352 <arg name="width" type="int"/>
353 <arg name="height" type="int"/>
354 </request>
355
356 <request name="set_maximized" />
357 <request name="unset_maximized" />
358
359 <request name="set_fullscreen">
360 <description summary="set the window as fullscreen on a monitor">
361 Make the surface fullscreen.
362
363 You can specify an output that you would prefer to be fullscreen.
364 If this value is NULL, it's up to the compositor to choose which
365 display will be used to map this surface.
366 </description>
367 <arg name="output" type="object" interface="wl_output" allow-null="true"/>
368 </request>
369 <request name="unset_fullscreen" />
370
371 <request name="set_minimized" />
372
373 <event name="close">
374 <description summary="surface wants to be closed">
375 The close event is sent by the compositor when the user
376 wants the surface to be closed. This should be equivalent to
377 the user clicking the close button in client-side decorations,
378 if your application has any...
379
380 This is only a request that the user intends to close your
381 window. The client may choose to ignore this request, or show
382 a dialog to ask the user to save their data...
383 </description>
384 </event>
385 </interface>
386
387 <interface name="xdg_popup" version="1">
388 <description summary="desktop-style metadata interface">
389 An interface that may be implemented by a wl_surface, for
390 implementations that provide a desktop-style popups/menus. A popup
391 surface is a transient surface with an added pointer grab.
392
393 An existing implicit grab will be changed to owner-events mode,
394 and the popup grab will continue after the implicit grab ends
395 (i.e. releasing the mouse button does not cause the popup to be
396 unmapped).
397
398 The popup grab continues until the window is destroyed or a mouse
399 button is pressed in any other clients window. A click in any of
400 the clients surfaces is reported as normal, however, clicks in
401 other clients surfaces will be discarded and trigger the callback.
402
403 The x and y arguments specify the locations of the upper left
404 corner of the surface relative to the upper left corner of the
405 parent surface, in surface local coordinates.
406
407 xdg_popup surfaces are always transient for another surface.
408 </description>
409
410 <request name="destroy" type="destructor">
411 <description summary="remove xdg_surface interface">
412 The xdg_surface interface is removed from the wl_surface object
413 that was turned into a xdg_surface with
414 xdg_shell.get_xdg_surface request. The xdg_surface properties,
415 like maximized and fullscreen, are lost. The wl_surface loses
416 its role as a xdg_surface. The wl_surface is unmapped.
417 </description>
418 </request>
419
420 <event name="popup_done">
421 <description summary="popup interaction is done">
422 The popup_done event is sent out when a popup grab is broken,
423 that is, when the users clicks a surface that doesn't belong
424 to the client owning the popup surface.
425 </description>
426 <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
427 </event>
428
429 </interface>
430</protocol>
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 5e8a081c..10ed1f6d 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -39,6 +39,32 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh,
39 } 39 }
40} 40}
41 41
42/**
43 * Checks whether a surface at (lx, ly) intersects an output. If `box` is not
44 * NULL, it populates it with the surface box in the output, in output-local
45 * coordinates.
46 */
47static bool surface_intersect_output(struct wlr_surface *surface,
48 struct wlr_output_layout *output_layout, struct wlr_output *wlr_output,
49 double lx, double ly, float rotation, struct wlr_box *box) {
50 double ox = lx, oy = ly;
51 wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy);
52
53 if (box != NULL) {
54 box->x = ox * wlr_output->scale;
55 box->y = oy * wlr_output->scale;
56 box->width = surface->current->width * wlr_output->scale;
57 box->height = surface->current->height * wlr_output->scale;
58 }
59
60 struct wlr_box layout_box = {
61 .x = lx, .y = ly,
62 .width = surface->current->width, .height = surface->current->height,
63 };
64 wlr_box_rotated_bounds(&layout_box, rotation, &layout_box);
65 return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box);
66}
67
42static void render_surface(struct wlr_surface *surface, 68static void render_surface(struct wlr_surface *surface,
43 struct wlr_output *wlr_output, struct timespec *when, 69 struct wlr_output *wlr_output, struct timespec *when,
44 double lx, double ly, float rotation) { 70 double lx, double ly, float rotation) {
@@ -48,29 +74,21 @@ static void render_surface(struct wlr_surface *surface,
48 if (!wlr_surface_has_buffer(surface)) { 74 if (!wlr_surface_has_buffer(surface)) {
49 return; 75 return;
50 } 76 }
77
51 struct wlr_output_layout *layout = root_container.sway_root->output_layout; 78 struct wlr_output_layout *layout = root_container.sway_root->output_layout;
52 int width = surface->current->width; 79
53 int height = surface->current->height; 80 struct wlr_box box;
54 int render_width = width * wlr_output->scale; 81 bool intersects = surface_intersect_output(surface, layout, wlr_output,
55 int render_height = height * wlr_output->scale; 82 lx, ly, rotation, &box);
56 int owidth, oheight; 83 if (intersects) {
57 wlr_output_effective_resolution(wlr_output, &owidth, &oheight);
58
59 // FIXME: view coords are inconsistently assumed to be in output or layout coords
60 struct wlr_box layout_box = {
61 .x = lx + wlr_output->lx, .y = ly + wlr_output->ly,
62 .width = render_width, .height = render_height,
63 };
64 if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) {
65 struct wlr_box render_box = {
66 .x = lx, .y = ly,
67 .width = render_width, .height = render_height
68 };
69 float matrix[9]; 84 float matrix[9];
70 wlr_matrix_project_box(matrix, &render_box, surface->current->transform, 85 enum wl_output_transform transform =
71 0, wlr_output->transform_matrix); 86 wlr_output_transform_invert(surface->current->transform);
72 wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 87 wlr_matrix_project_box(matrix, &box, transform, rotation,
73 1.0f); // TODO: configurable alpha 88 wlr_output->transform_matrix);
89
90 // TODO: configurable alpha
91 wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 1.0f);
74 92
75 wlr_surface_send_frame_done(surface, when); 93 wlr_surface_send_frame_done(surface, when);
76 } 94 }
@@ -80,9 +98,8 @@ static void render_surface(struct wlr_surface *surface,
80 struct wlr_surface_state *state = subsurface->surface->current; 98 struct wlr_surface_state *state = subsurface->surface->current;
81 double sx = state->subsurface_position.x; 99 double sx = state->subsurface_position.x;
82 double sy = state->subsurface_position.y; 100 double sy = state->subsurface_position.y;
83 double sw = state->buffer_width / state->scale; 101 rotate_child_position(&sx, &sy, state->width, state->height,
84 double sh = state->buffer_height / state->scale; 102 surface->current->width, surface->current->height, rotation);
85 rotate_child_position(&sx, &sy, sw, sh, width, height, rotation);
86 103
87 render_surface(subsurface->surface, wlr_output, when, 104 render_surface(subsurface->surface, wlr_output, when,
88 lx + sx, ly + sy, rotation); 105 lx + sx, ly + sy, rotation);
@@ -243,15 +260,15 @@ static void render_output(struct sway_output *output, struct timespec *when,
243 container_descendants(workspace, C_VIEW, render_view, &rdata); 260 container_descendants(workspace, C_VIEW, render_view, &rdata);
244 261
245 // render unmanaged views on top 262 // render unmanaged views on top
246 struct sway_view *view; 263 struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged;
247 wl_list_for_each(view, &root_container.sway_root->unmanaged_views, 264 struct sway_xwayland_unmanaged *sway_surface;
248 unmanaged_view_link) { 265 wl_list_for_each(sway_surface, unmanaged, link) {
249 if (view->type != SWAY_XWAYLAND_VIEW) { 266 struct wlr_xwayland_surface *xsurface =
267 sway_surface->wlr_xwayland_surface;
268 if (xsurface->surface == NULL) {
250 continue; 269 continue;
251 } 270 }
252 271
253 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
254
255 const struct wlr_box view_box = { 272 const struct wlr_box view_box = {
256 .x = xsurface->x, 273 .x = xsurface->x,
257 .y = xsurface->y, 274 .y = xsurface->y,
@@ -263,7 +280,7 @@ static void render_output(struct sway_output *output, struct timespec *when,
263 continue; 280 continue;
264 } 281 }
265 282
266 render_surface(view->surface, wlr_output, &output->last_frame, 283 render_surface(xsurface->surface, wlr_output, &output->last_frame,
267 view_box.x - output_box->x, view_box.y - output_box->y, 0); 284 view_box.x - output_box->x, view_box.y - output_box->y, 0);
268 } 285 }
269 286
@@ -341,6 +358,12 @@ static void handle_transform(struct wl_listener *listener, void *data) {
341 arrange_windows(output->swayc, -1, -1); 358 arrange_windows(output->swayc, -1, -1);
342} 359}
343 360
361static void handle_scale(struct wl_listener *listener, void *data) {
362 struct sway_output *output = wl_container_of(listener, output, scale);
363 arrange_layers(output);
364 arrange_windows(output->swayc, -1, -1);
365}
366
344void handle_new_output(struct wl_listener *listener, void *data) { 367void handle_new_output(struct wl_listener *listener, void *data) {
345 struct sway_server *server = wl_container_of(listener, server, new_output); 368 struct sway_server *server = wl_container_of(listener, server, new_output);
346 struct wlr_output *wlr_output = data; 369 struct wlr_output *wlr_output = data;
@@ -381,6 +404,8 @@ void handle_new_output(struct wl_listener *listener, void *data) {
381 output->mode.notify = handle_mode; 404 output->mode.notify = handle_mode;
382 wl_signal_add(&wlr_output->events.transform, &output->transform); 405 wl_signal_add(&wlr_output->events.transform, &output->transform);
383 output->transform.notify = handle_transform; 406 output->transform.notify = handle_transform;
407 wl_signal_add(&wlr_output->events.scale, &output->scale);
408 output->scale.notify = handle_scale;
384 409
385 wl_signal_add(&output->damage->events.frame, &output->damage_frame); 410 wl_signal_add(&output->damage->events.frame, &output->damage_frame);
386 output->damage_frame.notify = damage_handle_frame; 411 output->damage_frame.notify = damage_handle_frame;
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c
index c44fcf27..6528a397 100644
--- a/sway/desktop/wl_shell.c
+++ b/sway/desktop/wl_shell.c
@@ -30,28 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
30 } 30 }
31} 31}
32 32
33static void set_size(struct sway_view *view, int width, int height) { 33static void configure(struct sway_view *view, double ox, double oy, int width,
34 int height) {
34 if (!assert_wl_shell(view)) { 35 if (!assert_wl_shell(view)) {
35 return; 36 return;
36 } 37 }
38 view_update_position(view, ox, oy);
37 view->sway_wl_shell_surface->pending_width = width; 39 view->sway_wl_shell_surface->pending_width = width;
38 view->sway_wl_shell_surface->pending_height = height; 40 view->sway_wl_shell_surface->pending_height = height;
39 wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); 41 wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height);
40} 42}
41 43
42static void set_position(struct sway_view *view, double ox, double oy) { 44static void _close(struct sway_view *view) {
43 if (!assert_wl_shell(view)) {
44 return;
45 }
46 view->swayc->x = ox;
47 view->swayc->y = oy;
48}
49
50static void set_activated(struct sway_view *view, bool activated) {
51 // no way to activate wl_shell
52}
53
54static void close(struct sway_view *view) {
55 if (!assert_wl_shell(view)) { 45 if (!assert_wl_shell(view)) {
56 return; 46 return;
57 } 47 }
@@ -59,14 +49,20 @@ static void close(struct sway_view *view) {
59 wl_client_destroy(view->wlr_wl_shell_surface->client); 49 wl_client_destroy(view->wlr_wl_shell_surface->client);
60} 50}
61 51
52static const struct sway_view_impl view_impl = {
53 .get_prop = get_prop,
54 .configure = configure,
55 .close = _close,
56};
57
62static void handle_commit(struct wl_listener *listener, void *data) { 58static void handle_commit(struct wl_listener *listener, void *data) {
63 struct sway_wl_shell_surface *sway_surface = 59 struct sway_wl_shell_surface *sway_surface =
64 wl_container_of(listener, sway_surface, commit); 60 wl_container_of(listener, sway_surface, commit);
65 struct sway_view *view = sway_surface->view; 61 struct sway_view *view = sway_surface->view;
66 // NOTE: We intentionally discard the view's desired width here 62 // NOTE: We intentionally discard the view's desired width here
67 // TODO: Let floating views do whatever 63 // TODO: Let floating views do whatever
68 view->width = sway_surface->pending_width; 64 view_update_size(view, sway_surface->pending_width,
69 view->height = sway_surface->pending_height; 65 sway_surface->pending_height);
70 view_damage_from(view); 66 view_damage_from(view);
71} 67}
72 68
@@ -75,15 +71,13 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
75 wl_container_of(listener, sway_surface, destroy); 71 wl_container_of(listener, sway_surface, destroy);
76 wl_list_remove(&sway_surface->commit.link); 72 wl_list_remove(&sway_surface->commit.link);
77 wl_list_remove(&sway_surface->destroy.link); 73 wl_list_remove(&sway_surface->destroy.link);
78 struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); 74 view_destroy(sway_surface->view);
79 free(sway_surface->view);
80 free(sway_surface); 75 free(sway_surface);
81 arrange_windows(parent, -1, -1);
82} 76}
83 77
84void handle_wl_shell_surface(struct wl_listener *listener, void *data) { 78void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
85 struct sway_server *server = wl_container_of( 79 struct sway_server *server = wl_container_of(listener, server,
86 listener, server, wl_shell_surface); 80 wl_shell_surface);
87 struct wlr_wl_shell_surface *shell_surface = data; 81 struct wlr_wl_shell_surface *shell_surface = data;
88 82
89 if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { 83 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) {
103 return; 97 return;
104 } 98 }
105 99
106 struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); 100 struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW, &view_impl);
107 if (!sway_assert(sway_view, "Failed to allocate view!")) { 101 if (!sway_assert(view, "Failed to allocate view")) {
108 return; 102 return;
109 } 103 }
110 sway_view->type = SWAY_WL_SHELL_VIEW; 104 view->wlr_wl_shell_surface = shell_surface;
111 sway_view->iface.get_prop = get_prop; 105 view->sway_wl_shell_surface = sway_surface;
112 sway_view->iface.set_size = set_size; 106 sway_surface->view = view;
113 sway_view->iface.set_position = set_position;
114 sway_view->iface.set_activated = set_activated;
115 sway_view->iface.close = close;
116 sway_view->wlr_wl_shell_surface = shell_surface;
117 sway_view->sway_wl_shell_surface = sway_surface;
118 sway_view->surface = shell_surface->surface;
119 sway_surface->view = sway_view;
120 107
121 // TODO: 108 // TODO:
122 // - Wire up listeners 109 // - Wire up listeners
@@ -132,11 +119,5 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
132 sway_surface->destroy.notify = handle_destroy; 119 sway_surface->destroy.notify = handle_destroy;
133 wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); 120 wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy);
134 121
135 struct sway_seat *seat = input_manager_current_seat(input_manager); 122 view_map(view, shell_surface->surface);
136 struct sway_container *focus = seat_get_focus_inactive(seat, &root_container);
137 struct sway_container *cont = container_view_create(focus, sway_view);
138 sway_view->swayc = cont;
139
140 arrange_windows(cont->parent, -1, -1);
141 input_manager_set_focus(input_manager, cont);
142} 123}
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index cffe83fb..49305b39 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -30,23 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
30 } 30 }
31} 31}
32 32
33static void set_size(struct sway_view *view, int width, int height) { 33static void configure(struct sway_view *view, double ox, double oy, int width,
34 int height) {
34 if (!assert_xdg(view)) { 35 if (!assert_xdg(view)) {
35 return; 36 return;
36 } 37 }
38
39 view_update_position(view, ox, oy);
37 view->sway_xdg_surface_v6->pending_width = width; 40 view->sway_xdg_surface_v6->pending_width = width;
38 view->sway_xdg_surface_v6->pending_height = height; 41 view->sway_xdg_surface_v6->pending_height = height;
39 wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); 42 wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height);
40} 43}
41 44
42static void set_position(struct sway_view *view, double ox, double oy) {
43 if (!assert_xdg(view)) {
44 return;
45 }
46 view->swayc->x = ox;
47 view->swayc->y = oy;
48}
49
50static void set_activated(struct sway_view *view, bool activated) { 45static void set_activated(struct sway_view *view, bool activated) {
51 if (!assert_xdg(view)) { 46 if (!assert_xdg(view)) {
52 return; 47 return;
@@ -57,7 +52,7 @@ static void set_activated(struct sway_view *view, bool activated) {
57 } 52 }
58} 53}
59 54
60static void close(struct sway_view *view) { 55static void _close(struct sway_view *view) {
61 if (!assert_xdg(view)) { 56 if (!assert_xdg(view)) {
62 return; 57 return;
63 } 58 }
@@ -67,6 +62,13 @@ static void close(struct sway_view *view) {
67 } 62 }
68} 63}
69 64
65static const struct sway_view_impl view_impl = {
66 .get_prop = get_prop,
67 .configure = configure,
68 .set_activated = set_activated,
69 .close = _close,
70};
71
70static void handle_commit(struct wl_listener *listener, void *data) { 72static void handle_commit(struct wl_listener *listener, void *data) {
71 struct sway_xdg_surface_v6 *sway_surface = 73 struct sway_xdg_surface_v6 *sway_surface =
72 wl_container_of(listener, sway_surface, commit); 74 wl_container_of(listener, sway_surface, commit);
@@ -74,37 +76,22 @@ static void handle_commit(struct wl_listener *listener, void *data) {
74 // NOTE: We intentionally discard the view's desired width here 76 // NOTE: We intentionally discard the view's desired width here
75 // TODO: Store this for restoration when moving to floating plane 77 // TODO: Store this for restoration when moving to floating plane
76 // TODO: Let floating views do whatever 78 // TODO: Let floating views do whatever
77 view->width = sway_surface->pending_width; 79 view_update_size(view, sway_surface->pending_width,
78 view->height = sway_surface->pending_height; 80 sway_surface->pending_height);
79 view_damage_from(view); 81 view_damage_from(view);
80} 82}
81 83
82static void handle_unmap(struct wl_listener *listener, void *data) { 84static void handle_unmap(struct wl_listener *listener, void *data) {
83 struct sway_xdg_surface_v6 *sway_surface = 85 struct sway_xdg_surface_v6 *sway_surface =
84 wl_container_of(listener, sway_surface, unmap); 86 wl_container_of(listener, sway_surface, unmap);
85 view_damage_whole(sway_surface->view); 87 view_unmap(sway_surface->view);
86 container_view_destroy(sway_surface->view->swayc);
87 sway_surface->view->swayc = NULL;
88 sway_surface->view->surface = NULL;
89} 88}
90 89
91static void handle_map(struct wl_listener *listener, void *data) { 90static void handle_map(struct wl_listener *listener, void *data) {
92 struct sway_xdg_surface_v6 *sway_surface = 91 struct sway_xdg_surface_v6 *sway_surface =
93 wl_container_of(listener, sway_surface, map); 92 wl_container_of(listener, sway_surface, map);
94 struct sway_view *view = sway_surface->view; 93 struct sway_view *view = sway_surface->view;
95 94 view_map(view, view->wlr_xdg_surface_v6->surface);
96 sway_surface->view->surface = view->wlr_xdg_surface_v6->surface;
97
98 container_view_destroy(view->swayc);
99
100 struct sway_seat *seat = input_manager_current_seat(input_manager);
101 struct sway_container *focus = seat_get_focus_inactive(seat, &root_container);
102 struct sway_container *cont = container_view_create(focus, view);
103 view->swayc = cont;
104 arrange_windows(cont->parent, -1, -1);
105 input_manager_set_focus(input_manager, cont);
106
107 view_damage_whole(sway_surface->view);
108} 95}
109 96
110static void handle_destroy(struct wl_listener *listener, void *data) { 97static void handle_destroy(struct wl_listener *listener, void *data) {
@@ -112,8 +99,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
112 wl_container_of(listener, sway_xdg_surface, destroy); 99 wl_container_of(listener, sway_xdg_surface, destroy);
113 wl_list_remove(&sway_xdg_surface->commit.link); 100 wl_list_remove(&sway_xdg_surface->commit.link);
114 wl_list_remove(&sway_xdg_surface->destroy.link); 101 wl_list_remove(&sway_xdg_surface->destroy.link);
115 container_view_destroy(sway_xdg_surface->view->swayc); 102 wl_list_remove(&sway_xdg_surface->map.link);
116 free(sway_xdg_surface->view); 103 wl_list_remove(&sway_xdg_surface->unmap.link);
104 view_destroy(sway_xdg_surface->view);
117 free(sway_xdg_surface); 105 free(sway_xdg_surface);
118} 106}
119 107
@@ -138,23 +126,16 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
138 return; 126 return;
139 } 127 }
140 128
141 struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); 129 struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW, &view_impl);
142 if (!sway_assert(sway_view, "Failed to allocate view!")) { 130 if (!sway_assert(view, "Failed to allocate view")) {
143 return; 131 return;
144 } 132 }
145 sway_view->type = SWAY_XDG_SHELL_V6_VIEW; 133 view->wlr_xdg_surface_v6 = xdg_surface;
146 sway_view->iface.get_prop = get_prop; 134 view->sway_xdg_surface_v6 = sway_surface;
147 sway_view->iface.set_size = set_size; 135 sway_surface->view = view;
148 sway_view->iface.set_position = set_position;
149 sway_view->iface.set_activated = set_activated;
150 sway_view->iface.close = close;
151 sway_view->wlr_xdg_surface_v6 = xdg_surface;
152 sway_view->sway_xdg_surface_v6 = sway_surface;
153 sway_surface->view = sway_view;
154 136
155 // TODO: 137 // TODO:
156 // - Look up pid and open on appropriate workspace 138 // - Look up pid and open on appropriate workspace
157 // - Set new view to maximized so it behaves nicely
158 // - Criteria 139 // - Criteria
159 140
160 sway_surface->commit.notify = handle_commit; 141 sway_surface->commit.notify = handle_commit;
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 17f827d9..bfef68cf 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -14,6 +14,33 @@
14#include "sway/input/input-manager.h" 14#include "sway/input/input-manager.h"
15#include "log.h" 15#include "log.h"
16 16
17static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
18 struct sway_xwayland_unmanaged *sway_surface =
19 wl_container_of(listener, sway_surface, destroy);
20 wl_list_remove(&sway_surface->destroy.link);
21 wl_list_remove(&sway_surface->link);
22 free(sway_surface);
23}
24
25static void create_unmanaged(struct wlr_xwayland_surface *xsurface) {
26 struct sway_xwayland_unmanaged *sway_surface =
27 calloc(1, sizeof(struct sway_xwayland_unmanaged));
28 if (!sway_assert(sway_surface, "Failed to allocate surface")) {
29 return;
30 }
31
32 sway_surface->wlr_xwayland_surface = xsurface;
33
34 wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy);
35 sway_surface->destroy.notify = unmanaged_handle_destroy;
36
37 wl_list_insert(&root_container.sway_root->xwayland_unmanaged,
38 &sway_surface->link);
39
40 // TODO: damage tracking
41}
42
43
17static bool assert_xwayland(struct sway_view *view) { 44static bool assert_xwayland(struct sway_view *view) {
18 return sway_assert(view->type == SWAY_XWAYLAND_VIEW, 45 return sway_assert(view->type == SWAY_XWAYLAND_VIEW,
19 "Expected xwayland view!"); 46 "Expected xwayland view!");
@@ -33,22 +60,13 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
33 } 60 }
34} 61}
35 62
36static void set_size(struct sway_view *view, int width, int height) { 63static void configure(struct sway_view *view, double ox, double oy, int width,
64 int height) {
37 if (!assert_xwayland(view)) { 65 if (!assert_xwayland(view)) {
38 return; 66 return;
39 } 67 }
40 view->sway_xwayland_surface->pending_width = width;
41 view->sway_xwayland_surface->pending_height = height;
42
43 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 68 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
44 wlr_xwayland_surface_configure(xsurface, xsurface->x, xsurface->y,
45 width, height);
46}
47 69
48static void set_position(struct sway_view *view, double ox, double oy) {
49 if (!assert_xwayland(view)) {
50 return;
51 }
52 struct sway_container *output = container_parent(view->swayc, C_OUTPUT); 70 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
53 if (!sway_assert(output, "view must be within tree to set position")) { 71 if (!sway_assert(output, "view must be within tree to set position")) {
54 return; 72 return;
@@ -64,13 +82,12 @@ static void set_position(struct sway_view *view, double ox, double oy) {
64 return; 82 return;
65 } 83 }
66 84
67 view->swayc->x = ox; 85 view_update_position(view, ox, oy);
68 view->swayc->y = oy;
69 86
70 wlr_xwayland_surface_configure(view->wlr_xwayland_surface, 87 view->sway_xwayland_surface->pending_width = width;
71 ox + loutput->x, oy + loutput->y, 88 view->sway_xwayland_surface->pending_height = height;
72 view->wlr_xwayland_surface->width, 89 wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y,
73 view->wlr_xwayland_surface->height); 90 width, height);
74} 91}
75 92
76static void set_activated(struct sway_view *view, bool activated) { 93static void set_activated(struct sway_view *view, bool activated) {
@@ -81,77 +98,58 @@ static void set_activated(struct sway_view *view, bool activated) {
81 wlr_xwayland_surface_activate(surface, activated); 98 wlr_xwayland_surface_activate(surface, activated);
82} 99}
83 100
84static void close_view(struct sway_view *view) { 101static void _close(struct sway_view *view) {
85 if (!assert_xwayland(view)) { 102 if (!assert_xwayland(view)) {
86 return; 103 return;
87 } 104 }
88 wlr_xwayland_surface_close(view->wlr_xwayland_surface); 105 wlr_xwayland_surface_close(view->wlr_xwayland_surface);
89} 106}
90 107
108static const struct sway_view_impl view_impl = {
109 .get_prop = get_prop,
110 .configure = configure,
111 .set_activated = set_activated,
112 .close = _close,
113};
114
91static void handle_commit(struct wl_listener *listener, void *data) { 115static void handle_commit(struct wl_listener *listener, void *data) {
92 struct sway_xwayland_surface *sway_surface = 116 struct sway_xwayland_surface *sway_surface =
93 wl_container_of(listener, sway_surface, commit); 117 wl_container_of(listener, sway_surface, commit);
94 struct sway_view *view = sway_surface->view; 118 struct sway_view *view = sway_surface->view;
95 // NOTE: We intentionally discard the view's desired width here 119 // NOTE: We intentionally discard the view's desired width here
96 // TODO: Let floating views do whatever 120 // TODO: Let floating views do whatever
97 view->width = sway_surface->pending_width; 121 view_update_size(view, sway_surface->pending_width,
98 view->height = sway_surface->pending_height; 122 sway_surface->pending_height);
99 view_damage_from(view); 123 view_damage_from(view);
100} 124}
101 125
102static void handle_destroy(struct wl_listener *listener, void *data) { 126static void handle_destroy(struct wl_listener *listener, void *data) {
103 struct sway_xwayland_surface *sway_surface = 127 struct sway_xwayland_surface *sway_surface =
104 wl_container_of(listener, sway_surface, destroy); 128 wl_container_of(listener, sway_surface, destroy);
105
106 wl_list_remove(&sway_surface->commit.link); 129 wl_list_remove(&sway_surface->commit.link);
107 wl_list_remove(&sway_surface->destroy.link); 130 wl_list_remove(&sway_surface->destroy.link);
108 wl_list_remove(&sway_surface->request_configure.link); 131 wl_list_remove(&sway_surface->request_configure.link);
109 wl_list_remove(&sway_surface->view->unmanaged_view_link); 132 wl_list_remove(&sway_surface->map.link);
110 container_view_destroy(sway_surface->view->swayc); 133 wl_list_remove(&sway_surface->unmap.link);
111 sway_surface->view->swayc = NULL; 134 view_destroy(sway_surface->view);
112 sway_surface->view->surface = NULL; 135 free(sway_surface);
113} 136}
114 137
115static void handle_unmap(struct wl_listener *listener, void *data) { 138static void handle_unmap(struct wl_listener *listener, void *data) {
116 struct sway_xwayland_surface *sway_surface = 139 struct sway_xwayland_surface *sway_surface =
117 wl_container_of(listener, sway_surface, unmap); 140 wl_container_of(listener, sway_surface, unmap);
118 view_damage_whole(sway_surface->view); 141 view_unmap(sway_surface->view);
119 wl_list_remove(&sway_surface->view->unmanaged_view_link);
120 wl_list_init(&sway_surface->view->unmanaged_view_link);
121 container_view_destroy(sway_surface->view->swayc);
122 sway_surface->view->swayc = NULL;
123 sway_surface->view->surface = NULL;
124} 142}
125 143
126static void handle_map(struct wl_listener *listener, void *data) { 144static void handle_map(struct wl_listener *listener, void *data) {
127 struct sway_xwayland_surface *sway_surface = 145 struct sway_xwayland_surface *sway_surface =
128 wl_container_of(listener, sway_surface, map); 146 wl_container_of(listener, sway_surface, map);
129 struct wlr_xwayland_surface *xsurface = data; 147 struct wlr_xwayland_surface *xsurface = data;
130 148 struct sway_view *view = sway_surface->view;
131 sway_surface->view->surface = xsurface->surface;
132 149
133 // put it back into the tree 150 // put it back into the tree
134 if (wlr_xwayland_surface_is_unmanaged(xsurface) || 151 wlr_xwayland_surface_set_maximized(xsurface, true);
135 xsurface->override_redirect) { 152 view_map(view, xsurface->surface);
136 wl_list_remove(&sway_surface->view->unmanaged_view_link);
137 wl_list_insert(&root_container.sway_root->unmanaged_views,
138 &sway_surface->view->unmanaged_view_link);
139 } else {
140 struct sway_view *view = sway_surface->view;
141 container_view_destroy(view->swayc);
142
143 wlr_xwayland_surface_set_maximized(xsurface, true);
144
145 struct sway_seat *seat = input_manager_current_seat(input_manager);
146 struct sway_container *focus = seat_get_focus_inactive(seat,
147 &root_container);
148 struct sway_container *cont = container_view_create(focus, view);
149 view->swayc = cont;
150 arrange_windows(cont->parent, -1, -1);
151 input_manager_set_focus(input_manager, cont);
152 }
153
154 view_damage_whole(sway_surface->view);
155} 153}
156 154
157static void handle_request_configure(struct wl_listener *listener, void *data) { 155static void handle_request_configure(struct wl_listener *listener, void *data) {
@@ -171,34 +169,32 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
171 listener, server, xwayland_surface); 169 listener, server, xwayland_surface);
172 struct wlr_xwayland_surface *xsurface = data; 170 struct wlr_xwayland_surface *xsurface = data;
173 171
172 if (wlr_xwayland_surface_is_unmanaged(xsurface) ||
173 xsurface->override_redirect) {
174 wlr_log(L_DEBUG, "New xwayland unmanaged surface");
175 create_unmanaged(xsurface);
176 return;
177 }
178
174 wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", 179 wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'",
175 xsurface->title, xsurface->class); 180 xsurface->title, xsurface->class);
176 181
177 struct sway_xwayland_surface *sway_surface = 182 struct sway_xwayland_surface *sway_surface =
178 calloc(1, sizeof(struct sway_xwayland_surface)); 183 calloc(1, sizeof(struct sway_xwayland_surface));
179 if (!sway_assert(sway_surface, "Failed to allocate surface!")) { 184 if (!sway_assert(sway_surface, "Failed to allocate surface")) {
180 return; 185 return;
181 } 186 }
182 187
183 struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); 188 struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW, &view_impl);
184 if (!sway_assert(sway_view, "Failed to allocate view!")) { 189 if (!sway_assert(view, "Failed to allocate view")) {
185 return; 190 return;
186 } 191 }
187 sway_view->type = SWAY_XWAYLAND_VIEW; 192 view->wlr_xwayland_surface = xsurface;
188 sway_view->iface.get_prop = get_prop; 193 view->sway_xwayland_surface = sway_surface;
189 sway_view->iface.set_size = set_size; 194 sway_surface->view = view;
190 sway_view->iface.set_position = set_position;
191 sway_view->iface.set_activated = set_activated;
192 sway_view->iface.close = close_view;
193 sway_view->wlr_xwayland_surface = xsurface;
194 sway_view->sway_xwayland_surface = sway_surface;
195 sway_surface->view = sway_view;
196
197 wl_list_init(&sway_view->unmanaged_view_link);
198 195
199 // TODO: 196 // TODO:
200 // - Look up pid and open on appropriate workspace 197 // - Look up pid and open on appropriate workspace
201 // - Set new view to maximized so it behaves nicely
202 // - Criteria 198 // - Criteria
203 199
204 wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); 200 wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit);
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 7d05e942..97b4473c 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -47,14 +47,15 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output,
47static struct sway_container *container_at_cursor(struct sway_cursor *cursor, 47static struct sway_container *container_at_cursor(struct sway_cursor *cursor,
48 struct wlr_surface **surface, double *sx, double *sy) { 48 struct wlr_surface **surface, double *sx, double *sy) {
49 // check for unmanaged views first 49 // check for unmanaged views first
50 struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views; 50 struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged;
51 struct sway_view *view; 51 struct sway_xwayland_unmanaged *sway_surface;
52 wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) { 52 wl_list_for_each_reverse(sway_surface, unmanaged, link) {
53 if (view->type != SWAY_XWAYLAND_VIEW) { 53 struct wlr_xwayland_surface *xsurface =
54 sway_surface->wlr_xwayland_surface;
55 if (xsurface->surface == NULL) {
54 continue; 56 continue;
55 } 57 }
56 58
57 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
58 struct wlr_box box = { 59 struct wlr_box box = {
59 .x = xsurface->x, 60 .x = xsurface->x,
60 .y = xsurface->y, 61 .y = xsurface->y,
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index 88463e3b..95a84d12 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -58,7 +58,7 @@ void layout_init(void) {
58 58
59 root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); 59 root_container.sway_root = calloc(1, sizeof(*root_container.sway_root));
60 root_container.sway_root->output_layout = wlr_output_layout_create(); 60 root_container.sway_root->output_layout = wlr_output_layout_create();
61 wl_list_init(&root_container.sway_root->unmanaged_views); 61 wl_list_init(&root_container.sway_root->xwayland_unmanaged);
62 wl_signal_init(&root_container.sway_root->events.new_container); 62 wl_signal_init(&root_container.sway_root->events.new_container);
63 63
64 root_container.sway_root->output_layout_change.notify = 64 root_container.sway_root->output_layout_change.notify =
@@ -288,7 +288,7 @@ void arrange_windows(struct sway_container *container,
288 { 288 {
289 container->width = width; 289 container->width = width;
290 container->height = height; 290 container->height = height;
291 view_set_size(container->sway_view, 291 view_configure(container->sway_view, container->x, container->y,
292 container->width, container->height); 292 container->width, container->height);
293 wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", 293 wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f",
294 container->width, container->height, 294 container->width, container->height,
@@ -349,8 +349,10 @@ static void apply_horiz_layout(struct sway_container *container,
349 wlr_log(L_DEBUG, 349 wlr_log(L_DEBUG,
350 "Calculating arrangement for %p:%d (will scale %f by %f)", 350 "Calculating arrangement for %p:%d (will scale %f by %f)",
351 child, child->type, width, scale); 351 child, child->type, width, scale);
352
352 if (child->type == C_VIEW) { 353 if (child->type == C_VIEW) {
353 view_set_position(child->sway_view, child_x, y); 354 view_configure(child->sway_view, child_x, y, child->width,
355 child->height);
354 } else { 356 } else {
355 child->x = child_x; 357 child->x = child_x;
356 child->y = y; 358 child->y = y;
@@ -406,7 +408,8 @@ void apply_vert_layout(struct sway_container *container,
406 "Calculating arrangement for %p:%d (will scale %f by %f)", 408 "Calculating arrangement for %p:%d (will scale %f by %f)",
407 child, child->type, height, scale); 409 child, child->type, height, scale);
408 if (child->type == C_VIEW) { 410 if (child->type == C_VIEW) {
409 view_set_position(child->sway_view, x, child_y); 411 view_configure(child->sway_view, x, child_y, child->width,
412 child->height);
410 } else { 413 } else {
411 child->x = x; 414 child->x = x;
412 child->y = child_y; 415 child->y = child_y;
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 2331dc2b..0509db23 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -30,6 +30,7 @@ struct sway_container *container_output_destroy(struct sway_container *output) {
30 wl_list_remove(&output->sway_output->destroy.link); 30 wl_list_remove(&output->sway_output->destroy.link);
31 wl_list_remove(&output->sway_output->mode.link); 31 wl_list_remove(&output->sway_output->mode.link);
32 wl_list_remove(&output->sway_output->transform.link); 32 wl_list_remove(&output->sway_output->transform.link);
33 wl_list_remove(&output->sway_output->scale.link);
33 34
34 wl_list_remove(&output->sway_output->damage_destroy.link); 35 wl_list_remove(&output->sway_output->damage_destroy.link);
35 wl_list_remove(&output->sway_output->damage_frame.link); 36 wl_list_remove(&output->sway_output->damage_frame.link);
diff --git a/sway/tree/view.c b/sway/tree/view.c
index b7d1a41b..09c804e4 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -1,3 +1,4 @@
1#include <stdlib.h>
1#include <wayland-server.h> 2#include <wayland-server.h>
2#include <wlr/types/wlr_output_layout.h> 3#include <wlr/types/wlr_output_layout.h>
3#include "log.h" 4#include "log.h"
@@ -6,82 +7,117 @@
6#include "sway/tree/layout.h" 7#include "sway/tree/layout.h"
7#include "sway/tree/view.h" 8#include "sway/tree/view.h"
8 9
10struct sway_view *view_create(enum sway_view_type type,
11 const struct sway_view_impl *impl) {
12 struct sway_view *view = calloc(1, sizeof(struct sway_view));
13 if (view == NULL) {
14 return NULL;
15 }
16 view->type = type;
17 view->impl = impl;
18 return view;
19}
20
21void view_destroy(struct sway_view *view) {
22 if (view == NULL) {
23 return;
24 }
25
26 if (view->surface != NULL) {
27 view_unmap(view);
28 }
29
30 container_view_destroy(view->swayc);
31 free(view);
32}
33
9const char *view_get_title(struct sway_view *view) { 34const char *view_get_title(struct sway_view *view) {
10 if (view->iface.get_prop) { 35 if (view->impl->get_prop) {
11 return view->iface.get_prop(view, VIEW_PROP_TITLE); 36 return view->impl->get_prop(view, VIEW_PROP_TITLE);
12 } 37 }
13 return NULL; 38 return NULL;
14} 39}
15 40
16const char *view_get_app_id(struct sway_view *view) { 41const char *view_get_app_id(struct sway_view *view) {
17 if (view->iface.get_prop) { 42 if (view->impl->get_prop) {
18 return view->iface.get_prop(view, VIEW_PROP_APP_ID); 43 return view->impl->get_prop(view, VIEW_PROP_APP_ID);
19 } 44 }
20 return NULL; 45 return NULL;
21} 46}
22 47
23const char *view_get_class(struct sway_view *view) { 48const char *view_get_class(struct sway_view *view) {
24 if (view->iface.get_prop) { 49 if (view->impl->get_prop) {
25 return view->iface.get_prop(view, VIEW_PROP_CLASS); 50 return view->impl->get_prop(view, VIEW_PROP_CLASS);
26 } 51 }
27 return NULL; 52 return NULL;
28} 53}
29 54
30const char *view_get_instance(struct sway_view *view) { 55const char *view_get_instance(struct sway_view *view) {
31 if (view->iface.get_prop) { 56 if (view->impl->get_prop) {
32 return view->iface.get_prop(view, VIEW_PROP_INSTANCE); 57 return view->impl->get_prop(view, VIEW_PROP_INSTANCE);
33 } 58 }
34 return NULL; 59 return NULL;
35} 60}
36 61
37void view_set_size(struct sway_view *view, int width, int height) { 62void view_configure(struct sway_view *view, double ox, double oy, int width,
38 if (view->iface.set_size) { 63 int height) {
39 struct wlr_box box = { 64 if (view->impl->configure) {
40 .x = view->swayc->x, 65 view->impl->configure(view, ox, oy, width, height);
41 .y = view->swayc->y,
42 .width = view->width,
43 .height = view->height,
44 };
45 view->iface.set_size(view, width, height);
46 view_update_outputs(view, &box);
47 } 66 }
48} 67}
49 68
50// TODO make view coordinates in layout coordinates 69void view_set_activated(struct sway_view *view, bool activated) {
51void view_set_position(struct sway_view *view, double ox, double oy) { 70 if (view->impl->set_activated) {
52 if (view->iface.set_position) { 71 view->impl->set_activated(view, activated);
53 struct wlr_box box = {
54 .x = view->swayc->x,
55 .y = view->swayc->y,
56 .width = view->width,
57 .height = view->height,
58 };
59 view->iface.set_position(view, ox, oy);
60 view_update_outputs(view, &box);
61 } 72 }
62} 73}
63 74
64void view_set_activated(struct sway_view *view, bool activated) { 75void view_close(struct sway_view *view) {
65 if (view->iface.set_activated) { 76 if (view->impl->close) {
66 view->iface.set_activated(view, activated); 77 view->impl->close(view);
67 } 78 }
68} 79}
69 80
70void view_close(struct sway_view *view) { 81struct sway_container *container_view_destroy(struct sway_container *view) {
71 if (view->iface.close) { 82 if (!view) {
72 view->iface.close(view); 83 return NULL;
73 } 84 }
85 wlr_log(L_DEBUG, "Destroying view '%s'", view->name);
86 struct sway_container *parent = container_destroy(view);
87 arrange_windows(parent, -1, -1);
88 return parent;
89}
90
91void view_damage_whole(struct sway_view *view) {
92 for (int i = 0; i < root_container.children->length; ++i) {
93 struct sway_container *cont = root_container.children->items[i];
94 if (cont->type == C_OUTPUT) {
95 output_damage_whole_view(cont->sway_output, view);
96 }
97 }
98}
99
100void view_damage_from(struct sway_view *view) {
101 // TODO
102 view_damage_whole(view);
103}
104
105static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) {
106 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
107
108 box->x = output->x + view->swayc->x;
109 box->y = output->y + view->swayc->y;
110 box->width = view->width;
111 box->height = view->height;
74} 112}
75 113
76void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { 114static void view_update_outputs(struct sway_view *view,
115 const struct wlr_box *before) {
116 struct wlr_box box;
117 view_get_layout_box(view, &box);
118
77 struct wlr_output_layout *output_layout = 119 struct wlr_output_layout *output_layout =
78 root_container.sway_root->output_layout; 120 root_container.sway_root->output_layout;
79 struct wlr_box box = {
80 .x = view->swayc->x,
81 .y = view->swayc->y,
82 .width = view->width,
83 .height = view->height,
84 };
85 struct wlr_output_layout_output *layout_output; 121 struct wlr_output_layout_output *layout_output;
86 wl_list_for_each(layout_output, &output_layout->outputs, link) { 122 wl_list_for_each(layout_output, &output_layout->outputs, link) {
87 bool intersected = before != NULL && wlr_output_layout_intersects( 123 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) {
97 } 133 }
98} 134}
99 135
100struct sway_container *container_view_destroy(struct sway_container *view) { 136void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
101 if (!view) { 137 if (!sway_assert(view->surface == NULL, "cannot map mapped view")) {
102 return NULL; 138 return;
103 } 139 }
104 wlr_log(L_DEBUG, "Destroying view '%s'", view->name); 140
105 struct sway_container *parent = container_destroy(view); 141 struct sway_seat *seat = input_manager_current_seat(input_manager);
106 arrange_windows(parent, -1, -1); 142 struct sway_container *focus = seat_get_focus_inactive(seat,
107 return parent; 143 &root_container);
144 struct sway_container *cont = container_view_create(focus, view);
145
146 view->surface = wlr_surface;
147 view->swayc = cont;
148
149 arrange_windows(cont->parent, -1, -1);
150 input_manager_set_focus(input_manager, cont);
151
152 view_damage_whole(view);
153 view_update_outputs(view, NULL);
108} 154}
109 155
110void view_damage_whole(struct sway_view *view) { 156void view_unmap(struct sway_view *view) {
111 struct sway_container *cont = NULL; 157 if (!sway_assert(view->surface != NULL, "cannot unmap unmapped view")) {
112 for (int i = 0; i < root_container.children->length; ++i) { 158 return;
113 cont = root_container.children->items[i];
114 if (cont->type == C_OUTPUT) {
115 output_damage_whole_view(cont->sway_output, view);
116 }
117 } 159 }
160
161 view_damage_whole(view);
162
163 container_view_destroy(view->swayc);
164
165 view->swayc = NULL;
166 view->surface = NULL;
118} 167}
119 168
120void view_damage_from(struct sway_view *view) { 169void view_update_position(struct sway_view *view, double ox, double oy) {
121 // TODO 170 if (view->swayc->x == ox && view->swayc->y == oy) {
171 return;
172 }
173
174 struct wlr_box box;
175 view_get_layout_box(view, &box);
176 view_damage_whole(view);
177 view->swayc->x = ox;
178 view->swayc->y = oy;
179 view_update_outputs(view, &box);
180 view_damage_whole(view);
181}
182
183void view_update_size(struct sway_view *view, int width, int height) {
184 if (view->width == width && view->height == height) {
185 return;
186 }
187
188 struct wlr_box box;
189 view_get_layout_box(view, &box);
190 view_damage_whole(view);
191 view->width = width;
192 view->height = height;
193 view_update_outputs(view, &box);
122 view_damage_whole(view); 194 view_damage_whole(view);
123} 195}