diff options
author | Drew DeVault <sir@cmpwn.com> | 2015-11-18 22:01:22 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2015-11-18 22:01:22 -0500 |
commit | 82db2a57a9ab171e77a0765df5dd0b2d92cb4f70 (patch) | |
tree | 024d67d41888e4a14d7e3e281d4115e7268797fd | |
parent | Fix warning about uninitialized variable (diff) | |
download | sway-82db2a57a9ab171e77a0765df5dd0b2d92cb4f70.tar.gz sway-82db2a57a9ab171e77a0765df5dd0b2d92cb4f70.tar.zst sway-82db2a57a9ab171e77a0765df5dd0b2d92cb4f70.zip |
Basic support for extensions in server and clients
-rw-r--r-- | CMakeLists.txt | 10 | ||||
-rw-r--r-- | include/client/client.h | 4 | ||||
-rw-r--r-- | include/extensions.h | 6 | ||||
-rw-r--r-- | protocols/desktop-shell.xml | 138 | ||||
-rw-r--r-- | sway/extensions.c | 32 | ||||
-rw-r--r-- | sway/main.c | 3 | ||||
-rw-r--r-- | swaybg/CMakeLists.txt | 2 | ||||
-rw-r--r-- | swaybg/main.c | 7 | ||||
-rw-r--r-- | wayland/client.c | 13 |
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) | |||
5 | set(CMAKE_C_FLAGS "-g") | 5 | set(CMAKE_C_FLAGS "-g") |
6 | set(CMAKE_C_STANDARD 99) | 6 | set(CMAKE_C_STANDARD 99) |
7 | SET(CMAKE_C_EXTENSIONS OFF) | 7 | SET(CMAKE_C_EXTENSIONS OFF) |
8 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") | 8 | set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/bin") |
9 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") | ||
9 | add_definitions("-Wall -Wextra -Wno-unused-parameter -D_GNU_SOURCE") | 10 | add_definitions("-Wall -Wextra -Wno-unused-parameter -D_GNU_SOURCE") |
10 | list(INSERT CMAKE_MODULE_PATH 0 | 11 | list(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) | |||
38 | find_package(WLC REQUIRED) | 39 | find_package(WLC REQUIRED) |
39 | find_package(A2X REQUIRED) | 40 | find_package(A2X REQUIRED) |
40 | find_package(PCRE REQUIRED) | 41 | find_package(PCRE REQUIRED) |
42 | find_package(Wayland REQUIRED) | ||
41 | find_package(JsonC REQUIRED) | 43 | find_package(JsonC REQUIRED) |
42 | 44 | ||
43 | FILE(GLOB sources ${PROJECT_SOURCE_DIR}/sway/*.c) | 45 | FILE(GLOB sources ${PROJECT_SOURCE_DIR}/sway/*.c) |
44 | FILE(GLOB common ${PROJECT_SOURCE_DIR}/common/*.c) | 46 | FILE(GLOB common ${PROJECT_SOURCE_DIR}/common/*.c) |
45 | 47 | ||
48 | include(Wayland) | ||
49 | WAYLAND_ADD_PROTOCOL_SERVER(proto-desktop-shell "${PROJECT_SOURCE_DIR}/protocols/desktop-shell.xml" desktop-shell) | ||
50 | |||
46 | include_directories( | 51 | include_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 | ||
53 | add_executable(sway | 59 | add_executable(sway |
54 | ${sources} | 60 | ${sources} |
55 | ${common} | 61 | ${common} |
62 | ${proto-desktop-shell} | ||
56 | ) | 63 | ) |
57 | 64 | ||
58 | target_link_libraries(sway | 65 | target_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 | ||
65 | install( | 73 | install( |
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 | ||
50 | struct client_state *client_setup(uint32_t width, uint32_t height); | 52 | struct client_state *client_setup(uint32_t width, uint32_t height, bool shell_surface); |
51 | void client_teardown(struct client_state *state); | 53 | void client_teardown(struct client_state *state); |
52 | int client_prerender(struct client_state *state); | 54 | int client_prerender(struct client_state *state); |
53 | int client_render(struct client_state *state); | 55 | int 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 | |||
4 | void 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 | |||
6 | static 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 | |||
11 | static struct desktop_shell_interface desktop_shell_implementation = { | ||
12 | .set_background = set_background, | ||
13 | }; | ||
14 | |||
15 | static 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 | |||
30 | void 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) | |||
7 | include(Wayland) | 7 | include(Wayland) |
8 | set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/../bin/) | 8 | set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/../bin/) |
9 | WAYLAND_ADD_PROTOCOL_CLIENT(proto-xdg-shell "${PROJECT_SOURCE_DIR}/../protocols/xdg-shell.xml" xdg-shell) | 9 | WAYLAND_ADD_PROTOCOL_CLIENT(proto-xdg-shell "${PROJECT_SOURCE_DIR}/../protocols/xdg-shell.xml" xdg-shell) |
10 | WAYLAND_ADD_PROTOCOL_CLIENT(proto-desktop-shell "${PROJECT_SOURCE_DIR}/../protocols/desktop-shell.xml" desktop-shell) | ||
10 | 11 | ||
11 | include_directories( | 12 | include_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 | ||
29 | TARGET_LINK_LIBRARIES(swaybg ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES} ${CAIRO_LIBRARIES} ${PANGO_LIBRARIES} m) | 31 | TARGET_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 | ||
15 | int main(int argc, char **argv) { | 16 | int 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 | ||
122 | struct client_state *client_setup(uint32_t width, uint32_t height) { | 125 | struct 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"); |