From 02812a2e4da9f274c5957975fdbb4a4a58b20a69 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 29 Apr 2017 09:56:07 -0400 Subject: [PATCH 01/24] Support specifying fewer than 5 colors This doesn't work, I'm not sure why. The color structs definitely get changed but if you specify fewer than 5, it renders with the defaults. --- sway/commands.c | 2 +- sway/commands/client.c | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index 01e5e6b5e..509fd1a82 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -250,7 +250,7 @@ static struct cmd_handler bar_handlers[] = { */ struct cmd_results *add_color(const char *name, char *buffer, const char *color) { int len = strlen(color); - if (len != 7 && len != 9 ) { + if (len != 7 && len != 9) { return cmd_results_new(CMD_INVALID, name, "Invalid color definition %s", color); } diff --git a/sway/commands/client.c b/sway/commands/client.c index 7954f6701..30f9137e5 100644 --- a/sway/commands/client.c +++ b/sway/commands/client.c @@ -4,27 +4,27 @@ static struct cmd_results *parse_border_color(struct border_colors *border_colors, const char *cmd_name, int argc, char **argv) { struct cmd_results *error = NULL; - if (argc != 5) { - return cmd_results_new(CMD_INVALID, cmd_name, "Requires exactly five color values"); + if (argc < 3 || argc > 5) { + return cmd_results_new(CMD_INVALID, cmd_name, "Requires between three and five color values"); } - uint32_t colors[5]; + uint32_t *colors[5] = { + &border_colors->border, + &border_colors->background, + &border_colors->text, + &border_colors->indicator, + &border_colors->child_border + }; int i; - for (i = 0; i < 5; i++) { + for (i = 0; i < argc; i++) { char buffer[10]; error = add_color(cmd_name, buffer, argv[i]); if (error) { return error; } - colors[i] = strtoul(buffer+1, NULL, 16); + *colors[i] = strtoul(buffer + 1, NULL, 16); } - border_colors->border = colors[0]; - border_colors->background = colors[1]; - border_colors->text = colors[2]; - border_colors->indicator = colors[3]; - border_colors->child_border = colors[4]; - return cmd_results_new(CMD_SUCCESS, NULL, NULL); } From 816ceddcbdd6c98648784e85559b495b63613b7b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 29 Apr 2017 10:07:18 -0400 Subject: [PATCH 02/24] Set child border to background if not specified --- sway/commands/client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/commands/client.c b/sway/commands/client.c index 30f9137e5..f3d879cd4 100644 --- a/sway/commands/client.c +++ b/sway/commands/client.c @@ -25,6 +25,10 @@ static struct cmd_results *parse_border_color(struct border_colors *border_color *colors[i] = strtoul(buffer + 1, NULL, 16); } + if (argc < 5) { + border_colors->child_border = border_colors->background; + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } From 34fae764a5b92d25e5af84431d529d3d46757ff1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 29 Apr 2017 10:54:08 -0400 Subject: [PATCH 03/24] Add HACKING.md --- HACKING.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 HACKING.md diff --git a/HACKING.md b/HACKING.md new file mode 100644 index 000000000..cf18dbb04 --- /dev/null +++ b/HACKING.md @@ -0,0 +1,35 @@ +## Logging + +Use `sway_log(importance, fmt, ...)` to log. The following importances are +available: + +* `L_DEBUG`: Debug messages, only shows with `sway -d` +* `L_INFO`: Informational messages +* `L_ERROR`: Error messages + +`sway_log` is a macro that calls `_sway_log` with the current filename and line +number, which are written into the log with your message. + +## Assertions + +In the compositor, assertions *must not* be fatal. All error cases must be +handled as gracefully as possible - crashing the compositor will make the user +lose all of their work. + +Use `sway_assert(condition, fmt, ...)` to perform an assertion. This returns +`condition`, which you must handle if false. An error will be logged if the +assertion fails. + +Outside of the compositor (swaymsg, swaybar, etc), using `assert.h` is +permitted. + +## Building against a local wlc + +1. Build wlc as described [here](https://github.com/Cloudef/wlc#building) +2. Inside your sway source folder, tell `cmake` to use your local version of wlc: + +```bash +cmake \ + -DWLC_LIBRARIES=path/to/wlc/target/src/libwlc.so \ + -DWLC_INCLUDE_DIRS=path/to/wlc/include . +``` From f65a88e68d1ddd606f1a596ed697887c3b3888d0 Mon Sep 17 00:00:00 2001 From: Zandr Martin Date: Sat, 29 Apr 2017 14:02:07 -0400 Subject: [PATCH 04/24] prevent crash when `layout auto` is missing args --- sway/commands/layout.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 40ebd5903..57a865654 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -85,6 +85,10 @@ static struct cmd_results *cmd_layout_auto(swayc_t *container, int argc, char ** enum swayc_layouts old_layout = container->layout; enum swayc_layouts layout = old_layout; + if ((error = checkarg(argc, "layout auto", EXPECTED_MORE_THAN, 1))) { + return error; + } + if (strcasecmp(argv[1], "left") == 0) { layout = L_AUTO_LEFT; } else if (strcasecmp(argv[1], "right") == 0) { From 106868ddbf325963a3f51300669e24629f3b3c65 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 30 Apr 2017 22:51:52 -0400 Subject: [PATCH 05/24] Update config.in swaymsg -t get_inputs now pretty prints its output, so this warning is obsolete --- config.in | 1 - 1 file changed, 1 deletion(-) diff --git a/config.in b/config.in index a262fc822..993e2ab63 100644 --- a/config.in +++ b/config.in @@ -41,7 +41,6 @@ output * bg __DATADIR__/sway/Sway_Wallpaper_Blue_1920x1080.png fill # } # # You can get the names of your inputs by running: swaymsg -t get_inputs -# The escape symbol "\" has to be removed. # Read `man 5 sway-input` for more information about this section. ### Key bindings From 51ce752ebf490d9cb62e89f3a2d2b95252105156 Mon Sep 17 00:00:00 2001 From: Zandr Martin Date: Mon, 1 May 2017 12:53:07 -0400 Subject: [PATCH 06/24] document font command --- sway/sway.5.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sway/sway.5.txt b/sway/sway.5.txt index 1fa0b8560..131780e26 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -276,6 +276,11 @@ The default colors are: **focus_follows_mouse** :: If set to _yes_, moving your mouse over a window will focus that window. +**font** :: + Sets font for use in title bars. Generally the format is something like "Name + Style Size" e.g. "Deja Vu Sans Book 12". You can also use Pango font + descriptions with "pango:font". + **for_window** :: Whenever a window that matches _criteria_ appears, run list of commands. See **Criteria** section below. From 400998d6d2bf311f3402faf092154ee8ceac2bf9 Mon Sep 17 00:00:00 2001 From: Josip Janzic Date: Thu, 4 May 2017 22:42:50 +0200 Subject: [PATCH 07/24] Add mouse button bindings Adds support for bindings like: bindsym button3 floating toggle bindsym $mod+button3 floating toggle --- sway/commands/bind.c | 8 ++++++++ sway/handlers.c | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 8282277bd..af5a01e52 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -1,7 +1,9 @@ #include #include +#include #include "sway/commands.h" #include "sway/config.h" +#include "sway/input_state.h" #include "list.h" #include "log.h" #include "stringop.h" @@ -52,6 +54,12 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { // Check for xkb key xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE); + + // Check for mouse binding + if (strncasecmp(split->items[i], "button", strlen("button")) == 0 && + strlen(split->items[i]) == strlen("button0")) { + sym = ((char *)split->items[i])[strlen("button")] - '1' + M_LEFT_CLICK; + } if (!sym) { free_sway_binding(binding); free_flat_list(split); diff --git a/sway/handlers.c b/sway/handlers.c index da765d6d4..e1b90a074 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -917,6 +917,26 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w // Update view pointer is on pointer_state.view = container_under_pointer(); + struct sway_mode *mode = config->current_mode; + // handle bindings + for (int i = 0; i < mode->bindings->length; ++i) { + struct sway_binding *binding = mode->bindings->items[i]; + if ((modifiers->mods ^ binding->modifiers) == 0) { + switch (state) { + case WLC_BUTTON_STATE_PRESSED: { + if (!binding->release && handle_bindsym(binding, button, 0)) { + return EVENT_HANDLED; + } + } + case WLC_BUTTON_STATE_RELEASED: + if (binding->release && handle_bindsym(binding, button, 0)) { + return EVENT_HANDLED; + } + break; + } + } + } + // Update pointer_state switch (button) { case M_LEFT_CLICK: From 264a9ee9d8da6634775b49a07be4694b8507ce63 Mon Sep 17 00:00:00 2001 From: wdbw Date: Sat, 6 May 2017 10:45:17 +0100 Subject: [PATCH 08/24] Add missing send-event mode to sway-input(5) Also, fix a small typo. --- sway/sway-input.5.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/sway-input.5.txt b/sway/sway-input.5.txt index e92b523a4..f44a3179a 100644 --- a/sway/sway-input.5.txt +++ b/sway/sway-input.5.txt @@ -30,7 +30,7 @@ Commands **input** dwt :: Enables or disables disable-while-typing for the specified input device. -**input** events :: +**input** events :: Enables or disables send_events for specified input device. (Disabling send_events disables the input device) From 46fbb413f27d6f2a90ffa4216fb9fde5b7058684 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 11 May 2017 11:47:42 -0400 Subject: [PATCH 09/24] Mention Patreon in README.md Does this make me a sellout --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 548fc6ed7..65a943d38 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,12 @@ irc.freenode.net). [![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) -[More screenshots](https://github.com/SirCmpwn/sway/wiki/Screenshots-of-Sway) +If you'd like to support Sway development, you can contribute to [my Patreon +page](https://patreon.com/sircmpwn) or you can contribute to +[bounties](https://github.com/SirCmpwn/sway/issues/986) for specific features. +Anyone is welcome to claim a bounty and you can make a bounty for any feature +you wish, and Patreon is more useful for supporting the overall health and +maintenance of Sway. ## Release Signatures @@ -23,8 +28,6 @@ and published [on GitHub](https://github.com/SirCmpwn/sway/releases). - [i3-gaps feature support](https://github.com/SirCmpwn/sway/issues/307) - [security features](https://github.com/SirCmpwn/sway/issues/984) -[Bounties](https://github.com/SirCmpwn/sway/issues/986): sponsor features or get paid to write them - ## Installation ### From Packages From f736198c315bb91bfa7faff095181a3e8e89df94 Mon Sep 17 00:00:00 2001 From: Mykyta Holubakha Date: Thu, 11 May 2017 19:29:10 +0300 Subject: [PATCH 10/24] Initialise logging earlier --- sway/main.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/sway/main.c b/sway/main.c index b9549b127..3d2d6c68f 100644 --- a/sway/main.c +++ b/sway/main.c @@ -288,6 +288,15 @@ int main(int argc, char **argv) { } } + // we need to setup logging before wlc_init in case it fails. + if (debug) { + init_log(L_DEBUG); + } else if (verbose || validate) { + init_log(L_INFO); + } else { + init_log(L_ERROR); + } + if (optind < argc) { // Behave as IPC client if(optind != 1) { sway_log(L_ERROR, "Don't use options with the IPC client"); @@ -329,14 +338,6 @@ int main(int argc, char **argv) { } #endif - // we need to setup logging before wlc_init in case it fails. - if (debug) { - init_log(L_DEBUG); - } else if (verbose || validate) { - init_log(L_INFO); - } else { - init_log(L_ERROR); - } wlc_log_set_handler(wlc_log_handler); log_kernel(); log_distro(); From 93cf21fb9afd8205f01399ed2d8dcbe16b522fa4 Mon Sep 17 00:00:00 2001 From: Mykyta Holubakha Date: Wed, 10 May 2017 02:51:28 +0300 Subject: [PATCH 11/24] Terminate when both suid bit and filecaps are set --- sway/main.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sway/main.c b/sway/main.c index 3d2d6c68f..819788b17 100644 --- a/sway/main.c +++ b/sway/main.c @@ -27,6 +27,7 @@ #include "stringop.h" #include "sway.h" #include "log.h" +#include "util.h" static bool terminate_request = false; static int exit_value = 0; @@ -209,6 +210,27 @@ static void security_sanity_check() { #endif } +static void executable_sanity_check() { +#ifdef __linux__ + struct stat sb; + char *exe = realpath("/proc/self/exe", NULL); + stat(exe, &sb); + // We assume that cap_get_file returning NULL implies ENODATA + if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) { + sway_log(L_ERROR, + "sway executable has both the s(g)uid bit AND file caps set."); + sway_log(L_ERROR, + "This is strongly discouraged (and completely broken)."); + sway_log(L_ERROR, + "Please clear one of them (either the suid bit, or the file caps)."); + sway_log(L_ERROR, + "If unsure, strip the file caps."); + exit(EXIT_FAILURE); + } + free(exe); +#endif +} + int main(int argc, char **argv) { static int verbose = 0, debug = 0, validate = 0; @@ -326,6 +348,7 @@ int main(int argc, char **argv) { return 0; } + executable_sanity_check(); #ifdef __linux__ bool suid = false; if (getuid() != geteuid() || getgid() != getegid()) { From f470fa58a3fb56f456f83f08e3509d9785ad06d5 Mon Sep 17 00:00:00 2001 From: Mykyta Holubakha Date: Thu, 11 May 2017 19:38:32 +0300 Subject: [PATCH 12/24] Replace spaces with tabs in resolve_path --- common/util.c | 64 +++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/common/util.c b/common/util.c index a9e6a9c2a..34bb5ec19 100644 --- a/common/util.c +++ b/common/util.c @@ -124,38 +124,38 @@ uint32_t parse_color(const char *color) { } char* resolve_path(const char* path) { - struct stat sb; - ssize_t r; - int i; - char *current = NULL; - char *resolved = NULL; + struct stat sb; + ssize_t r; + int i; + char *current = NULL; + char *resolved = NULL; - if(!(current = strdup(path))) { - return NULL; - } - for (i = 0; i < 16; ++i) { - if (lstat(current, &sb) == -1) { - goto failed; - } - if((sb.st_mode & S_IFMT) != S_IFLNK) { - return current; - } - if (!(resolved = malloc(sb.st_size + 1))) { - goto failed; - } - r = readlink(current, resolved, sb.st_size); - if (r == -1 || r > sb.st_size) { - goto failed; - } - resolved[r] = '\0'; - free(current); - current = strdup(resolved); - free(resolved); - resolved = NULL; - } + if(!(current = strdup(path))) { + return NULL; + } + for (i = 0; i < 16; ++i) { + if (lstat(current, &sb) == -1) { + goto failed; + } + if((sb.st_mode & S_IFMT) != S_IFLNK) { + return current; + } + if (!(resolved = malloc(sb.st_size + 1))) { + goto failed; + } + r = readlink(current, resolved, sb.st_size); + if (r == -1 || r > sb.st_size) { + goto failed; + } + resolved[r] = '\0'; + free(current); + current = strdup(resolved); + free(resolved); + resolved = NULL; + } failed: - free(resolved); - free(current); - return NULL; -} \ No newline at end of file + free(resolved); + free(current); + return NULL; +} From 91f2bf81bf89699d43083f3d3a27805ba5e395a9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 17 May 2017 13:10:33 -0400 Subject: [PATCH 13/24] Drop epoll dependency --- CMake/FindEpollShim.cmake | 17 ----------------- CMakeLists.txt | 4 ---- 2 files changed, 21 deletions(-) delete mode 100644 CMake/FindEpollShim.cmake diff --git a/CMake/FindEpollShim.cmake b/CMake/FindEpollShim.cmake deleted file mode 100644 index b6bed1426..000000000 --- a/CMake/FindEpollShim.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# - Find EpollShim -# Once done, this will define -# -# EPOLLSHIM_FOUND - System has EpollShim -# EPOLLSHIM_INCLUDE_DIRS - The EpollShim include directories -# EPOLLSHIM_LIBRARIES - The libraries needed to use EpollShim - -find_path(EPOLLSHIM_INCLUDE_DIRS NAMES sys/epoll.h sys/timerfd.h HINTS /usr/local/include/libepoll-shim) -find_library(EPOLLSHIM_LIBRARIES NAMES epoll-shim libepoll-shim HINTS /usr/local/lib) - -if (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES) - set(EPOLLSHIM_FOUND TRUE) -endif (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(EPOLLSHIM DEFAULT_MSG EPOLLSHIM_LIBRARIES EPOLLSHIM_INCLUDE_DIRS) -mark_as_advanced(EPOLLSHIM_INCLUDE_DIRS EPOLLSHIM_LIBRARIES) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ed458301..da505cd48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,10 +68,6 @@ find_package(PAM) find_package(LibInput REQUIRED) find_package(Libcap REQUIRED) -if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) - find_package(EpollShim REQUIRED) -endif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) - include(FeatureSummary) include(Manpage) include(GNUInstallDirs) From 5ed533a94331ea2d849f900ee20f8932d742e9b5 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 17 May 2017 13:11:49 -0400 Subject: [PATCH 14/24] Revert "Drop epoll dependency" This reverts commit 91f2bf81bf89699d43083f3d3a27805ba5e395a9. --- CMake/FindEpollShim.cmake | 17 +++++++++++++++++ CMakeLists.txt | 4 ++++ 2 files changed, 21 insertions(+) create mode 100644 CMake/FindEpollShim.cmake diff --git a/CMake/FindEpollShim.cmake b/CMake/FindEpollShim.cmake new file mode 100644 index 000000000..b6bed1426 --- /dev/null +++ b/CMake/FindEpollShim.cmake @@ -0,0 +1,17 @@ +# - Find EpollShim +# Once done, this will define +# +# EPOLLSHIM_FOUND - System has EpollShim +# EPOLLSHIM_INCLUDE_DIRS - The EpollShim include directories +# EPOLLSHIM_LIBRARIES - The libraries needed to use EpollShim + +find_path(EPOLLSHIM_INCLUDE_DIRS NAMES sys/epoll.h sys/timerfd.h HINTS /usr/local/include/libepoll-shim) +find_library(EPOLLSHIM_LIBRARIES NAMES epoll-shim libepoll-shim HINTS /usr/local/lib) + +if (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES) + set(EPOLLSHIM_FOUND TRUE) +endif (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(EPOLLSHIM DEFAULT_MSG EPOLLSHIM_LIBRARIES EPOLLSHIM_INCLUDE_DIRS) +mark_as_advanced(EPOLLSHIM_INCLUDE_DIRS EPOLLSHIM_LIBRARIES) diff --git a/CMakeLists.txt b/CMakeLists.txt index da505cd48..9ed458301 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,10 @@ find_package(PAM) find_package(LibInput REQUIRED) find_package(Libcap REQUIRED) +if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) + find_package(EpollShim REQUIRED) +endif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) + include(FeatureSummary) include(Manpage) include(GNUInstallDirs) From 7fef2830446e1f98a02f8d8a3bba866b7edd5bd0 Mon Sep 17 00:00:00 2001 From: johalun Date: Mon, 5 Jun 2017 13:44:29 +0200 Subject: [PATCH 15/24] FreeBSD fixes Increase _POSIX_SOURCE value where needed. Increase _XOPEN_SOURCE value where needed. Conditionally link to libcap (only on Linux). Possibly some trailing whitespace fixes (automatic). --- CMakeLists.txt | 5 ++++- common/log.c | 2 +- common/stringop.c | 2 +- common/util.c | 2 +- sway/border.c | 2 +- sway/commands.c | 2 +- sway/commands/assign.c | 3 +-- sway/commands/set.c | 2 +- sway/config.c | 4 ++-- sway/criteria.c | 2 +- sway/input.c | 4 ++-- sway/main.c | 3 +-- sway/security.c | 2 +- swaygrab/json.c | 2 +- swaygrab/main.c | 2 +- 15 files changed, 20 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ed458301..edf486ca7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,10 @@ find_package(GdkPixbuf) find_package(PAM) find_package(LibInput REQUIRED) -find_package(Libcap REQUIRED) + +if (CMAKE_SYSTEM_NAME STREQUAL Linux) + find_package(Libcap REQUIRED) +endif (CMAKE_SYSTEM_NAME STREQUAL Linux) if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) find_package(EpollShim REQUIRED) diff --git a/common/log.c b/common/log.c index 619374954..af1bdc3f6 100644 --- a/common/log.c +++ b/common/log.c @@ -1,4 +1,4 @@ -#define _POSIX_C_SOURCE 1 +#define _POSIX_C_SOURCE 199506L #include #include #include diff --git a/common/stringop.c b/common/stringop.c index 99e9636d8..4a37543d6 100644 --- a/common/stringop.c +++ b/common/stringop.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include diff --git a/common/util.c b/common/util.c index 34bb5ec19..d63698535 100644 --- a/common/util.c +++ b/common/util.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include diff --git a/sway/border.c b/sway/border.c index 10ad92c2d..df0022ce2 100644 --- a/sway/border.c +++ b/sway/border.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include diff --git a/sway/commands.c b/sway/commands.c index 509fd1a82..342184914 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include diff --git a/sway/commands/assign.c b/sway/commands/assign.c index ec262bb8b..c3b03bbc4 100644 --- a/sway/commands/assign.c +++ b/sway/commands/assign.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include "sway/commands.h" @@ -55,4 +55,3 @@ struct cmd_results *cmd_assign(int argc, char **argv) { } return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); } - diff --git a/sway/commands/set.c b/sway/commands/set.c index 1d6bce04e..e3d08dd34 100644 --- a/sway/commands/set.c +++ b/sway/commands/set.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include diff --git a/sway/config.c b/sway/config.c index 19b1882f4..85823953c 100644 --- a/sway/config.c +++ b/sway/config.c @@ -1,5 +1,5 @@ #define _POSIX_C_SOURCE 200809L -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include @@ -527,7 +527,7 @@ bool load_main_config(const char *file, bool is_active) { list_add(config->config_chain, path); config->reading = true; - + // Read security configs bool success = true; DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); diff --git a/sway/criteria.c b/sway/criteria.c index 1ea8311e4..04683f660 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include diff --git a/sway/input.c b/sway/input.c index 4f1ef7606..6263f79fe 100644 --- a/sway/input.c +++ b/sway/input.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include @@ -60,7 +60,7 @@ char *libinput_dev_unique_id(struct libinput_device *device) { } const char *fmt = "%d:%d:%s"; - snprintf(identifier, len, fmt, vendor, product, name); + snprintf(identifier, len, fmt, vendor, product, name); free(name); return identifier; } diff --git a/sway/main.c b/sway/main.c index 819788b17..82375e0ba 100644 --- a/sway/main.c +++ b/sway/main.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #define _POSIX_C_SOURCE 200112L #include #include @@ -433,4 +433,3 @@ int main(int argc, char **argv) { return exit_value; } - diff --git a/sway/security.c b/sway/security.c index 8eab61261..92de06c1d 100644 --- a/sway/security.c +++ b/sway/security.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include diff --git a/swaygrab/json.c b/swaygrab/json.c index 563b8ba35..80dae299f 100644 --- a/swaygrab/json.c +++ b/swaygrab/json.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include #include #include diff --git a/swaygrab/main.c b/swaygrab/main.c index f901d3188..413de1fae 100644 --- a/swaygrab/main.c +++ b/swaygrab/main.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #define _POSIX_C_SOURCE 199309L #include #include From 843ad38b3c427adb0bf319e9613d9813c8d9246c Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Wed, 7 Jun 2017 16:45:28 -0700 Subject: [PATCH 16/24] Implement Tray Icons This commit implements the StatusNotifierItem protocol, and enables swaybar to show tray icons. It also uses `xembedsniproxy` in order to communicate with xembed applications. The tray is completely optional, and can be disabled on compile time with the `enable-tray` option. Or on runtime with the bar config option `tray_output none`. Overview of changes: In swaybar very little is changed outside the tray subfolder except that all events are now polled in `event_loop.c`, this creates no functional difference. Six bar configuration options were added, these are detailed in sway-bar(5) The tray subfolder is where all protocol implementation takes place and is organised as follows: tray/sni_watcher.c: This file contains the StatusNotifierWatcher. It keeps track of items and hosts and reports when they come or go. tray/tray.c This file contains the StatusNotifierHost. It keeps track of sway's version of the items and represents the tray itself. tray/sni.c This file contains the StatusNotifierItem struct and all communication with individual items. tray/icon.c This file implements the icon theme protocol. It allows for finding icons by name, rather than by pixmap. tray/dbus.c This file allows for asynchronous DBus communication. See #986 #343 --- CMake/FindDBus.cmake | 59 ++++ CMakeLists.txt | 13 + include/client/cairo.h | 2 + include/sway/commands.h | 4 + include/sway/config.h | 12 +- include/swaybar/bar.h | 6 + include/swaybar/config.h | 11 + include/swaybar/event_loop.h | 26 ++ include/swaybar/tray/dbus.h | 18 + include/swaybar/tray/icon.h | 16 + include/swaybar/tray/sni.h | 81 +++++ include/swaybar/tray/sni_watcher.h | 10 + include/swaybar/tray/tray.h | 26 ++ sway/commands.c | 4 + sway/commands/bar/activate_button.c | 26 ++ sway/commands/bar/context_button.c | 26 ++ sway/commands/bar/icon_theme.c | 25 ++ sway/commands/bar/secondary_button.c | 26 ++ sway/commands/bar/tray_output.c | 26 +- sway/commands/bar/tray_padding.c | 34 +- sway/config.c | 11 + sway/ipc-json.c | 17 +- sway/sway-bar.5.txt | 36 ++ swaybar/CMakeLists.txt | 11 + swaybar/bar.c | 135 ++++++-- swaybar/config.c | 12 + swaybar/event_loop.c | 143 ++++++++ swaybar/ipc.c | 40 ++- swaybar/render.c | 75 ++++- swaybar/tray/dbus.c | 189 +++++++++++ swaybar/tray/icon.c | 404 ++++++++++++++++++++++ swaybar/tray/sni.c | 463 +++++++++++++++++++++++++ swaybar/tray/sni_watcher.c | 487 +++++++++++++++++++++++++++ swaybar/tray/tray.c | 279 +++++++++++++++ wayland/cairo.c | 19 ++ 35 files changed, 2714 insertions(+), 58 deletions(-) create mode 100644 CMake/FindDBus.cmake create mode 100644 include/swaybar/event_loop.h create mode 100644 include/swaybar/tray/dbus.h create mode 100644 include/swaybar/tray/icon.h create mode 100644 include/swaybar/tray/sni.h create mode 100644 include/swaybar/tray/sni_watcher.h create mode 100644 include/swaybar/tray/tray.h create mode 100644 sway/commands/bar/activate_button.c create mode 100644 sway/commands/bar/context_button.c create mode 100644 sway/commands/bar/icon_theme.c create mode 100644 sway/commands/bar/secondary_button.c create mode 100644 swaybar/event_loop.c create mode 100644 swaybar/tray/dbus.c create mode 100644 swaybar/tray/icon.c create mode 100644 swaybar/tray/sni.c create mode 100644 swaybar/tray/sni_watcher.c create mode 100644 swaybar/tray/tray.c diff --git a/CMake/FindDBus.cmake b/CMake/FindDBus.cmake new file mode 100644 index 000000000..4a1a18056 --- /dev/null +++ b/CMake/FindDBus.cmake @@ -0,0 +1,59 @@ +# - Try to find DBus +# Once done, this will define +# +# DBUS_FOUND - system has DBus +# DBUS_INCLUDE_DIRS - the DBus include directories +# DBUS_LIBRARIES - link these to use DBus +# +# Copyright (C) 2012 Raphael Kubo da Costa +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS +# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FIND_PACKAGE(PkgConfig) +PKG_CHECK_MODULES(PC_DBUS QUIET dbus-1) + +FIND_LIBRARY(DBUS_LIBRARIES + NAMES dbus-1 + HINTS ${PC_DBUS_LIBDIR} + ${PC_DBUS_LIBRARY_DIRS} +) + +FIND_PATH(DBUS_INCLUDE_DIR + NAMES dbus/dbus.h + HINTS ${PC_DBUS_INCLUDEDIR} + ${PC_DBUS_INCLUDE_DIRS} +) + +GET_FILENAME_COMPONENT(_DBUS_LIBRARY_DIR ${DBUS_LIBRARIES} PATH) +FIND_PATH(DBUS_ARCH_INCLUDE_DIR + NAMES dbus/dbus-arch-deps.h + HINTS ${PC_DBUS_INCLUDEDIR} + ${PC_DBUS_INCLUDE_DIRS} + ${_DBUS_LIBRARY_DIR} + ${DBUS_INCLUDE_DIR} + PATH_SUFFIXES include +) + +SET(DBUS_INCLUDE_DIRS ${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR}) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(DBUS REQUIRED_VARS DBUS_INCLUDE_DIRS DBUS_LIBRARIES) diff --git a/CMakeLists.txt b/CMakeLists.txt index edf486ca7..c80f63613 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ option(enable-swaybar "Enables the swaybar utility" YES) option(enable-swaygrab "Enables the swaygrab utility" YES) option(enable-swaymsg "Enables the swaymsg utility" YES) option(enable-gdk-pixbuf "Use Pixbuf to support more image formats" YES) +option(enable-tray "Enables the swaybar tray" YES) option(zsh-completions "Zsh shell completions" NO) option(default-wallpaper "Installs the default wallpaper" YES) option(LD_LIBRARY_PATH "Configure sway's default LD_LIBRARY_PATH") @@ -64,6 +65,7 @@ find_package(Cairo REQUIRED) find_package(Pango REQUIRED) find_package(GdkPixbuf) find_package(PAM) +find_package(DBus) find_package(LibInput REQUIRED) @@ -90,6 +92,17 @@ else() message(STATUS "Building without gdk-pixbuf, only png images supported.") endif() +if (enable-tray) + if (DBUS_FOUND) + set(ENABLE_TRAY) + add_definitions(-DENABLE_TRAY) + else() + message(WARNING "Tray required but DBus was not found. Tray will not be included") + endif() +else() + message(STATUS "Building without the tray.") +endif() + include_directories(include) add_subdirectory(protocols) diff --git a/include/client/cairo.h b/include/client/cairo.h index 46c53566d..e7ef7c7e5 100644 --- a/include/client/cairo.h +++ b/include/client/cairo.h @@ -6,6 +6,8 @@ void cairo_set_source_u32(cairo_t *cairo, uint32_t color); +cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, int width, int height); + #ifdef WITH_GDK_PIXBUF #include diff --git a/include/sway/commands.h b/include/sway/commands.h index 078652e70..f67df10fc 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -157,17 +157,21 @@ sway_cmd cmd_workspace; sway_cmd cmd_ws_auto_back_and_forth; sway_cmd cmd_workspace_layout; +sway_cmd bar_cmd_activate_button; sway_cmd bar_cmd_binding_mode_indicator; sway_cmd bar_cmd_bindsym; sway_cmd bar_cmd_colors; +sway_cmd bar_cmd_context_button; sway_cmd bar_cmd_font; sway_cmd bar_cmd_mode; sway_cmd bar_cmd_modifier; sway_cmd bar_cmd_output; sway_cmd bar_cmd_height; sway_cmd bar_cmd_hidden_state; +sway_cmd bar_cmd_icon_theme; sway_cmd bar_cmd_id; sway_cmd bar_cmd_position; +sway_cmd bar_cmd_secondary_button; sway_cmd bar_cmd_separator_symbol; sway_cmd bar_cmd_status_command; sway_cmd bar_cmd_pango_markup; diff --git a/include/sway/config.h b/include/sway/config.h index 35f8d5f7e..999a471a0 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -133,7 +133,17 @@ struct bar_config { char *swaybar_command; char *font; int height; // -1 not defined - int tray_padding; + +#ifdef ENABLE_TRAY + // Tray + char *tray_output; + char *icon_theme; + uint32_t tray_padding; + uint32_t activate_button; + uint32_t context_button; + uint32_t secondary_button; +#endif + bool workspace_buttons; bool wrap_scroll; char *separator_symbol; diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 697a48c2b..010e1f84c 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -21,6 +21,9 @@ struct output { struct window *window; struct registry *registry; list_t *workspaces; +#ifdef ENABLE_TRAY + list_t *items; +#endif char *name; int idx; bool focused; @@ -37,6 +40,9 @@ struct workspace { /** Global bar state */ extern struct bar swaybar; +/** True if sway needs to render */ +extern bool dirty; + /** * Setup bar. */ diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 04b12cd4b..651f0ee3f 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -33,6 +33,17 @@ struct config { bool all_outputs; list_t *outputs; +#ifdef ENABLE_TRAY + // Tray + char *tray_output; + char *icon_theme; + + uint32_t tray_padding; + uint32_t activate_button; + uint32_t context_button; + uint32_t secondary_button; +#endif + int height; struct { diff --git a/include/swaybar/event_loop.h b/include/swaybar/event_loop.h new file mode 100644 index 000000000..a0cde07fe --- /dev/null +++ b/include/swaybar/event_loop.h @@ -0,0 +1,26 @@ +#ifndef _SWAYBAR_EVENT_LOOP_H +#define _SWAYBAR_EVENT_LOOP_H + +#include +#include + +void add_event(int fd, short mask, + void(*cb)(int fd, short mask, void *data), + void *data); + +// Not guaranteed to notify cb immediately +void add_timer(timer_t timer, + void(*cb)(timer_t timer, void *data), + void *data); + +// Returns false if nothing exists, true otherwise +bool remove_event(int fd); + +// Returns false if nothing exists, true otherwise +bool remove_timer(timer_t timer); + +// Blocks and returns after sending callbacks +void event_loop_poll(); + +void init_event_loop(); +#endif /*_SWAYBAR_EVENT_LOOP_H */ diff --git a/include/swaybar/tray/dbus.h b/include/swaybar/tray/dbus.h new file mode 100644 index 000000000..eb9cfea70 --- /dev/null +++ b/include/swaybar/tray/dbus.h @@ -0,0 +1,18 @@ +#ifndef _SWAYBAR_DBUS_H +#define _SWAYBAR_DBUS_H + +#include +#include +extern DBusConnection *conn; + +/** + * Should be called in main loop to dispatch events + */ +void dispatch_dbus(); + +/** + * Initializes async dbus communication + */ +int dbus_init(); + +#endif /* _SWAYBAR_DBUS_H */ diff --git a/include/swaybar/tray/icon.h b/include/swaybar/tray/icon.h new file mode 100644 index 000000000..1cc6ff9c1 --- /dev/null +++ b/include/swaybar/tray/icon.h @@ -0,0 +1,16 @@ +#ifndef _SWAYBAR_ICON_H +#define _SWAYBAR_ICON_H + +#include +#include +#include + +/** + * Returns the image found by `name` that is closest to `size` + */ +cairo_surface_t *find_icon(const char *name, int size); + +/* Struct used internally only */ +struct subdir; + +#endif /* _SWAYBAR_ICON_H */ diff --git a/include/swaybar/tray/sni.h b/include/swaybar/tray/sni.h new file mode 100644 index 000000000..83809b2d4 --- /dev/null +++ b/include/swaybar/tray/sni.h @@ -0,0 +1,81 @@ +#ifndef _SWAYBAR_SNI_H +#define _SWAYBAR_SNI_H + +#include +#include + +struct StatusNotifierItem { + /* Name registered to sni watcher */ + char *name; + /* Unique bus name, needed for determining signal origins */ + char *unique_name; + bool kde_special_snowflake; + + cairo_surface_t *image; + bool dirty; +}; + +/* Each output holds an sni_icon_ref of each item to render */ +struct sni_icon_ref { + cairo_surface_t *icon; + struct StatusNotifierItem *ref; +}; + +struct sni_icon_ref *sni_icon_ref_create(struct StatusNotifierItem *item, + int height); + +void sni_icon_ref_free(struct sni_icon_ref *sni_ref); + +/** + * Will return a new item and get its icon. (see warning below) + */ +struct StatusNotifierItem *sni_create(const char *name); + +/** + * `item` must be a struct StatusNotifierItem * + * `str` must be a NUL terminated char * + * + * Returns 0 if `item` has a name of `str` + */ +int sni_str_cmp(const void *item, const void *str); + +/** + * Returns 0 if `item` has a unique name of `str` or if + * `item->unique_name == NULL` + */ +int sni_uniq_cmp(const void *item, const void *str); + +/** + * Gets an icon for the given item if found. + * + * XXX + * This function keeps a reference to the item until it gets responses, make + * sure that the reference and item are valid during this time. + */ +void get_icon(struct StatusNotifierItem *item); + +/** + * Calls the "activate" method on the given StatusNotifierItem + * + * x and y should be where the item was clicked + */ +void sni_activate(struct StatusNotifierItem *item, uint32_t x, uint32_t y); + +/** + * Asks the item to draw a context menu at the given x and y coords + */ +void sni_context_menu(struct StatusNotifierItem *item, uint32_t x, uint32_t y); + +/** + * Calls the "secondary activate" method on the given StatusNotifierItem + * + * x and y should be where the item was clicked + */ +void sni_secondary(struct StatusNotifierItem *item, uint32_t x, uint32_t y); + +/** + * Deconstructs `item` + */ +void sni_free(struct StatusNotifierItem *item); + +#endif /* _SWAYBAR_SNI_H */ diff --git a/include/swaybar/tray/sni_watcher.h b/include/swaybar/tray/sni_watcher.h new file mode 100644 index 000000000..25ddfcd29 --- /dev/null +++ b/include/swaybar/tray/sni_watcher.h @@ -0,0 +1,10 @@ +#ifndef _SWAYBAR_SNI_WATCHER_H +#define _SWAYBAR_SNI_WATCHER_H + +/** + * Starts the sni_watcher, the watcher is practically a black box and should + * only be accessed though functions described in its spec + */ +int init_sni_watcher(); + +#endif /* _SWAYBAR_SNI_WATCHER_H */ diff --git a/include/swaybar/tray/tray.h b/include/swaybar/tray/tray.h new file mode 100644 index 000000000..7d371008f --- /dev/null +++ b/include/swaybar/tray/tray.h @@ -0,0 +1,26 @@ +#ifndef _SWAYBAR_TRAY_H +#define _SWAYBAR_TRAY_H + +#include +#include +#include "swaybar/tray/dbus.h" +#include "swaybar/tray/sni.h" +#include "list.h" + +extern struct tray *tray; + +struct tray { + list_t *items; +}; + +/** + * Initializes the tray host with D-Bus + */ +int init_tray(); + +/** + * Returns an item if `x` and `y` collide with it and NULL otherwise + */ +struct StatusNotifierItem *collides_with_sni(int x, int y); + +#endif /* _SWAYBAR_TRAY_H */ diff --git a/sway/commands.c b/sway/commands.c index 342184914..f83b52878 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -221,18 +221,22 @@ static struct cmd_handler handlers[] = { }; static struct cmd_handler bar_handlers[] = { + { "activate_button", bar_cmd_activate_button }, { "binding_mode_indicator", bar_cmd_binding_mode_indicator }, { "bindsym", bar_cmd_bindsym }, { "colors", bar_cmd_colors }, + { "context_button", bar_cmd_context_button }, { "font", bar_cmd_font }, { "height", bar_cmd_height }, { "hidden_state", bar_cmd_hidden_state }, + { "icon_theme", bar_cmd_icon_theme }, { "id", bar_cmd_id }, { "mode", bar_cmd_mode }, { "modifier", bar_cmd_modifier }, { "output", bar_cmd_output }, { "pango_markup", bar_cmd_pango_markup }, { "position", bar_cmd_position }, + { "secondary_button", bar_cmd_secondary_button }, { "separator_symbol", bar_cmd_separator_symbol }, { "status_command", bar_cmd_status_command }, { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, diff --git a/sway/commands/bar/activate_button.c b/sway/commands/bar/activate_button.c new file mode 100644 index 000000000..32a1d3e51 --- /dev/null +++ b/sway/commands/bar/activate_button.c @@ -0,0 +1,26 @@ +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_activate_button(int argc, char **argv) { + const char *cmd_name = "activate_button"; +#ifndef ENABLE_TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " + "%s called, but sway was compiled without tray support", + cmd_name, cmd_name); +#else + struct cmd_results *error = NULL; + if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); + } + + // User should be able to prefix with 0x or whatever they want + config->current_bar->secondary_button = strtoul(argv[0], NULL, 0); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +#endif +} diff --git a/sway/commands/bar/context_button.c b/sway/commands/bar/context_button.c new file mode 100644 index 000000000..6d7d7aecc --- /dev/null +++ b/sway/commands/bar/context_button.c @@ -0,0 +1,26 @@ +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_context_button(int argc, char **argv) { + const char *cmd_name = "context_button"; +#ifndef ENABLE_TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " + "%s called, but sway was compiled without tray support", + cmd_name, cmd_name); +#else + struct cmd_results *error = NULL; + if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); + } + + // User should be able to prefix with 0x or whatever they want + config->current_bar->context_button = strtoul(argv[0], NULL, 0); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +#endif +} diff --git a/sway/commands/bar/icon_theme.c b/sway/commands/bar/icon_theme.c new file mode 100644 index 000000000..cbfc0be50 --- /dev/null +++ b/sway/commands/bar/icon_theme.c @@ -0,0 +1,25 @@ +#define _XOPEN_SOURCE 500 +#include +#include "sway/commands.h" + +struct cmd_results *bar_cmd_icon_theme(int argc, char **argv) { + const char *cmd_name = "tray_output"; +#ifndef ENABLE_TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " + "%s called, but sway was compiled without tray support", + cmd_name, cmd_name); +#else + struct cmd_results *error = NULL; + if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); + } + + config->current_bar->icon_theme = strdup(argv[0]); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +#endif +} diff --git a/sway/commands/bar/secondary_button.c b/sway/commands/bar/secondary_button.c new file mode 100644 index 000000000..745045c5a --- /dev/null +++ b/sway/commands/bar/secondary_button.c @@ -0,0 +1,26 @@ +#include +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_secondary_button(int argc, char **argv) { + const char *cmd_name = "secondary_button"; +#ifndef ENABLE_TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " + "%s called, but sway was compiled without tray support", + cmd_name, cmd_name); +#else + struct cmd_results *error = NULL; + if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); + } + + // User should be able to prefix with 0x or whatever they want + config->current_bar->secondary_button = strtoul(argv[0], NULL, 0); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +#endif +} diff --git a/sway/commands/bar/tray_output.c b/sway/commands/bar/tray_output.c index 8a1b5d35b..012304a96 100644 --- a/sway/commands/bar/tray_output.c +++ b/sway/commands/bar/tray_output.c @@ -1,7 +1,29 @@ +#define _XOPEN_SOURCE 500 +#include #include "sway/commands.h" -#include "log.h" struct cmd_results *bar_cmd_tray_output(int argc, char **argv) { - sway_log(L_ERROR, "Warning: tray_output is not supported on wayland"); + const char *cmd_name = "tray_output"; +#ifndef ENABLE_TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command " + "%s called, but sway was compiled without tray support", + cmd_name, cmd_name); +#else + struct cmd_results *error = NULL; + if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); + } + + if (strcmp(argv[0], "all") == 0) { + // Default behaviour + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + config->current_bar->tray_output = strdup(argv[0]); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +#endif } diff --git a/sway/commands/bar/tray_padding.c b/sway/commands/bar/tray_padding.c index 8c559f653..ac0572cec 100644 --- a/sway/commands/bar/tray_padding.c +++ b/sway/commands/bar/tray_padding.c @@ -1,30 +1,34 @@ #include -#include #include #include "sway/commands.h" #include "log.h" struct cmd_results *bar_cmd_tray_padding(int argc, char **argv) { + const char *cmd_name = "tray_padding"; +#ifndef ENABLE_TRAY + return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command" + "%s called, but sway was compiled without tray support", + cmd_name, cmd_name); +#else struct cmd_results *error = NULL; - if ((error = checkarg(argc, "tray_padding", EXPECTED_AT_LEAST, 1))) { + if ((error = checkarg(argc, cmd_name, EXPECTED_AT_LEAST, 1))) { return error; } if (!config->current_bar) { - return cmd_results_new(CMD_FAILURE, "tray_padding", "No bar defined."); + return cmd_results_new(CMD_FAILURE, cmd_name, "No bar defined."); } - int padding = atoi(argv[0]); - if (padding < 0) { - return cmd_results_new(CMD_INVALID, "tray_padding", - "Invalid padding value %s, minimum is 0", argv[0]); + if (argc == 1 || (argc == 2 && strcasecmp("px", argv[1]) == 0)) { + char *inv; + uint32_t padding = strtoul(argv[0], &inv, 10); + if (*inv == '\0' || strcasecmp(inv, "px") == 0) { + config->current_bar->tray_padding = padding; + sway_log(L_DEBUG, "Enabling tray padding of %d px on bar: %s", padding, config->current_bar->id); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } } - - if (argc > 1 && strcasecmp("px", argv[1]) != 0) { - return cmd_results_new(CMD_INVALID, "tray_padding", - "Unknown unit %s", argv[1]); - } - config->current_bar->tray_padding = padding; - sway_log(L_DEBUG, "Enabling tray padding of %d px on bar: %s", padding, config->current_bar->id); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); + return cmd_results_new(CMD_FAILURE, cmd_name, + "Expected 'tray_padding [px]'"); +#endif } diff --git a/sway/config.c b/sway/config.c index 85823953c..e0b656153 100644 --- a/sway/config.c +++ b/sway/config.c @@ -69,6 +69,10 @@ static void free_bar(struct bar_config *bar) { } free(bar->mode); free(bar->hidden_state); +#ifdef ENABLE_TRAY + free(bar->tray_output); + free(bar->icon_theme); +#endif free(bar->status_command); free(bar->font); free(bar->separator_symbol); @@ -1386,7 +1390,14 @@ struct bar_config *default_bar_config(void) { bar->separator_symbol = NULL; bar->strip_workspace_numbers = false; bar->binding_mode_indicator = true; +#ifdef ENABLE_TRAY + bar->tray_output = NULL; + bar->icon_theme = NULL; bar->tray_padding = 2; + bar->activate_button = 0x110; /* BTN_LEFT */ + bar->context_button = 0x111; /* BTN_RIGHT */ + bar->secondary_button = 0x112; /* BTN_MIDDLE */ +#endif bar->verbose = false; bar->pid = 0; // set default colors diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 512144a4a..31de53f0d 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -327,7 +327,22 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object *json = json_object_new_object(); json_object_object_add(json, "id", json_object_new_string(bar->id)); - json_object_object_add(json, "tray_output", NULL); +#ifdef ENABLE_TRAY + if (bar->tray_output) { + json_object_object_add(json, "tray_output", json_object_new_string(bar->tray_output)); + } else { + json_object_object_add(json, "tray_output", NULL); + } + if (bar->icon_theme) { + json_object_object_add(json, "icon_theme", json_object_new_string(bar->icon_theme)); + } else { + json_object_object_add(json, "icon_theme", NULL); + } + json_object_object_add(json, "tray_padding", json_object_new_int(bar->tray_padding)); + json_object_object_add(json, "activate_button", json_object_new_int(bar->activate_button)); + json_object_object_add(json, "context_button", json_object_new_int(bar->context_button)); + json_object_object_add(json, "secondary_button", json_object_new_int(bar->secondary_button)); +#endif json_object_object_add(json, "mode", json_object_new_string(bar->mode)); json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state)); json_object_object_add(json, "modifier", json_object_new_string(get_modifier_name_by_mask(bar->modifier))); diff --git a/sway/sway-bar.5.txt b/sway/sway-bar.5.txt index 5a52e7db6..294876624 100644 --- a/sway/sway-bar.5.txt +++ b/sway/sway-bar.5.txt @@ -65,6 +65,42 @@ Commands **height** :: Sets the height of the bar. Default height will match the font size. +Tray +---- + +Swaybar provides a system tray where programs such as NetworkManager, VLC, +Pidgin, etc. can place little icons. The following commands configure +interaction with the tray or individual icons. +The _button_ argument in all following commands is a Linux input event code as +defined in linux/input-event-codes.h. This is because wayland defines button +codes in this manner. + +**activate_button**