mirror of
https://github.com/swaywm/sway.git
synced 2024-11-22 07:51:28 +00:00
Basic support for extensions in server and clients
This commit is contained in:
parent
fb0bfa13ce
commit
82db2a57a9
|
@ -5,7 +5,8 @@ project(sway C)
|
||||||
set(CMAKE_C_FLAGS "-g")
|
set(CMAKE_C_FLAGS "-g")
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
SET(CMAKE_C_EXTENSIONS OFF)
|
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")
|
add_definitions("-Wall -Wextra -Wno-unused-parameter -D_GNU_SOURCE")
|
||||||
list(INSERT CMAKE_MODULE_PATH 0
|
list(INSERT CMAKE_MODULE_PATH 0
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/CMake")
|
"${CMAKE_CURRENT_SOURCE_DIR}/CMake")
|
||||||
|
@ -38,21 +39,27 @@ find_package(XKBCommon REQUIRED)
|
||||||
find_package(WLC REQUIRED)
|
find_package(WLC REQUIRED)
|
||||||
find_package(A2X REQUIRED)
|
find_package(A2X REQUIRED)
|
||||||
find_package(PCRE REQUIRED)
|
find_package(PCRE REQUIRED)
|
||||||
|
find_package(Wayland REQUIRED)
|
||||||
find_package(JsonC REQUIRED)
|
find_package(JsonC REQUIRED)
|
||||||
|
|
||||||
FILE(GLOB sources ${PROJECT_SOURCE_DIR}/sway/*.c)
|
FILE(GLOB sources ${PROJECT_SOURCE_DIR}/sway/*.c)
|
||||||
FILE(GLOB common ${PROJECT_SOURCE_DIR}/common/*.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(
|
include_directories(
|
||||||
${WLC_INCLUDE_DIRS}
|
${WLC_INCLUDE_DIRS}
|
||||||
${PCRE_INCLUDE_DIRS}
|
${PCRE_INCLUDE_DIRS}
|
||||||
${JSONC_INCLUDE_DIRS}
|
${JSONC_INCLUDE_DIRS}
|
||||||
${XKBCOMMON_INCLUDE_DIRS}
|
${XKBCOMMON_INCLUDE_DIRS}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(sway
|
add_executable(sway
|
||||||
${sources}
|
${sources}
|
||||||
${common}
|
${common}
|
||||||
|
${proto-desktop-shell}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(sway
|
target_link_libraries(sway
|
||||||
|
@ -60,6 +67,7 @@ target_link_libraries(sway
|
||||||
${XKBCOMMON_LIBRARIES}
|
${XKBCOMMON_LIBRARIES}
|
||||||
${PCRE_LIBRARIES}
|
${PCRE_LIBRARIES}
|
||||||
${JSONC_LIBRARIES}
|
${JSONC_LIBRARIES}
|
||||||
|
${WAYLAND_SERVER_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define _CLIENT_H
|
#define _CLIENT_H
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
#include "wayland-desktop-shell-client-protocol.h"
|
||||||
#include <cairo/cairo.h>
|
#include <cairo/cairo.h>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -41,13 +42,14 @@ struct client_state {
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct wl_shell_surface *shell_surface;
|
struct wl_shell_surface *shell_surface;
|
||||||
struct wl_callback *frame_cb;
|
struct wl_callback *frame_cb;
|
||||||
|
struct desktop_shell *desktop_shell;
|
||||||
struct cursor cursor;
|
struct cursor cursor;
|
||||||
uint32_t width, height;
|
uint32_t width, height;
|
||||||
cairo_t *cairo;
|
cairo_t *cairo;
|
||||||
list_t *outputs;
|
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);
|
void client_teardown(struct client_state *state);
|
||||||
int client_prerender(struct client_state *state);
|
int client_prerender(struct client_state *state);
|
||||||
int client_render(struct client_state *state);
|
int client_render(struct client_state *state);
|
||||||
|
|
6
include/extensions.h
Normal file
6
include/extensions.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef _SWAY_EXTENSIONS_H
|
||||||
|
#define _SWAY_EXTENSIONS_H
|
||||||
|
|
||||||
|
void register_extensions(void);
|
||||||
|
|
||||||
|
#endif
|
138
protocols/desktop-shell.xml
Normal file
138
protocols/desktop-shell.xml
Normal file
|
@ -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>
|
32
sway/extensions.c
Normal file
32
sway/extensions.c
Normal file
|
@ -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);
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include "extensions.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -73,6 +74,8 @@ int main(int argc, char **argv) {
|
||||||
if (!wlc_init(&interface, argc, argv)) {
|
if (!wlc_init(&interface, argc, argv)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register_extensions();
|
||||||
|
|
||||||
char *config_path = NULL;
|
char *config_path = NULL;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ find_package(Pango REQUIRED)
|
||||||
include(Wayland)
|
include(Wayland)
|
||||||
set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/../bin/)
|
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-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(
|
include_directories(
|
||||||
${WAYLAND_CLIENT_INCLUDE_DIR}
|
${WAYLAND_CLIENT_INCLUDE_DIR}
|
||||||
|
@ -24,6 +25,7 @@ add_executable(swaybg
|
||||||
${wl_sources}
|
${wl_sources}
|
||||||
${common}
|
${common}
|
||||||
${proto-xdg-shell}
|
${proto-xdg-shell}
|
||||||
|
${proto-desktop-shell}
|
||||||
)
|
)
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(swaybg ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES} ${CAIRO_LIBRARIES} ${PANGO_LIBRARIES} m)
|
TARGET_LINK_LIBRARIES(swaybg ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES} ${CAIRO_LIBRARIES} ${PANGO_LIBRARIES} m)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "wayland-desktop-shell-client-protocol.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
@ -14,12 +15,16 @@ void sway_terminate(void) {
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
init_log(L_INFO);
|
init_log(L_INFO);
|
||||||
if (!(state = client_setup(100, 100))) {
|
if (!(state = client_setup(100, 100, false))) {
|
||||||
return -1;
|
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];
|
struct output_state *output = state->outputs->items[0];
|
||||||
state->width = output->width;
|
state->width = output->width;
|
||||||
state->height = output->height;
|
state->height = output->height;
|
||||||
|
desktop_shell_set_background(state->desktop_shell, output->output, state->surface);
|
||||||
|
|
||||||
uint8_t r = 0, g = 0, b = 0;
|
uint8_t r = 0, g = 0, b = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <wayland-cursor.h>
|
#include <wayland-cursor.h>
|
||||||
#include "wayland-xdg-shell-client-protocol.h"
|
#include "wayland-xdg-shell-client-protocol.h"
|
||||||
|
#include "wayland-desktop-shell-client-protocol.h"
|
||||||
#include <cairo/cairo.h>
|
#include <cairo/cairo.h>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -96,6 +97,8 @@ static void registry_global(void *data, struct wl_registry *registry,
|
||||||
ostate->output = output;
|
ostate->output = output;
|
||||||
wl_output_add_listener(output, &output_listener, ostate);
|
wl_output_add_listener(output, &output_listener, ostate);
|
||||||
list_add(state->outputs, 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
|
.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));
|
struct client_state *state = malloc(sizeof(struct client_state));
|
||||||
memset(state, 0, sizeof(struct client_state));
|
memset(state, 0, sizeof(struct client_state));
|
||||||
state->outputs = create_list();
|
state->outputs = create_list();
|
||||||
|
@ -140,9 +143,11 @@ struct client_state *client_setup(uint32_t width, uint32_t height) {
|
||||||
wl_registry_destroy(registry);
|
wl_registry_destroy(registry);
|
||||||
|
|
||||||
state->surface = wl_compositor_create_surface(state->compositor);
|
state->surface = wl_compositor_create_surface(state->compositor);
|
||||||
state->shell_surface = wl_shell_get_shell_surface(state->shell, state->surface);
|
if (shell_surface) {
|
||||||
wl_shell_surface_add_listener(state->shell_surface, &surface_listener, state);
|
state->shell_surface = wl_shell_get_shell_surface(state->shell, state->surface);
|
||||||
wl_shell_surface_set_toplevel(state->shell_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_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");
|
state->cursor.cursor = wl_cursor_theme_get_cursor(state->cursor.cursor_theme, "left_ptr");
|
||||||
|
|
Loading…
Reference in a new issue