summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt10
-rw-r--r--include/client/client.h4
-rw-r--r--include/extensions.h6
-rw-r--r--protocols/desktop-shell.xml138
-rw-r--r--sway/extensions.c32
-rw-r--r--sway/main.c3
-rw-r--r--swaybg/CMakeLists.txt2
-rw-r--r--swaybg/main.c7
-rw-r--r--wayland/client.c13
9 files changed, 208 insertions, 7 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7be65a03..0e61946b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,8 @@ project(sway C)
5set(CMAKE_C_FLAGS "-g") 5set(CMAKE_C_FLAGS "-g")
6set(CMAKE_C_STANDARD 99) 6set(CMAKE_C_STANDARD 99)
7SET(CMAKE_C_EXTENSIONS OFF) 7SET(CMAKE_C_EXTENSIONS OFF)
8set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") 8set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/bin")
9set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
9add_definitions("-Wall -Wextra -Wno-unused-parameter -D_GNU_SOURCE") 10add_definitions("-Wall -Wextra -Wno-unused-parameter -D_GNU_SOURCE")
10list(INSERT CMAKE_MODULE_PATH 0 11list(INSERT CMAKE_MODULE_PATH 0
11 "${CMAKE_CURRENT_SOURCE_DIR}/CMake") 12 "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
@@ -38,21 +39,27 @@ find_package(XKBCommon REQUIRED)
38find_package(WLC REQUIRED) 39find_package(WLC REQUIRED)
39find_package(A2X REQUIRED) 40find_package(A2X REQUIRED)
40find_package(PCRE REQUIRED) 41find_package(PCRE REQUIRED)
42find_package(Wayland REQUIRED)
41find_package(JsonC REQUIRED) 43find_package(JsonC REQUIRED)
42 44
43FILE(GLOB sources ${PROJECT_SOURCE_DIR}/sway/*.c) 45FILE(GLOB sources ${PROJECT_SOURCE_DIR}/sway/*.c)
44FILE(GLOB common ${PROJECT_SOURCE_DIR}/common/*.c) 46FILE(GLOB common ${PROJECT_SOURCE_DIR}/common/*.c)
45 47
48include(Wayland)
49WAYLAND_ADD_PROTOCOL_SERVER(proto-desktop-shell "${PROJECT_SOURCE_DIR}/protocols/desktop-shell.xml" desktop-shell)
50
46include_directories( 51include_directories(
47 ${WLC_INCLUDE_DIRS} 52 ${WLC_INCLUDE_DIRS}
48 ${PCRE_INCLUDE_DIRS} 53 ${PCRE_INCLUDE_DIRS}
49 ${JSONC_INCLUDE_DIRS} 54 ${JSONC_INCLUDE_DIRS}
50 ${XKBCOMMON_INCLUDE_DIRS} 55 ${XKBCOMMON_INCLUDE_DIRS}
56 ${CMAKE_CURRENT_BINARY_DIR}
51) 57)
52 58
53add_executable(sway 59add_executable(sway
54 ${sources} 60 ${sources}
55 ${common} 61 ${common}
62 ${proto-desktop-shell}
56) 63)
57 64
58target_link_libraries(sway 65target_link_libraries(sway
@@ -60,6 +67,7 @@ target_link_libraries(sway
60 ${XKBCOMMON_LIBRARIES} 67 ${XKBCOMMON_LIBRARIES}
61 ${PCRE_LIBRARIES} 68 ${PCRE_LIBRARIES}
62 ${JSONC_LIBRARIES} 69 ${JSONC_LIBRARIES}
70 ${WAYLAND_SERVER_LIBRARIES}
63) 71)
64 72
65install( 73install(
diff --git a/include/client/client.h b/include/client/client.h
index b823235b..30ec25c0 100644
--- a/include/client/client.h
+++ b/include/client/client.h
@@ -2,6 +2,7 @@
2#define _CLIENT_H 2#define _CLIENT_H
3 3
4#include <wayland-client.h> 4#include <wayland-client.h>
5#include "wayland-desktop-shell-client-protocol.h"
5#include <cairo/cairo.h> 6#include <cairo/cairo.h>
6#include <pango/pangocairo.h> 7#include <pango/pangocairo.h>
7#include <stdbool.h> 8#include <stdbool.h>
@@ -41,13 +42,14 @@ struct client_state {
41 struct wl_surface *surface; 42 struct wl_surface *surface;
42 struct wl_shell_surface *shell_surface; 43 struct wl_shell_surface *shell_surface;
43 struct wl_callback *frame_cb; 44 struct wl_callback *frame_cb;
45 struct desktop_shell *desktop_shell;
44 struct cursor cursor; 46 struct cursor cursor;
45 uint32_t width, height; 47 uint32_t width, height;
46 cairo_t *cairo; 48 cairo_t *cairo;
47 list_t *outputs; 49 list_t *outputs;
48}; 50};
49 51
50struct client_state *client_setup(uint32_t width, uint32_t height); 52struct client_state *client_setup(uint32_t width, uint32_t height, bool shell_surface);
51void client_teardown(struct client_state *state); 53void client_teardown(struct client_state *state);
52int client_prerender(struct client_state *state); 54int client_prerender(struct client_state *state);
53int client_render(struct client_state *state); 55int client_render(struct client_state *state);
diff --git a/include/extensions.h b/include/extensions.h
new file mode 100644
index 00000000..e122c59a
--- /dev/null
+++ b/include/extensions.h
@@ -0,0 +1,6 @@
1#ifndef _SWAY_EXTENSIONS_H
2#define _SWAY_EXTENSIONS_H
3
4void register_extensions(void);
5
6#endif
diff --git a/protocols/desktop-shell.xml b/protocols/desktop-shell.xml
new file mode 100644
index 00000000..dd81574a
--- /dev/null
+++ b/protocols/desktop-shell.xml
@@ -0,0 +1,138 @@
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 <arg name="position" type="uint"/>
113 <description summary="set panel position">
114 Tell the shell which side of the screen the panel is
115 located. This is so that new windows do not overlap the panel
116 and maximized windows maximize properly.
117 </description>
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/sway/extensions.c b/sway/extensions.c
new file mode 100644
index 00000000..a37ceaa8
--- /dev/null
+++ b/sway/extensions.c
@@ -0,0 +1,32 @@
1#include <wlc/wlc.h>
2#include <wlc/wlc-wayland.h>
3#include "wayland-desktop-shell-server-protocol.h"
4#include "log.h"
5
6static void set_background(struct wl_client *client, struct wl_resource *resource,
7 struct wl_resource *output, struct wl_resource *surface) {
8 sway_log(L_DEBUG, "Surface requesting background for output");
9}
10
11static struct desktop_shell_interface desktop_shell_implementation = {
12 .set_background = set_background,
13};
14
15static void desktop_shell_bind(struct wl_client *client, void *data,
16 unsigned int version, unsigned int id) {
17 if (version > 1) {
18 // Unsupported version
19 return;
20 }
21
22 struct wl_resource *resource = wl_resource_create(client, &desktop_shell_interface, version, id);
23 if (!resource) {
24 wl_client_post_no_memory(client);
25 }
26
27 wl_resource_set_implementation(resource, &desktop_shell_implementation, NULL, NULL);
28}
29
30void register_extensions(void) {
31 wl_global_create(wlc_get_wl_display(), &desktop_shell_interface, 1, NULL, desktop_shell_bind);
32}
diff --git a/sway/main.c b/sway/main.c
index 4afbccbd..ebb45930 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -7,6 +7,7 @@
7#include <sys/un.h> 7#include <sys/un.h>
8#include <signal.h> 8#include <signal.h>
9#include <getopt.h> 9#include <getopt.h>
10#include "extensions.h"
10#include "layout.h" 11#include "layout.h"
11#include "stringop.h" 12#include "stringop.h"
12#include "config.h" 13#include "config.h"
@@ -73,6 +74,8 @@ int main(int argc, char **argv) {
73 if (!wlc_init(&interface, argc, argv)) { 74 if (!wlc_init(&interface, argc, argv)) {
74 return 1; 75 return 1;
75 } 76 }
77
78 register_extensions();
76 79
77 char *config_path = NULL; 80 char *config_path = NULL;
78 81
diff --git a/swaybg/CMakeLists.txt b/swaybg/CMakeLists.txt
index 7f0556df..d4de69de 100644
--- a/swaybg/CMakeLists.txt
+++ b/swaybg/CMakeLists.txt
@@ -7,6 +7,7 @@ find_package(Pango REQUIRED)
7include(Wayland) 7include(Wayland)
8set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/../bin/) 8set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/../bin/)
9WAYLAND_ADD_PROTOCOL_CLIENT(proto-xdg-shell "${PROJECT_SOURCE_DIR}/../protocols/xdg-shell.xml" xdg-shell) 9WAYLAND_ADD_PROTOCOL_CLIENT(proto-xdg-shell "${PROJECT_SOURCE_DIR}/../protocols/xdg-shell.xml" xdg-shell)
10WAYLAND_ADD_PROTOCOL_CLIENT(proto-desktop-shell "${PROJECT_SOURCE_DIR}/../protocols/desktop-shell.xml" desktop-shell)
10 11
11include_directories( 12include_directories(
12 ${WAYLAND_CLIENT_INCLUDE_DIR} 13 ${WAYLAND_CLIENT_INCLUDE_DIR}
@@ -24,6 +25,7 @@ add_executable(swaybg
24 ${wl_sources} 25 ${wl_sources}
25 ${common} 26 ${common}
26 ${proto-xdg-shell} 27 ${proto-xdg-shell}
28 ${proto-desktop-shell}
27) 29)
28 30
29TARGET_LINK_LIBRARIES(swaybg ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES} ${CAIRO_LIBRARIES} ${PANGO_LIBRARIES} m) 31TARGET_LINK_LIBRARIES(swaybg ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES} ${CAIRO_LIBRARIES} ${PANGO_LIBRARIES} m)
diff --git a/swaybg/main.c b/swaybg/main.c
index b4614ac0..8d95f60a 100644
--- a/swaybg/main.c
+++ b/swaybg/main.c
@@ -1,3 +1,4 @@
1#include "wayland-desktop-shell-client-protocol.h"
1#include <stdio.h> 2#include <stdio.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <wayland-client.h> 4#include <wayland-client.h>
@@ -14,12 +15,16 @@ void sway_terminate(void) {
14 15
15int main(int argc, char **argv) { 16int main(int argc, char **argv) {
16 init_log(L_INFO); 17 init_log(L_INFO);
17 if (!(state = client_setup(100, 100))) { 18 if (!(state = client_setup(100, 100, false))) {
18 return -1; 19 return -1;
19 } 20 }
21 if (!state->desktop_shell) {
22 sway_abort("swaybg requires the compositor to support the desktop-shell extension.");
23 }
20 struct output_state *output = state->outputs->items[0]; 24 struct output_state *output = state->outputs->items[0];
21 state->width = output->width; 25 state->width = output->width;
22 state->height = output->height; 26 state->height = output->height;
27 desktop_shell_set_background(state->desktop_shell, output->output, state->surface);
23 28
24 uint8_t r = 0, g = 0, b = 0; 29 uint8_t r = 0, g = 0, b = 0;
25 30
diff --git a/wayland/client.c b/wayland/client.c
index be93709b..ab8adc47 100644
--- a/wayland/client.c
+++ b/wayland/client.c
@@ -1,6 +1,7 @@
1#include <wayland-client.h> 1#include <wayland-client.h>
2#include <wayland-cursor.h> 2#include <wayland-cursor.h>
3#include "wayland-xdg-shell-client-protocol.h" 3#include "wayland-xdg-shell-client-protocol.h"
4#include "wayland-desktop-shell-client-protocol.h"
4#include <cairo/cairo.h> 5#include <cairo/cairo.h>
5#include <pango/pangocairo.h> 6#include <pango/pangocairo.h>
6#include <stdlib.h> 7#include <stdlib.h>
@@ -96,6 +97,8 @@ static void registry_global(void *data, struct wl_registry *registry,
96 ostate->output = output; 97 ostate->output = output;
97 wl_output_add_listener(output, &output_listener, ostate); 98 wl_output_add_listener(output, &output_listener, ostate);
98 list_add(state->outputs, ostate); 99 list_add(state->outputs, ostate);
100 } else if (strcmp(interface, desktop_shell_interface.name) == 0) {
101 state->desktop_shell = wl_registry_bind(registry, name, &desktop_shell_interface, version);
99 } 102 }
100} 103}
101 104
@@ -119,7 +122,7 @@ static const struct wl_shell_surface_listener surface_listener = {
119 .configure = shell_surface_configure 122 .configure = shell_surface_configure
120}; 123};
121 124
122struct client_state *client_setup(uint32_t width, uint32_t height) { 125struct client_state *client_setup(uint32_t width, uint32_t height, bool shell_surface) {
123 struct client_state *state = malloc(sizeof(struct client_state)); 126 struct client_state *state = malloc(sizeof(struct client_state));
124 memset(state, 0, sizeof(struct client_state)); 127 memset(state, 0, sizeof(struct client_state));
125 state->outputs = create_list(); 128 state->outputs = create_list();
@@ -140,9 +143,11 @@ struct client_state *client_setup(uint32_t width, uint32_t height) {
140 wl_registry_destroy(registry); 143 wl_registry_destroy(registry);
141 144
142 state->surface = wl_compositor_create_surface(state->compositor); 145 state->surface = wl_compositor_create_surface(state->compositor);
143 state->shell_surface = wl_shell_get_shell_surface(state->shell, state->surface); 146 if (shell_surface) {
144 wl_shell_surface_add_listener(state->shell_surface, &surface_listener, state); 147 state->shell_surface = wl_shell_get_shell_surface(state->shell, state->surface);
145 wl_shell_surface_set_toplevel(state->shell_surface); 148 wl_shell_surface_add_listener(state->shell_surface, &surface_listener, state);
149 wl_shell_surface_set_toplevel(state->shell_surface);
150 }
146 151
147 state->cursor.cursor_theme = wl_cursor_theme_load("default", 32, state->shm); // TODO: let you customize this 152 state->cursor.cursor_theme = wl_cursor_theme_load("default", 32, state->shm); // TODO: let you customize this
148 state->cursor.cursor = wl_cursor_theme_get_cursor(state->cursor.cursor_theme, "left_ptr"); 153 state->cursor.cursor = wl_cursor_theme_get_cursor(state->cursor.cursor_theme, "left_ptr");