diff options
author | Daniel Eklöf <daniel@ekloef.se> | 2019-06-01 21:05:09 +0200 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-06-05 11:00:10 -0400 |
commit | 190546fd315a24c04006fb1b177069933f4350da (patch) | |
tree | db0910b4931625d259f14b22a56b54095a8466bd | |
parent | cmd_hide_edge_borders: add missing arg count check (diff) | |
download | sway-190546fd315a24c04006fb1b177069933f4350da.tar.gz sway-190546fd315a24c04006fb1b177069933f4350da.tar.zst sway-190546fd315a24c04006fb1b177069933f4350da.zip |
add seat sub command 'xcursor_theme'
New 'seat <name> xcursor_theme <theme> [<size>]' command that
configures the default xcursor theme.
The default seat's xcursor theme is also propagated to XWayland, and
exported through the XCURSOR_THEME and XCURSOR_SIZE environment
variables. This is done every time the default seat's configuration is
changed.
-rw-r--r-- | include/sway/commands.h | 1 | ||||
-rw-r--r-- | include/sway/config.h | 4 | ||||
-rw-r--r-- | sway/commands/seat.c | 1 | ||||
-rw-r--r-- | sway/commands/seat/xcursor_theme.c | 33 | ||||
-rw-r--r-- | sway/config/seat.c | 9 | ||||
-rw-r--r-- | sway/input/seat.c | 70 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/server.c | 23 | ||||
-rw-r--r-- | sway/sway-input.5.scd | 6 |
9 files changed, 119 insertions, 29 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index c4903788..927296b0 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -278,6 +278,7 @@ sway_cmd seat_cmd_cursor; | |||
278 | sway_cmd seat_cmd_fallback; | 278 | sway_cmd seat_cmd_fallback; |
279 | sway_cmd seat_cmd_hide_cursor; | 279 | sway_cmd seat_cmd_hide_cursor; |
280 | sway_cmd seat_cmd_pointer_constraint; | 280 | sway_cmd seat_cmd_pointer_constraint; |
281 | sway_cmd seat_cmd_xcursor_theme; | ||
281 | 282 | ||
282 | sway_cmd cmd_ipc_cmd; | 283 | sway_cmd cmd_ipc_cmd; |
283 | sway_cmd cmd_ipc_events; | 284 | sway_cmd cmd_ipc_events; |
diff --git a/include/sway/config.h b/include/sway/config.h index b94a35f3..311adb16 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -165,6 +165,10 @@ struct seat_config { | |||
165 | list_t *attachments; // list of seat_attachment configs | 165 | list_t *attachments; // list of seat_attachment configs |
166 | int hide_cursor_timeout; | 166 | int hide_cursor_timeout; |
167 | enum seat_config_allow_constrain allow_constrain; | 167 | enum seat_config_allow_constrain allow_constrain; |
168 | struct { | ||
169 | char *name; | ||
170 | int size; | ||
171 | } xcursor_theme; | ||
168 | }; | 172 | }; |
169 | 173 | ||
170 | enum config_dpms { | 174 | enum config_dpms { |
diff --git a/sway/commands/seat.c b/sway/commands/seat.c index aa36ba95..a827bf74 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c | |||
@@ -13,6 +13,7 @@ static struct cmd_handler seat_handlers[] = { | |||
13 | { "fallback", seat_cmd_fallback }, | 13 | { "fallback", seat_cmd_fallback }, |
14 | { "hide_cursor", seat_cmd_hide_cursor }, | 14 | { "hide_cursor", seat_cmd_hide_cursor }, |
15 | { "pointer_constraint", seat_cmd_pointer_constraint }, | 15 | { "pointer_constraint", seat_cmd_pointer_constraint }, |
16 | { "xcursor_theme", seat_cmd_xcursor_theme }, | ||
16 | }; | 17 | }; |
17 | 18 | ||
18 | struct cmd_results *cmd_seat(int argc, char **argv) { | 19 | struct cmd_results *cmd_seat(int argc, char **argv) { |
diff --git a/sway/commands/seat/xcursor_theme.c b/sway/commands/seat/xcursor_theme.c new file mode 100644 index 00000000..202f35b9 --- /dev/null +++ b/sway/commands/seat/xcursor_theme.c | |||
@@ -0,0 +1,33 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <string.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/config.h" | ||
5 | |||
6 | struct cmd_results *seat_cmd_xcursor_theme(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "xcursor_theme", EXPECTED_AT_LEAST, 1)) || | ||
9 | (error = checkarg(argc, "xcursor_theme", EXPECTED_AT_MOST, 2))) { | ||
10 | return error; | ||
11 | } | ||
12 | if (!config->handler_context.seat_config) { | ||
13 | return cmd_results_new(CMD_FAILURE, "No seat defined"); | ||
14 | } | ||
15 | |||
16 | const char *theme_name = argv[0]; | ||
17 | unsigned size = 24; | ||
18 | |||
19 | if (argc == 2) { | ||
20 | char *end; | ||
21 | size = strtoul(argv[1], &end, 10); | ||
22 | if (*end) { | ||
23 | return cmd_results_new( | ||
24 | CMD_INVALID, "Expected a positive integer size"); | ||
25 | } | ||
26 | } | ||
27 | |||
28 | free(config->handler_context.seat_config->xcursor_theme.name); | ||
29 | config->handler_context.seat_config->xcursor_theme.name = strdup(theme_name); | ||
30 | config->handler_context.seat_config->xcursor_theme.size = size; | ||
31 | |||
32 | return cmd_results_new(CMD_SUCCESS, NULL); | ||
33 | } | ||
diff --git a/sway/config/seat.c b/sway/config/seat.c index 04a44e3a..d4190cec 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c | |||
@@ -27,6 +27,8 @@ struct seat_config *new_seat_config(const char* name) { | |||
27 | } | 27 | } |
28 | seat->hide_cursor_timeout = -1; | 28 | seat->hide_cursor_timeout = -1; |
29 | seat->allow_constrain = CONSTRAIN_DEFAULT; | 29 | seat->allow_constrain = CONSTRAIN_DEFAULT; |
30 | seat->xcursor_theme.name = NULL; | ||
31 | seat->xcursor_theme.size = 24; | ||
30 | 32 | ||
31 | return seat; | 33 | return seat; |
32 | } | 34 | } |
@@ -147,6 +149,12 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) { | |||
147 | if (source->allow_constrain != CONSTRAIN_DEFAULT) { | 149 | if (source->allow_constrain != CONSTRAIN_DEFAULT) { |
148 | dest->allow_constrain = source->allow_constrain; | 150 | dest->allow_constrain = source->allow_constrain; |
149 | } | 151 | } |
152 | |||
153 | if (source->xcursor_theme.name != NULL) { | ||
154 | free(dest->xcursor_theme.name); | ||
155 | dest->xcursor_theme.name = strdup(source->xcursor_theme.name); | ||
156 | dest->xcursor_theme.size = source->xcursor_theme.size; | ||
157 | } | ||
150 | } | 158 | } |
151 | 159 | ||
152 | struct seat_config *copy_seat_config(struct seat_config *seat) { | 160 | struct seat_config *copy_seat_config(struct seat_config *seat) { |
@@ -170,6 +178,7 @@ void free_seat_config(struct seat_config *seat) { | |||
170 | seat_attachment_config_free(seat->attachments->items[i]); | 178 | seat_attachment_config_free(seat->attachments->items[i]); |
171 | } | 179 | } |
172 | list_free(seat->attachments); | 180 | list_free(seat->attachments); |
181 | free(seat->xcursor_theme.name); | ||
173 | free(seat); | 182 | free(seat); |
174 | } | 183 | } |
175 | 184 | ||
diff --git a/sway/input/seat.c b/sway/input/seat.c index ce009d7e..2e386d2c 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include "sway/ipc-server.h" | 19 | #include "sway/ipc-server.h" |
20 | #include "sway/layers.h" | 20 | #include "sway/layers.h" |
21 | #include "sway/output.h" | 21 | #include "sway/output.h" |
22 | #include "sway/server.h" | ||
22 | #include "sway/tree/arrange.h" | 23 | #include "sway/tree/arrange.h" |
23 | #include "sway/tree/container.h" | 24 | #include "sway/tree/container.h" |
24 | #include "sway/tree/root.h" | 25 | #include "sway/tree/root.h" |
@@ -722,17 +723,72 @@ void seat_remove_device(struct sway_seat *seat, | |||
722 | seat_update_capabilities(seat); | 723 | seat_update_capabilities(seat); |
723 | } | 724 | } |
724 | 725 | ||
726 | static bool xcursor_manager_is_named(const struct wlr_xcursor_manager *manager, | ||
727 | const char *name) { | ||
728 | return (!manager->name && !name) || | ||
729 | (name && manager->name && strcmp(name, manager->name) == 0); | ||
730 | } | ||
731 | |||
725 | void seat_configure_xcursor(struct sway_seat *seat) { | 732 | void seat_configure_xcursor(struct sway_seat *seat) { |
726 | // TODO configure theme and size | 733 | unsigned cursor_size = 24; |
727 | const char *cursor_theme = NULL; | 734 | const char *cursor_theme = NULL; |
728 | 735 | ||
729 | if (!seat->cursor->xcursor_manager) { | 736 | const struct seat_config *seat_config = seat_get_config(seat); |
730 | seat->cursor->xcursor_manager = | 737 | if (!seat_config) { |
731 | wlr_xcursor_manager_create(cursor_theme, 24); | 738 | seat_config = seat_get_config_by_name("*"); |
732 | if (sway_assert(seat->cursor->xcursor_manager, | 739 | } |
733 | "Cannot create XCursor manager for theme")) { | 740 | if (seat_config) { |
734 | return; | 741 | cursor_size = seat_config->xcursor_theme.size; |
742 | cursor_theme = seat_config->xcursor_theme.name; | ||
743 | } | ||
744 | |||
745 | if (seat == input_manager_get_default_seat()) { | ||
746 | char cursor_size_fmt[16]; | ||
747 | snprintf(cursor_size_fmt, sizeof(cursor_size_fmt), "%d", cursor_size); | ||
748 | setenv("XCURSOR_SIZE", cursor_size_fmt, 1); | ||
749 | if (cursor_theme != NULL) { | ||
750 | setenv("XCURSOR_THEME", cursor_theme, 1); | ||
735 | } | 751 | } |
752 | |||
753 | #if HAVE_XWAYLAND | ||
754 | if (!server.xwayland.xcursor_manager || | ||
755 | !xcursor_manager_is_named(server.xwayland.xcursor_manager, | ||
756 | cursor_theme) || | ||
757 | server.xwayland.xcursor_manager->size != cursor_size) { | ||
758 | |||
759 | wlr_xcursor_manager_destroy(server.xwayland.xcursor_manager); | ||
760 | |||
761 | server.xwayland.xcursor_manager = | ||
762 | wlr_xcursor_manager_create(cursor_theme, cursor_size); | ||
763 | sway_assert(server.xwayland.xcursor_manager, | ||
764 | "Cannot create XCursor manager for theme"); | ||
765 | |||
766 | wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1); | ||
767 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( | ||
768 | server.xwayland.xcursor_manager, "left_ptr", 1); | ||
769 | if (xcursor != NULL) { | ||
770 | struct wlr_xcursor_image *image = xcursor->images[0]; | ||
771 | wlr_xwayland_set_cursor( | ||
772 | server.xwayland.wlr_xwayland, image->buffer, | ||
773 | image->width * 4, image->width, image->height, | ||
774 | image->hotspot_x, image->hotspot_y); | ||
775 | } | ||
776 | } | ||
777 | #endif | ||
778 | } | ||
779 | |||
780 | /* Create xcursor manager if we don't have one already, or if the | ||
781 | * theme has changed */ | ||
782 | if (!seat->cursor->xcursor_manager || | ||
783 | !xcursor_manager_is_named( | ||
784 | seat->cursor->xcursor_manager, cursor_theme) || | ||
785 | seat->cursor->xcursor_manager->size != cursor_size) { | ||
786 | |||
787 | wlr_xcursor_manager_destroy(seat->cursor->xcursor_manager); | ||
788 | seat->cursor->xcursor_manager = | ||
789 | wlr_xcursor_manager_create(cursor_theme, cursor_size); | ||
790 | sway_assert(seat->cursor->xcursor_manager, | ||
791 | "Cannot create XCursor manager for theme"); | ||
736 | } | 792 | } |
737 | 793 | ||
738 | for (int i = 0; i < root->outputs->length; ++i) { | 794 | for (int i = 0; i < root->outputs->length; ++i) { |
diff --git a/sway/meson.build b/sway/meson.build index 05cece7a..262d7057 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -89,6 +89,7 @@ sway_sources = files( | |||
89 | 'commands/seat/fallback.c', | 89 | 'commands/seat/fallback.c', |
90 | 'commands/seat/hide_cursor.c', | 90 | 'commands/seat/hide_cursor.c', |
91 | 'commands/seat/pointer_constraint.c', | 91 | 'commands/seat/pointer_constraint.c', |
92 | 'commands/seat/xcursor_theme.c', | ||
92 | 'commands/set.c', | 93 | 'commands/set.c', |
93 | 'commands/show_marks.c', | 94 | 'commands/show_marks.c', |
94 | 'commands/smart_borders.c', | 95 | 'commands/smart_borders.c', |
diff --git a/sway/server.c b/sway/server.c index a403d8b3..b50e3ccc 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -168,17 +168,6 @@ void server_fini(struct sway_server *server) { | |||
168 | } | 168 | } |
169 | 169 | ||
170 | bool server_start(struct sway_server *server) { | 170 | bool server_start(struct sway_server *server) { |
171 | // TODO: configurable cursor theme and size | ||
172 | int cursor_size = 24; | ||
173 | const char *cursor_theme = NULL; | ||
174 | |||
175 | char cursor_size_fmt[16]; | ||
176 | snprintf(cursor_size_fmt, sizeof(cursor_size_fmt), "%d", cursor_size); | ||
177 | setenv("XCURSOR_SIZE", cursor_size_fmt, 1); | ||
178 | if (cursor_theme != NULL) { | ||
179 | setenv("XCURSOR_THEME", cursor_theme, 1); | ||
180 | } | ||
181 | |||
182 | #if HAVE_XWAYLAND | 171 | #if HAVE_XWAYLAND |
183 | if (config->xwayland) { | 172 | if (config->xwayland) { |
184 | sway_log(SWAY_DEBUG, "Initializing Xwayland"); | 173 | sway_log(SWAY_DEBUG, "Initializing Xwayland"); |
@@ -193,17 +182,7 @@ bool server_start(struct sway_server *server) { | |||
193 | 182 | ||
194 | setenv("DISPLAY", server->xwayland.wlr_xwayland->display_name, true); | 183 | setenv("DISPLAY", server->xwayland.wlr_xwayland->display_name, true); |
195 | 184 | ||
196 | server->xwayland.xcursor_manager = | 185 | /* xcursor configured by the default seat */ |
197 | wlr_xcursor_manager_create(cursor_theme, cursor_size); | ||
198 | wlr_xcursor_manager_load(server->xwayland.xcursor_manager, 1); | ||
199 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( | ||
200 | server->xwayland.xcursor_manager, "left_ptr", 1); | ||
201 | if (xcursor != NULL) { | ||
202 | struct wlr_xcursor_image *image = xcursor->images[0]; | ||
203 | wlr_xwayland_set_cursor(server->xwayland.wlr_xwayland, image->buffer, | ||
204 | image->width * 4, image->width, image->height, image->hotspot_x, | ||
205 | image->hotspot_y); | ||
206 | } | ||
207 | } | 186 | } |
208 | #endif | 187 | #endif |
209 | 188 | ||
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index efd3d1af..3191bddf 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd | |||
@@ -206,6 +206,12 @@ correct seat. | |||
206 | by default) for the seat. This is primarily useful for video games. The | 206 | by default) for the seat. This is primarily useful for video games. The |
207 | "escape" command can be used at runtime to escape from a captured client. | 207 | "escape" command can be used at runtime to escape from a captured client. |
208 | 208 | ||
209 | *seat* <name> xcursor_theme <theme> [<size>] | ||
210 | Override the system default XCursor theme. The default seat's | ||
211 | (_seat0_) theme is also used as the default cursor theme in | ||
212 | XWayland, and exported through the _XCURSOR_THEME_ and | ||
213 | _XCURSOR_SIZE_ environment variables. | ||
214 | |||
209 | # SEE ALSO | 215 | # SEE ALSO |
210 | 216 | ||
211 | *sway*(5) *sway-output*(5) *xkeyboard-config*(7) | 217 | *sway*(5) *sway-output*(5) *xkeyboard-config*(7) |