diff options
-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) set(CMAKE_C_FLAGS "-g") set(CMAKE_C_STANDARD 99) SET(CMAKE_C_EXTENSIONS OFF) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") +set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/bin") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") add_definitions("-Wall -Wextra -Wno-unused-parameter -D_GNU_SOURCE") list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/CMake") @@ -38,21 +39,27 @@ find_package(XKBCommon REQUIRED) find_package(WLC REQUIRED) find_package(A2X REQUIRED) find_package(PCRE REQUIRED) +find_package(Wayland REQUIRED) find_package(JsonC REQUIRED) FILE(GLOB sources ${PROJECT_SOURCE_DIR}/sway/*.c) FILE(GLOB common ${PROJECT_SOURCE_DIR}/common/*.c) +include(Wayland) +WAYLAND_ADD_PROTOCOL_SERVER(proto-desktop-shell "${PROJECT_SOURCE_DIR}/protocols/desktop-shell.xml" desktop-shell) + include_directories( ${WLC_INCLUDE_DIRS} ${PCRE_INCLUDE_DIRS} ${JSONC_INCLUDE_DIRS} ${XKBCOMMON_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} ) add_executable(sway ${sources} ${common} + ${proto-desktop-shell} ) target_link_libraries(sway @@ -60,6 +67,7 @@ target_link_libraries(sway ${XKBCOMMON_LIBRARIES} ${PCRE_LIBRARIES} ${JSONC_LIBRARIES} + ${WAYLAND_SERVER_LIBRARIES} ) 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 @@ #define _CLIENT_H #include <wayland-client.h> +#include "wayland-desktop-shell-client-protocol.h" #include <cairo/cairo.h> #include <pango/pangocairo.h> #include <stdbool.h> @@ -41,13 +42,14 @@ struct client_state { struct wl_surface *surface; struct wl_shell_surface *shell_surface; struct wl_callback *frame_cb; + struct desktop_shell *desktop_shell; struct cursor cursor; uint32_t width, height; cairo_t *cairo; list_t *outputs; }; -struct client_state *client_setup(uint32_t width, uint32_t height); +struct client_state *client_setup(uint32_t width, uint32_t height, bool shell_surface); void client_teardown(struct client_state *state); int client_prerender(struct client_state *state); 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 @@ +#ifndef _SWAY_EXTENSIONS_H +#define _SWAY_EXTENSIONS_H + +void register_extensions(void); + +#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 @@ +<protocol name="desktop"> + + <interface name="desktop_shell" version="3"> + <description summary="create desktop widgets and helpers"> + Traditional user interfaces can rely on this interface to define the + foundations of typical desktops. Currently it's possible to set up + background, panels and locking surfaces. + </description> + + <request name="set_background"> + <arg name="output" type="object" interface="wl_output"/> + <arg name="surface" type="object" interface="wl_surface"/> + </request> + + <request name="set_panel"> + <arg name="output" type="object" interface="wl_output"/> + <arg name="surface" type="object" interface="wl_surface"/> + </request> + + <request name="set_lock_surface"> + <arg name="surface" type="object" interface="wl_surface"/> + </request> + + <request name="unlock"/> + + <request name="set_grab_surface"> + <description summary="set grab surface"> + The surface set by this request will receive a fake + pointer.enter event during grabs at position 0, 0 and is + expected to set an appropriate cursor image as described by + the grab_cursor event sent just before the enter event. + </description> + <arg name="surface" type="object" interface="wl_surface"/> + </request> + + <!-- We'll fold most of wl_shell into this interface and then + they'll share the configure event. --> + <event name="configure"> + <arg name="edges" type="uint"/> + <arg name="surface" type="object" interface="wl_surface"/> + <arg name="width" type="int"/> + <arg name="height" type="int"/> + </event> + + <event name="prepare_lock_surface"> + <description summary="tell the client to create, set the lock surface"> + Tell the client we want it to create and set the lock surface, which is + a GUI asking the user to unlock the screen. The lock surface is + announced with 'set_lock_surface'. Whether or not the client actually + implements locking, it MUST send 'unlock' request to let the normal + desktop resume. + </description> + </event> + + <event name="grab_cursor"> + <description summary="tell client what cursor to show during a grab"> + This event will be sent immediately before a fake enter event on the + grab surface. + </description> + <arg name="cursor" type="uint"/> + </event> + + <enum name="cursor"> + <entry name="none" value="0"/> + + <entry name="resize_top" value="1"/> + <entry name="resize_bottom" value="2"/> + + <entry name="arrow" value="3"/> + + <entry name="resize_left" value="4"/> + <entry name="resize_top_left" value="5"/> + <entry name="resize_bottom_left" value="6"/> + + <entry name="move" value="7"/> + + <entry name="resize_right" value="8"/> + <entry name="resize_top_right" value="9"/> + <entry name="resize_bottom_right" value="10"/> + + <entry name="busy" value="11"/> + </enum> + + <!-- Version 2 additions --> + + <request name="desktop_ready" since="2"> + <description summary="desktop is ready to be shown"> + Tell the server, that enough desktop elements have been drawn + to make the desktop look ready for use. During start-up, the + server can wait for this request with a black screen before + starting to fade in the desktop, for instance. If the client + parts of a desktop take a long time to initialize, we avoid + showing temporary garbage. + </description> + </request> + + <!-- Version 3 additions --> + + <enum name="panel_position"> + <entry name="top" value="0"/> + <entry name="bottom" value="1"/> + <entry name="left" value="2"/> + <entry name="right" value="3"/> + </enum> + + <enum name="error"> + <entry name="invalid_argument" value="0" + summary="an invalid argument was provided in a request"/> + </enum> + + <request name="set_panel_position" since="3"> + <arg name="position" type="uint"/> + <description summary="set panel position"> + Tell the shell which side of the screen the panel is + located. This is so that new windows do not overlap the panel + and maximized windows maximize properly. + </description> + </request> + + </interface> + + <interface name="screensaver" version="1"> + <description summary="interface for implementing screensavers"> + Only one client can bind this interface at a time. + </description> + + <request name="set_surface"> + <description summary="set the surface type as a screensaver"> + A screensaver surface is normally hidden, and only visible after an + idle timeout. + </description> + + <arg name="surface" type="object" interface="wl_surface"/> + <arg name="output" type="object" interface="wl_output"/> + </request> + + </interface> +</protocol> 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 @@ +#include <wlc/wlc.h> +#include <wlc/wlc-wayland.h> +#include "wayland-desktop-shell-server-protocol.h" +#include "log.h" + +static void set_background(struct wl_client *client, struct wl_resource *resource, + struct wl_resource *output, struct wl_resource *surface) { + sway_log(L_DEBUG, "Surface requesting background for output"); +} + +static struct desktop_shell_interface desktop_shell_implementation = { + .set_background = set_background, +}; + +static void desktop_shell_bind(struct wl_client *client, void *data, + unsigned int version, unsigned int id) { + if (version > 1) { + // Unsupported version + return; + } + + struct wl_resource *resource = wl_resource_create(client, &desktop_shell_interface, version, id); + if (!resource) { + wl_client_post_no_memory(client); + } + + wl_resource_set_implementation(resource, &desktop_shell_implementation, NULL, NULL); +} + +void register_extensions(void) { + wl_global_create(wlc_get_wl_display(), &desktop_shell_interface, 1, NULL, desktop_shell_bind); +} 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 @@ #include <sys/un.h> #include <signal.h> #include <getopt.h> +#include "extensions.h" #include "layout.h" #include "stringop.h" #include "config.h" @@ -73,6 +74,8 @@ int main(int argc, char **argv) { if (!wlc_init(&interface, argc, argv)) { return 1; } + + register_extensions(); char *config_path = NULL; 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) include(Wayland) set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/../bin/) WAYLAND_ADD_PROTOCOL_CLIENT(proto-xdg-shell "${PROJECT_SOURCE_DIR}/../protocols/xdg-shell.xml" xdg-shell) +WAYLAND_ADD_PROTOCOL_CLIENT(proto-desktop-shell "${PROJECT_SOURCE_DIR}/../protocols/desktop-shell.xml" desktop-shell) include_directories( ${WAYLAND_CLIENT_INCLUDE_DIR} @@ -24,6 +25,7 @@ add_executable(swaybg ${wl_sources} ${common} ${proto-xdg-shell} + ${proto-desktop-shell} ) 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 @@ +#include "wayland-desktop-shell-client-protocol.h" #include <stdio.h> #include <stdlib.h> #include <wayland-client.h> @@ -14,12 +15,16 @@ void sway_terminate(void) { int main(int argc, char **argv) { init_log(L_INFO); - if (!(state = client_setup(100, 100))) { + if (!(state = client_setup(100, 100, false))) { return -1; } + if (!state->desktop_shell) { + sway_abort("swaybg requires the compositor to support the desktop-shell extension."); + } struct output_state *output = state->outputs->items[0]; state->width = output->width; state->height = output->height; + desktop_shell_set_background(state->desktop_shell, output->output, state->surface); uint8_t r = 0, g = 0, b = 0; 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 @@ #include <wayland-client.h> #include <wayland-cursor.h> #include "wayland-xdg-shell-client-protocol.h" +#include "wayland-desktop-shell-client-protocol.h" #include <cairo/cairo.h> #include <pango/pangocairo.h> #include <stdlib.h> @@ -96,6 +97,8 @@ static void registry_global(void *data, struct wl_registry *registry, ostate->output = output; wl_output_add_listener(output, &output_listener, ostate); list_add(state->outputs, ostate); + } else if (strcmp(interface, desktop_shell_interface.name) == 0) { + state->desktop_shell = wl_registry_bind(registry, name, &desktop_shell_interface, version); } } @@ -119,7 +122,7 @@ static const struct wl_shell_surface_listener surface_listener = { .configure = shell_surface_configure }; -struct client_state *client_setup(uint32_t width, uint32_t height) { +struct client_state *client_setup(uint32_t width, uint32_t height, bool shell_surface) { struct client_state *state = malloc(sizeof(struct client_state)); memset(state, 0, sizeof(struct client_state)); state->outputs = create_list(); @@ -140,9 +143,11 @@ struct client_state *client_setup(uint32_t width, uint32_t height) { wl_registry_destroy(registry); state->surface = wl_compositor_create_surface(state->compositor); - state->shell_surface = wl_shell_get_shell_surface(state->shell, state->surface); - wl_shell_surface_add_listener(state->shell_surface, &surface_listener, state); - wl_shell_surface_set_toplevel(state->shell_surface); + if (shell_surface) { + state->shell_surface = wl_shell_get_shell_surface(state->shell, state->surface); + wl_shell_surface_add_listener(state->shell_surface, &surface_listener, state); + wl_shell_surface_set_toplevel(state->shell_surface); + } state->cursor.cursor_theme = wl_cursor_theme_load("default", 32, state->shm); // TODO: let you customize this state->cursor.cursor = wl_cursor_theme_get_cursor(state->cursor.cursor_theme, "left_ptr"); |